1 #include "config.h"
2 
3 #ifdef SOUND
4 
5 #if defined(HAVE_SDL)
6 #include "SDL.h"
7 #include "SDL_mixer.h"
8 #endif
9 
10 #include "copyright.h"
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include <time.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include INC_LIMITS
21 #include INC_SYS_TIME
22 
23 #if defined(sgi)
24 #include <unistd.h>
25 #include <string.h>
26 #include <math.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <sys/types.h>
30 #include <sys/prctl.h>
31 #include <invent.h>
32 #include <dmedia/audio.h>
33 #include <dmedia/audiofile.h>
34 #include <signal.h>
35 #include <stropts.h>
36 #include <poll.h>
37 #include "sgi-sound.h"
38 #endif
39 
40 #include "Wlib.h"
41 #include "defs.h"
42 #include "struct.h"
43 #include "data.h"
44 #include "audio.h"
45 
46 #if defined(HAVE_SDL) || defined(sgi)
47 enum {
48   INTRO_WAV,			/*  0 */
49   FIRE_TORP_WAV,		/*  1 */
50   PHASER_WAV,			/*  2 */
51   FIRE_PLASMA_WAV,		/*  3 */
52   EXPLOSION_WAV,		/*  4 */
53   SBEXPLOSION_WAV,		/*  5 */
54   CLOAK_WAV,			/*  6 */
55   UNCLOAK_WAV,			/*  7 */
56   SHIELD_DOWN_WAV,		/*  8 */
57   SHIELD_UP_WAV,		/*  9 */
58   TORP_HIT_WAV,			/* 10 */
59   REDALERT_WAV,			/* 11 */
60   BUZZER_WAV,			/* 12 */
61   ENTER_SHIP_WAV,		/* 13 */
62   SELF_DESTRUCT_WAV,		/* 14 */
63   PLASMA_HIT_WAV,		/* 15 */
64   MESSAGE_WAV,			/* 16 */
65   ENGINE_WAV,			/* 17 */
66   THERMAL_WAV,			/* 18 */
67   FIRE_TORP_OTHER_WAV,		/* 19 */
68   PHASER_OTHER_WAV,		/* 20 */
69   FIRE_PLASMA_OTHER_WAV,	/* 21 */
70   EXPLOSION_OTHER_WAV,		/* 22 */
71   SBEXPLOSION_OTHER_WAV,	/* 23 */
72   NUM_WAVES			/* 24 */
73 };
74 #endif
75 
76 #if defined(HAVE_SDL)
77 /* This is probably unix specific paths */
78 static Mix_Chunk *sounds[NUM_WAVES];
79 #endif
80 
81 #if defined(sgi)
82 static ALport sfxInitAudioPort(int init);
83 static short *sfxLoadAudioFile(char *dirName, char *fileName, AFframecount *size);
84 static int sfxCheckForAudio(void);
85 static int sfxOpenAudioPorts(ALport ports[], int maxAudioPorts);
86 static void sfxCheckVolume(void);
87 static void sfxResetAudioHw(void);
88 static void sfxSetGain(float l, float r);
89 static void sfxSetGainIndex(unsigned long gain);
90 static void sfxSignalSound(Sfx sp);
91 static void sfxDieGracefully(int sig);
92 static void sfxSoundDied(int sig);
93 static void sfxSoundErrFunc(long err, const char *msg, ...);
94 static void sfxSoundHandler(void *arg);
95 
96 static Sfx sounds[NUM_WAVES];			/* waveform storage */
97 static ALport audioPort[MAX_AUDIO_PORTS];	/* audio port structure */
98 static int nAudioPorts;				/* number of audio ports */
99 static int soundOther = 1;			/* sound toggle for other ships */
100 static int soundChild;				/* set if child process is running */
101 static int gainIndex;				/* current gain index */
102 static int endingOnPurpose = 0;			/* set if sound should end on purpose */
103 static int spigot[2];				/* pipe to the child process */
104 static int soundId = 0;				/* ID of current sound */
105 static char *sfxAudioDir;			/* directory with sound files */
106 static unsigned long origLeftGain;		/* initial gain setting for left channel */
107 static unsigned long origRightGain;		/* initial gain setting for right channel */
108 static unsigned long origOutputRate;		/* initial output sample rate */
109 static unsigned long currLeftGain;		/* current gain setting for left channel */
110 static unsigned long currRightGain;		/* current gain setting for right channel */
111 static unsigned long gainSettings[] = { 0, 2, 3, 5, 9, 16, 29, 50, 91, 156, 255 };
112 #endif
113 
114 #if !defined(HAVE_SDL) && !defined(sgi)
115 
116 /* Each sound has a priority which controls what can override what
117  * Currently these are set as follows:
118  *
119  * 10: explosion
120  * 9: phaser,plasma
121  * 8: torp/plasma hit
122  * 7: torp fire, cloak
123  * 6: alert
124  * 4: "informational" sounds (self destruct, enter ship, message, etc.)
125  * 3: shield up/down, other people's sounds (phaser, torp, plasma, explode)
126  * 0: background or ambient (engine?)
127  */
128 static struct Sound sounds[NUM_SOUNDS+1] = {
129 	{"", 0, 0},
130 	{"nt_fire_torp", 7, 1},
131 	{"nt_phaser", 9, 1},
132 	{"nt_fire_plasma", 9, 1},
133 	{"nt_explosion", 10, 1},
134 	{"nt_cloaked", 7, 1},
135 	{"nt_uncloak", 7, 1},
136 	{"nt_shield_down", 3, 1},
137 	{"nt_shield_up", 3, 1},
138 	{"nt_torp_hit", 8, 1},
139 	{"nt_warning", 5, 1},
140 	{"nt_engine", 0, 0},
141 	{"nt_enter_ship", 4, 1},
142 	{"nt_self_destruct", 6, 1},
143 	{"nt_plasma_hit", 8, 1},
144 	{"nt_message", 4, 1},
145 	{"nt_message1", 4, 1},
146 	{"nt_message2", 4, 1},
147 	{"nt_message3", 4, 1},
148 	{"nt_message4", 4, 1},
149 	{"nt_message5", 4, 1},
150 	{"nt_message6", 4, 1},
151 	{"nt_message7", 4, 1},
152 	{"nt_message8", 4, 1},
153 	{"nt_message9", 4, 1},
154 	{"nt_fire_torp_other", 3, 1},
155 	{"nt_phaser_other", 3, 1},
156 	{"nt_fire_plasma_other", 3, 1},
157 	{"nt_explosion_other", 10, 1}
158 };
159 
160 static char sound_prefix[PATH_MAX];
161 static int current_sound = NO_SOUND;
162 static int soundOther = 1;		 /* play other ship's sounds?  */
163 
164 #endif /* HAVE_SDL */
165 
isDirectory(char * dir)166 static int isDirectory(char* dir) {	/* check wheter `dir' is a directory */
167 	struct stat buf;
168 
169 	if (stat(dir, &buf) < 0) {
170 		return 0;
171 	}
172 	return S_ISDIR(buf.st_mode);
173 }
174 
175 #if defined(sgi)
176 
177 /*
178  * Initialize the audio hardware.
179  */
sfxInit(char * audioDir,int numPorts)180 int sfxInit(char *audioDir, int numPorts) {
181 	int idx;
182 	char *str;
183 
184 	if (audioDir != NULL) {
185 		str = strdup(audioDir);
186 		if (str)
187 			sfxAudioDir = str;
188 	}
189 	if (numPorts < 1)
190 		return SFX_ERR_NO_PORTS_AVAIL;
191 
192 	if (numPorts > MAX_AUDIO_PORTS)
193 		numPorts = MAX_AUDIO_PORTS;
194 
195 	(void) ALseterrorhandler(sfxSoundErrFunc);
196 
197 	nAudioPorts = sfxOpenAudioPorts(audioPort, numPorts);
198 
199 	if (nAudioPorts == 0)
200 		return SFX_ERR_NO_PORTS_AVAIL;
201 
202 	if (nAudioPorts < 0)
203 		return SFX_ERR_NO_AUDIO_HW;
204 
205 	(void) signal(SIGCHLD, sfxSoundDied);
206 
207 	if (pipe(spigot) < 0 || (soundChild = sproc(sfxSoundHandler, PR_SADDR, audioPort)) < 0) {
208 		for (idx=0; idx < nAudioPorts; idx++)
209 			ALcloseport(audioPort[idx]);
210 
211 		return SFX_ERR_NO_SPROC;
212 	}
213 	return nAudioPorts;
214 }
215 
216 /*
217  * Load an audio file.
218  */
sfxLoad(char * filename)219 Sfx sfxLoad(char *filename) {
220 	Sfx sp;
221 
222 	if ((sp=(Sfx)malloc(sizeof(struct _sfx))) == NULL)
223 		return NULL;
224 
225 	sp->soundData = NULL;
226 	sp->soundSize = NULL;
227 	sp->loop = 0;
228 	sp->repeat = 0;
229 	sp->count = 1;
230 	sp->pitch = 0;
231 	sp->enabled = 1;
232 
233 	if ((sp->soundData=(short **)malloc(sizeof(short *))) == NULL) {
234 		sfxFree(sp);
235 		return NULL;
236 	}
237 	if ((sp->soundSize=(AFframecount *)malloc(sizeof(AFframecount))) == NULL) {
238 		sfxFree(sp);
239 		return NULL;
240 	}
241 	if ((sp->soundData[0] = sfxLoadAudioFile(sfxAudioDir, filename, &(sp->soundSize[0]))) == NULL) {
242 		sfxFree(sp);
243 		return NULL;
244 	}
245 	sp->id = soundId++;
246 	return sp;
247 }
248 
249 /*
250  * Indicate that a sound is to loop.
251  */
sfxLoop(Sfx sp)252 void sfxLoop(Sfx sp) {
253 	if (sp != NULL)
254 		sp->loop = 1;
255 	return;
256 }
257 
258 /*
259  * Play a sound effect.
260  */
sfxPlay(Sfx sp)261 void sfxPlay(Sfx sp) {
262 	if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
263 		if (sp->loop)
264 			sp->repeat = 1;
265 
266 		sfxCheckVolume();
267 		sfxSignalSound(sp);
268 	}
269 	return;
270 }
271 
272 /*
273  * Play a pitch-bent audio clip.
274  */
sfxPlayPitch(Sfx sp,float val)275 void sfxPlayPitch(Sfx sp, float val) {
276 	int i;
277 
278 	if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
279 		if (val <= sp->loVal)
280 			i = 0;
281 		else if (val >= sp->hiVal)
282 			i = sp->count-1;
283 		else
284 			i = (long)(0.4f + (sp->count - 1) *
285 				   (val - sp->loVal)/(sp->hiVal - sp->loVal));
286 
287 		if (sp->loop && sp->repeat && sp->pitch == i)
288                         return;
289 
290 		sp->pitch = i;
291 		sfxPlay(sp);
292 	}
293 	return;
294 }
295 
296 /*
297  * Create a pitch bend audio clip.
298  */
sfxPitchBend(Sfx sp,float startVal,float endVal,float startPitch,float endPitch,float basePitch,int steps)299 void sfxPitchBend(Sfx sp, float startVal, float endVal,
300 			  float startPitch, float endPitch,
301 			  float basePitch, int steps) {
302 	int	i, k;
303 	int	size;
304 	short	**ptr;
305 	short	*data;
306 	short	*origData;
307 	double	pitch;
308 	double	a, b;
309 	long	frameIndex;
310 	AFframecount *lptr;
311 
312 	if (sp == NULL || steps < 2 || sp->count != 1)
313 		return;
314 
315 	if ((lptr=(AFframecount *)malloc(steps * sizeof(AFframecount))) == NULL)
316 		return;
317 
318 	size = 0;
319 	a = (endPitch - startPitch) / (double)(steps - 1);
320 	b = 1.0 / (double)basePitch;
321 
322 	for (i=0; i < steps; i++) {
323 		pitch = (startPitch + (double)i * a) * b;
324 		k = (long)((double)sp->soundSize[0] / pitch);
325 		lptr[i] = k;
326 		size += k;
327 	}
328 	if ((ptr=(short **)malloc(steps * sizeof(short *))) == NULL) {
329 		free(lptr);
330 		return;
331 	}
332 
333 	/*
334 	 * Allocate new space for pitch-bent sound data.
335 	 */
336 	if ((data=(short *)malloc(size * 2 * sizeof(short))) == NULL) {
337 		free(lptr);
338 		free(ptr);
339 		return;
340 	}
341 
342 	size = (int)sp->soundSize[0];
343 	free(sp->soundSize);
344 	sp->soundSize = lptr;
345 
346 	origData = sp->soundData[0];
347 	free(sp->soundData);
348 	sp->soundData = ptr;
349 
350 	sp->count = steps;
351 	sp->loVal = startVal;
352 	sp->hiVal = endVal;
353 
354 	for (i=0; i < steps; i++) {
355 		pitch = (startPitch + (double)i * a) * b;
356 
357 		if (i == 0)
358 			sp->soundData[i] = data;
359 		else
360 			sp->soundData[i] = sp->soundData[i-1] + 2 * sp->soundSize[i-1];
361 
362 		for (k=0; k < sp->soundSize[i]; k++) {
363 			frameIndex = (long)(k * pitch + 0.5);
364 			if (frameIndex >= size)
365 				frameIndex = size - 1;
366 
367 			sp->soundData[i][2*k  ] = origData[2*frameIndex	 ];
368 			sp->soundData[i][2*k+1] = origData[2*frameIndex+1];
369 		}
370 	}
371 	free(origData);
372 	return;
373 }
374 
375 /*
376  * Silence an audio loop.
377  */
sfxSilenceLoop(Sfx sp)378 void sfxSilenceLoop(Sfx sp) {
379 	if (sp != NULL && sp->repeat) {
380 		sp->repeat = 0;
381 		sfxSignalSound(sp);
382 	}
383 	return;
384 }
385 
386 /*
387  * Disable a sound clip.
388  */
sfxDisable(Sfx sp)389 void sfxDisable(Sfx sp) {
390 	if (sp != NULL) {
391 		sp->enabled = 0;
392 		if (sp->loop)
393 			sfxSilenceLoop(sp);
394 	}
395 	return;
396 }
397 
398 /*
399  * Enable a sound clip.
400  */
sfxEnable(Sfx sp)401 void sfxEnable(Sfx sp) {
402 	if (sp != NULL)
403 		sp->enabled = 1;
404 	return;
405 }
406 
407 /*
408  * Check whether a sound clip is enabled.
409  */
sfxIsEnabled(Sfx sp)410 int sfxIsEnabled(Sfx sp) {
411 	return (sp != NULL) && sp->enabled;
412 }
413 
414 /*
415  * Set the volume to a specified level.
416  */
sfxSetVolume(int level)417 void sfxSetVolume(int level) {
418 	if (level >= 0 && level < sizeof( gainSettings ) / sizeof( gainSettings[0])) {
419 		gainIndex = level;
420 		currLeftGain = currRightGain = gainSettings[gainIndex];
421 	}
422 	return;
423 }
424 
425 /*
426  * Clean up sound routines.
427  */
sfxEnd(int waitForSounds)428 void sfxEnd(int waitForSounds) {
429 	int idx;
430 
431 	endingOnPurpose = 1;
432 
433 	if (waitForSounds) {		/* wait for sounds to complete */
434 		for (idx=0; idx < nAudioPorts; idx++) {
435 			while (ALgetfilled(audioPort[idx]) > 0)
436 				sginap(1);
437 
438 			ALcloseport(audioPort[idx]);
439 		}
440 	} else if (soundChild > 0)	/* kill childs playing sounds */
441 		kill(soundChild, SIGKILL);
442 
443 	if (nAudioPorts > 0)		/* reset audio subsystem */
444 		sfxResetAudioHw();
445 }
446 
447 /*
448  * Open up the audio ports.
449  */
sfxOpenAudioPorts(ALport ports[],int maxAudioPorts)450 static int sfxOpenAudioPorts(ALport ports[], int maxAudioPorts) {
451 	int n;
452 
453 	if (sfxCheckForAudio() == 0)
454 		return -1;
455 
456 	for (n=0; n < maxAudioPorts; n++)
457 		if ((audioPort[n] = sfxInitAudioPort(n == 0)) == NULL)
458 			break;
459 	return n;
460 }
461 
462 /*
463  * Check for audio hardware.
464  */
sfxCheckForAudio(void)465 static int sfxCheckForAudio(void) {
466 	int st = 0;
467 	inventory_t *base;
468 	inventory_t *inv;
469 
470 	inv = base = getinvent();
471 	while (inv != NULL) {
472 		/*
473 		 * Ok if any type of audio hardware available.
474 		 */
475 		if (inv->inv_class == INV_AUDIO)
476 			st = 1;
477 
478 		inv = getinvent();
479 	}
480 	if( base )
481 		endinvent();
482 
483 	return st;
484 }
485 
486 /*
487  * Open and initialize an audio port.
488  */
sfxInitAudioPort(int init)489 static ALport sfxInitAudioPort(int init) {
490 	ALport ap;
491 	ALconfig audioPortConfig;
492 	long pvbuf[6];
493 
494 	if (init) {
495 		pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
496 		pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
497 		pvbuf[4] = AL_OUTPUT_RATE;
498 		ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 6L);
499 		currLeftGain = origLeftGain = pvbuf[1];
500 		currRightGain = origRightGain = pvbuf[3];
501 		origOutputRate = pvbuf[5];
502 		sfxSetGainIndex((origLeftGain+origRightGain)/2);
503 	}
504 
505 	/*
506 	 * Configure and open audio port.
507 	 */
508 	audioPortConfig = ALnewconfig();
509 	ALsetwidth(audioPortConfig, AL_SAMPLE_16);
510 	ALsetchannels(audioPortConfig, AL_STEREO);
511 	ALsetqueuesize(audioPortConfig, 16000);
512 	ap = ALopenport("spacetrek", "w", audioPortConfig);
513 	ALfreeconfig(audioPortConfig);
514 
515 	return ap;
516 }
517 
518 /*
519  * Reset the audio hardware to where we found it when we started.
520  */
sfxResetAudioHw(void)521 static void sfxResetAudioHw(void) {
522 	long pvbuf[6];
523 
524 	pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
525 	pvbuf[1] = origLeftGain;
526 	pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
527 	pvbuf[3] = origRightGain;
528 	pvbuf[4] = AL_OUTPUT_RATE;
529 	pvbuf[5] = origOutputRate;
530 
531 	ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 6L);
532 	return;
533 }
534 
535 /*
536  * Free the Sfx structure.
537  */
sfxFree(Sfx sp)538 void sfxFree(Sfx sp) {
539 	if (sp) {
540 		if (sp->soundData) {
541 			free(sp->soundData);
542 			sp->soundData = NULL;
543 		}
544 		if (sp->soundSize) {
545 			free(sp->soundSize);
546 			sp->soundSize = NULL;
547 		}
548 		free(sp);
549 	}
550 	return;
551 }
552 
553 /*
554  * Set the gain index.
555  */
sfxSetGainIndex(unsigned long gain)556 static void sfxSetGainIndex(unsigned long gain) {
557 	int idx;
558 	long min = 256;
559 	long diff;
560 
561 	for (idx=0; idx < sizeof(gainSettings) / sizeof(gainSettings[0]); idx++) {
562 		diff = gain - gainSettings[idx];
563 		if (diff < 0)
564 			diff = -diff;
565 
566 		if (diff < min) {
567 			min = diff;
568 			gainIndex = idx;
569 		}
570 	}
571 	return;
572 }
573 
574 /*
575  * Set the volume level.
576  */
sfxSetGain(float l,float r)577 static void sfxSetGain(float l, float r) {
578 	long pvbuf[4];
579 
580 	pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
581 	pvbuf[1] = l * currLeftGain;
582 	pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
583 	pvbuf[3] = r * currRightGain;
584 
585 	ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4L);
586 }
587 
588 /*
589  * Check for external volume changes.
590  */
sfxCheckVolume(void)591 static void sfxCheckVolume(void) {
592 	long pvbuf[6];
593 
594 	/*
595 	 * Check to see if the volume was changed externally.
596 	 */
597 	pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
598 	pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
599 
600 	ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4L);
601 	if (pvbuf[1] != currLeftGain || pvbuf[3] != currRightGain) {
602 		origLeftGain = currLeftGain = pvbuf[1];
603 		origRightGain = currRightGain = pvbuf[3];
604 		sfxSetGainIndex((pvbuf[1] + pvbuf[3]) / 2);
605 	}
606 	return;
607 }
608 
609 /*
610  * Adjust the volume.
611  */
sfxVolumeChange(int direction)612 int sfxVolumeChange(int direction) {
613 	if (sound_init) {
614 		sfxCheckVolume();
615 		if (direction == 1) {
616 			if (gainIndex < sizeof(gainSettings)/sizeof(gainSettings[0])-1)
617 				gainIndex++;
618 
619 		} else if (gainIndex > 0)
620 			gainIndex--;
621 
622 		currLeftGain = currRightGain = gainSettings[gainIndex];
623 		sfxSetGain(1., 1.);
624 
625 		return gainIndex;
626 	}
627 	return 0;
628 }
629 
630 /*
631  * Wake up the sound handler.
632  */
sfxSignalSound(Sfx sp)633 static void sfxSignalSound(Sfx sp) {
634 	if (soundChild && write(spigot[1], sp, sizeof(*sp)) != sizeof(*sp))
635 		(void) fprintf(stderr, "sfxSignalSound failed: %s\n", strerror(errno));
636 
637 	return;
638 }
639 
640 /*
641  * Audio library error handler.
642  */
sfxSoundErrFunc(long err,const char * msg,...)643 static void sfxSoundErrFunc(long err, const char *msg, ...) { }
644 
645 /*
646  * Handler for sound child dying.
647  */
sfxSoundDied(int sig)648 static void sfxSoundDied(int sig) {
649 	if (!endingOnPurpose) {
650 		nAudioPorts = 0;
651 		sound_init = 0;
652 
653 		(void) fprintf(stderr,
654 				"Sound handling child process was killed by signal %d\n", sig);
655 	}
656 	return;
657 }
658 
659 /*
660  * Exit sound handler on SIGHUP.
661  */
sfxDieGracefully(int sig)662 static void sfxDieGracefully(int sig) {
663 	exit(0);
664 }
665 
666 /*
667  * Sound handler.
668  */
sfxSoundHandler(void * arg)669 static void sfxSoundHandler(void *arg) {
670 	ALport *ap = (ALport *)arg;
671 	Sample samp[MAX_AUDIO_PORTS];
672 
673 	int idx, nap;
674 	int treated;
675 	int nSounds = 1;
676 	int nextPort = 0;
677 	long maxSampsPerPass;
678 	long sampCount;
679 	long pvbuf[2];
680 	struct _sfx ss;
681 	struct pollfd pf;
682 
683 	prctl(PR_TERMCHILD, 0);
684 
685 	(void) signal(SIGHUP, sfxDieGracefully);
686 
687 	maxSampsPerPass = 1600;
688 
689 	for (idx=0; idx < nAudioPorts; idx++) {
690 		samp[idx].id = -1;
691 		samp[idx].sample = NULL;
692 		samp[idx].sampsToPlay = 0;
693 		samp[idx].repeat = 0;
694 	}
695 
696 	/*
697 	 * Set sample rate for output device.
698 	 */
699 	pvbuf[0] = AL_OUTPUT_RATE;
700 	pvbuf[1] = AL_RATE_16000;
701 
702 	(void) ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2L);
703 
704 	/*
705 	 * Prepare to read from pipe.
706 	 */
707 	pf.fd = spigot[0];
708 	pf.events = POLLIN | POLLRDNORM | POLLRDBAND;
709 
710 #define EVER ;;
711 	for (EVER) {
712 		if (nSounds == 0 || (idx=poll(&pf, 1, 0)) > 0) {
713 			(void) read(spigot[0], &ss, sizeof(ss));
714 			treated = 0;
715 			if (ss.loop == 1 && ss.repeat == 0) {
716 				treated = 1;
717 				for (idx=0; idx < nAudioPorts; idx++) {
718 					if (samp[idx].id == ss.id) {
719 						samp[idx].id = -1;
720 						samp[idx].repeat = 0;
721 						samp[idx].sampsToPlay = 0;
722 						samp[idx].sample = NULL;
723 					}
724 				}
725 			} else if (ss.loop == 1 && ss.count > 1) {
726 				for (idx=0; idx < nAudioPorts; idx++) {
727 					if (samp[idx].id == ss.id) {
728 						treated = 1;
729 						samp[idx].repeat = ss.repeat;
730 						samp[idx].sampsToPlay = (long)ss.soundSize[ss.pitch];
731 						samp[idx].sampsPlayed = 0;
732 						samp[idx].sample = ss.soundData[ss.pitch];
733 					}
734 				}
735 			}
736 			if (!treated) {
737 				for (idx=0; idx < nAudioPorts; idx++) {
738 					nextPort = (nextPort+1) % nAudioPorts;
739 					if (samp[nextPort].repeat == 0)
740 						break;
741 				}
742 				samp[nextPort].sample = ss.soundData[ss.pitch];
743 				samp[nextPort].sampsToPlay = (long)ss.soundSize[ss.pitch];
744 				samp[nextPort].sampsPlayed = 0;
745 				samp[nextPort].repeat = ss.repeat;
746 				samp[nextPort].id = ss.id;
747 			}
748 		} else if (idx < 0)
749 			(void) fprintf(stderr, "panic: input poll failed: %s\n", strerror(errno));
750 
751 		nSounds = 0;
752 		nap = 0;
753 
754 		for (idx=0; idx < nAudioPorts; idx++) {
755 			if (samp[idx].sampsToPlay > 0) {
756 				nSounds++;
757 				if (ALgetfilled(ap[idx]) > 4000) {
758 					nap++;
759 					continue;
760 				}
761 			}
762 			if (samp[idx].sampsToPlay >= maxSampsPerPass) {
763 				(void) ALwritesamps(ap[idx],
764 						    samp[idx].sample + samp[idx].sampsPlayed, maxSampsPerPass);
765 				samp[idx].sampsPlayed += maxSampsPerPass;
766 				samp[idx].sampsToPlay -= maxSampsPerPass;
767 
768 			} else if (samp[idx].sampsToPlay > 0) {
769 				if ((samp[idx].sampsToPlay%2) == 1) {
770 					samp[idx].sampsToPlay -= 1;
771 					samp[idx].sampsPlayed += 1;
772 				}
773 				if (samp[idx].sampsToPlay > 0)
774 				    (void) ALwritesamps(ap[idx],
775 							samp[idx].sample+samp[idx].sampsPlayed, samp[idx].sampsToPlay);
776 
777 				if (samp[idx].repeat) {
778 					sampCount = maxSampsPerPass - samp[idx].sampsToPlay;
779 					samp[idx].sampsToPlay += samp[idx].sampsPlayed - sampCount;
780 					samp[idx].sampsPlayed = sampCount;
781 					(void) ALwritesamps(ap[idx], samp[idx].sample, sampCount);
782 				} else
783 					samp[idx].sampsToPlay = 0;
784 			}
785 		}
786 		if (nap == nSounds)
787 			sginap(1);
788 	}
789 	return;
790 }
791 
792 /*
793  * Open an audio file, check for recognized type, and read.
794  */
sfxLoadAudioFile(char * dirName,char * fileName,AFframecount * size)795 static short *sfxLoadAudioFile(char *dirName, char *fileName, AFframecount *size) {
796 	int fd;
797 	int sampleWidth;
798 	int sampleFmt;
799 	char *name;
800 	short *data;
801 	AFfilehandle file;
802 
803 	if (!(name = malloc(strlen(dirName)+strlen(fileName)+2)))
804 		return NULL;
805 
806 	(void) sprintf(name, "%s/%s", dirName, fileName);
807 
808 	if ((fd=open(name, O_RDONLY)) < 0) {
809 		(void) fprintf(stderr, "Could not open audio file `%s': %s\n", name, strerror(errno));
810 		free(name);
811 		return NULL;
812 	}
813 
814 	switch(AFidentifyfd(fd)) {
815 	  case AF_FILE_AIFF:
816 	  case AF_FILE_AIFFC:
817 		break;
818 
819 	  default:
820 		(void) fprintf(stderr, "%s: unrecognized file type -- convert to AIFF or AIFC\n", name);
821 		free(name);
822 		return NULL;
823 	}
824 	file = AFopenfd(fd, "r", AF_NULL_FILESETUP);
825 
826 	if (file == AF_NULL_FILEHANDLE) {
827 		fprintf(stderr, "%s: failed to attach an audio file struct\n", name);
828 		free(name);
829 		return NULL;
830 	}
831 
832 	if ((int)AFgetchannels(file, AF_DEFAULT_TRACK) != 2) {
833 		fprintf(stderr, "%s: does not have 2 channels\n", name);
834 		free(name);
835 		AFclosefile(file);
836 		return NULL;
837 	}
838 
839 	if (AFgetrate(file, AF_DEFAULT_TRACK) != 16000) {
840 		fprintf(stderr, "%s: is not recorded at 16 KHz\n", name);
841 		free(name);
842 		AFclosefile(file);
843 		return NULL;
844 	}
845 
846 	AFgetsampfmt(file, AF_DEFAULT_TRACK, &sampleFmt, &sampleWidth);
847 	if (sampleWidth != 16) {
848 		fprintf(stderr, "%s: is not recorded with 16 bit samples\n", name);
849 		free(name);
850 		AFclosefile(file);
851 		return NULL;
852 	}
853 	free(name);
854 
855 	*size = AFgetframecnt(file, AF_DEFAULT_TRACK);
856 
857 	if ((data=(short *)malloc((size_t)(*size * 2 * sizeof(short)))) == NULL) {
858 		(void) fprintf(stderr, "%s: out of memory for %lld samples\n", name, *size);
859 		*size = 0;
860 		AFclosefile(file);
861 		return NULL;
862 	}
863 
864 	if (AFreadframes(file, AF_DEFAULT_TRACK, data, (int)*size) != (int)*size) {
865 		(void) fprintf(stderr, "%s: error reading\n", name);
866 		free(data);
867 		data = NULL;
868 		*size = 0L;
869 	}
870 
871 	*size *= 2L;
872 	AFclosefile(file);
873 	return data;
874 }
875 
876 #elif defined(HAVE_SDL)
877 /*
878  * Build the path to the sound files
879  */
DATAFILE(const char * wav)880 static char *DATAFILE(const char* wav) {
881 	static char buf[PATH_MAX];
882 
883 	(void) snprintf(buf, sizeof buf, "%s/%s", sounddir, wav);
884 	return (char *)buf;
885 }
886 
887 /*
888  * Load the .wave files into the sounds array
889  */
loadSounds(void)890 static int loadSounds(void) {
891 #ifdef SOUND_WARN_MISSING
892 	int i;
893 #endif
894 
895 	sounds[CLOAK_WAV] = Mix_LoadWAV(DATAFILE("nt_cloaked.wav"));
896 	sounds[ENTER_SHIP_WAV] = Mix_LoadWAV(DATAFILE("nt_enter_ship.wav"));
897 	sounds[EXPLOSION_WAV] = Mix_LoadWAV(DATAFILE("nt_explosion.wav"));
898 	sounds[SBEXPLOSION_WAV] = Mix_LoadWAV(DATAFILE("nt_sbexplosion.wav"));
899 	sounds[EXPLOSION_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_explosion_other.wav"));
900 	sounds[FIRE_PLASMA_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_plasma.wav"));
901 	sounds[FIRE_TORP_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_torp.wav"));
902 	sounds[FIRE_TORP_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_fire_torp_other.wav"));
903 	sounds[INTRO_WAV] = Mix_LoadWAV(DATAFILE("nt_intro.wav"));
904 	sounds[MESSAGE_WAV] = Mix_LoadWAV(DATAFILE("nt_message.wav"));
905 	sounds[PHASER_WAV] = Mix_LoadWAV(DATAFILE("nt_phaser.wav"));
906 	sounds[PHASER_OTHER_WAV] = Mix_LoadWAV(DATAFILE("nt_phaser_other.wav"));
907 	sounds[PLASMA_HIT_WAV] = Mix_LoadWAV(DATAFILE("nt_plasma_hit.wav"));
908 	sounds[SELF_DESTRUCT_WAV] = Mix_LoadWAV(DATAFILE("nt_self_destruct.wav"));
909 	sounds[SHIELD_DOWN_WAV] = Mix_LoadWAV(DATAFILE("nt_shield_down.wav"));
910 	sounds[SHIELD_UP_WAV] = Mix_LoadWAV(DATAFILE("nt_shield_up.wav"));
911 	sounds[TORP_HIT_WAV] = Mix_LoadWAV(DATAFILE("nt_torp_hit.wav"));
912 	sounds[UNCLOAK_WAV] = Mix_LoadWAV(DATAFILE("nt_uncloak.wav"));
913 	sounds[REDALERT_WAV] = Mix_LoadWAV(DATAFILE("nt_warning.wav"));
914 
915 #ifdef SOUND_WARN_MISSING
916 	for (i=0; i < NUM_WAVES; i++) {
917 		if (!sounds[i]) {
918 			(void) fprintf(stderr, "Mix_LoadWAV sound[%d] could not be loaded.\n"
919 						"Check soundDir in your .netrekrc: %s\n", i, Mix_GetError());
920 		}
921 	}
922 #endif
923 	return 1;
924 }
925 
sound_cleanup(void)926 void sound_cleanup (void) {
927 	int i;
928 
929 	/* Free the sound effects */
930 	for (i = 0; i < NUM_WAVES; i++)
931 		Mix_FreeChunk(sounds[i]);
932 
933 	/* Quit SDL_mixer */
934 	Mix_CloseAudio();
935 
936 	/* Quit SDL */	/* Oh boy, what a meaningful comment! */
937 	SDL_Quit();
938 }
939 #endif /* HAVE_SDL */
940 
Exit_Sound(void)941 void Exit_Sound(void) {
942 
943 #if defined(sgi)
944 	if (sound_init)
945 		sfxEnd(1);
946 
947 #elif !defined(HAVE_SDL)
948 	if (sound_init)
949 		ExitSound();
950 #endif
951 	sound_init = 0;
952 	sound_toggle = 0;
953 }
954 
Init_Sound(void)955 void Init_Sound(void) {
956 	char *sd;
957 
958 #if defined(sgi)
959 	int err;
960 #elif defined(HAVE_SDL)
961 #else
962 	char buf[PATH_MAX];
963 #endif
964 
965 #ifdef DEBUG
966 	printf("Init_Sound\n");
967 #endif
968 	/*
969 	 * If sound_init is on in the .xtrekrc file (set in defaults.c)
970 	 * look for sounds in .xtrekrc sounddir parameter. If that fails
971 	 * look for an environment variable called SOUNDDIR and if that
972 	 * fails, try to open the hardcoded sound directory.
973 	 */
974 	if (sound_init) {
975 		if ((sounddir = getdefault("sounddir")) == NULL) {
976 			if ((sd=getenv("SOUNDDIR")) != NULL)
977 				sounddir = strdup(sd);
978 			else
979 #if defined(sgi)
980 				sounddir = "/usr/local/local/games/netrek-sgi/sounds";
981 #else
982 				sounddir = "/usr/local/share/sounds/netrek-client-cow";
983 #endif
984 		}
985 		if (!isDirectory(sounddir)) {
986 			sounddir = "sounds";
987 				if (!isDirectory(sounddir)) {
988 					(void) fprintf(stderr, "sound directory %s missing\n", sounddir);
989 					return;
990 			}
991 		}
992 	}
993 #if defined(sgi)
994 	err = sfxInit(sounddir, 3);			/* initialize up to three audio ports */
995 	if (err == SFX_ERR_NO_PORTS_AVAIL) {
996 		(void) fprintf(stderr, "No audio ports available.\n");
997 		sound_init = 0;
998 		sound_toggle = 0;
999 		return;
1000 	}
1001 	if (err == SFX_ERR_NO_SPROC) {
1002 		(void) fprintf(stderr, "Unable to execute sound process.\n");
1003 		sound_init = 0;
1004 		sound_toggle = 0;
1005 		return;
1006 	}
1007 	if (err == SFX_ERR_NO_MEM) {
1008 		(void) fprintf(stderr, "No memory available for sound data.\n");
1009 		sound_init = 0;
1010 		sound_toggle = 0;
1011 		return;
1012 	}
1013 	if (err > 0) {				/* load mandatory sounds f we got at least one audio port */
1014 		sounds[FIRE_TORP_WAV] = sfxLoad("fire_torp.aiff");
1015 		sounds[PHASER_WAV] = sfxLoad("phaser.aiff");
1016 		sounds[FIRE_PLASMA_WAV] = sfxLoad("fire_plasma.aiff");
1017 		sounds[EXPLOSION_WAV] = sfxLoad("explosion.aiff");
1018 		sounds[FIRE_TORP_OTHER_WAV] = sfxLoad("fire_torp_other.aiff");
1019 		sounds[PHASER_OTHER_WAV] = sfxLoad("phaser_other.aiff");
1020 		sounds[FIRE_PLASMA_OTHER_WAV] = sfxLoad("fire_plasma_other.aiff");
1021 		sounds[EXPLOSION_OTHER_WAV] = sfxLoad("explosion_other.aiff");
1022 		sounds[PLASMA_HIT_WAV] = sfxLoad("plasma_hit.aiff");
1023 		sounds[TORP_HIT_WAV] = sfxLoad("torp_hit.aiff");
1024 
1025 		if (err > 1) {			/* load optional sounds only if we got two audio ports */
1026 			sounds[CLOAK_WAV] = sfxLoad("cloak.aiff");
1027 			sounds[UNCLOAK_WAV] = sfxLoad("cloak.aiff");
1028 			sounds[SHIELD_DOWN_WAV] = sfxLoad("shield_down.aiff");
1029 			sounds[SHIELD_UP_WAV] = sfxLoad("shield_up.aiff");
1030 			sounds[REDALERT_WAV] = sfxLoad("klaxon.aiff");
1031 			sounds[INTRO_WAV] = sfxLoad("paradise.aiff");
1032 			sounds[MESSAGE_WAV] = sfxLoad("message.aiff");
1033 
1034 			/* load sound loops only if we got three audio ports */
1035 			if (err > 2) {
1036 				sounds[THERMAL_WAV] = sfxLoad("thermal_warn.aiff");
1037 				sounds[ENTER_SHIP_WAV] = sfxLoad("enter_ship.aiff");
1038 				sounds[SELF_DESTRUCT_WAV] = sfxLoad("self_destruct.aiff");
1039 
1040 				if ((sounds[ENGINE_WAV] = sfxLoad("bridge.aiff")) != NULL) {
1041 					sfxLoop(sounds[ENGINE_WAV]);
1042 					sfxPitchBend(sounds[ENGINE_WAV], 0.0f, 1.0f, 1.0f, 2.0f, 1.1f, 20);
1043 				}
1044 			}
1045 		}
1046 		sfxPlay(sounds[INTRO_WAV]);
1047 	}
1048 
1049 #elif defined(HAVE_SDL)
1050 #ifdef DEBUG
1051 	printf("Init_Sound using SDL\n");
1052 #endif
1053 
1054 	/* Initialize the SDL library */
1055 	if (SDL_Init(SDL_INIT_AUDIO) < 0) {
1056 	  fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
1057 	}
1058 	atexit(SDL_Quit);
1059 
1060 	/* Open the audio device at 8000 Hz 8 bit Microsoft PCM */
1061 	if (Mix_OpenAudio(22050, AUDIO_U8, 2, 512) < 0) {
1062 	  fprintf(stderr,"Mix_OpenAudio: %s\n", Mix_GetError());
1063 	  sound_init = 0;
1064 	}
1065 
1066         Mix_AllocateChannels(16);
1067 
1068 	if (getdefault("soundvol") != NULL) {
1069 	  int vol = atoi(getdefault("soundvol"));
1070 	  Mix_Volume(-1, vol);
1071 	}
1072 
1073 	/* If we successfully loaded the wav files, so shut-off
1074 	   sound_init and play the introduction */
1075 	if (loadSounds()) {
1076 	  if (sounds[INTRO_WAV])
1077 	    if (Mix_PlayChannel(-1, sounds[INTRO_WAV], 0) < 0) {
1078 	      fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
1079 	    }
1080 	}
1081 #else
1082 	if (InitSound() == -1) {
1083 	  sound_toggle = 0;
1084 	  sound_init = 0;
1085 	} else {
1086 	  sound_init = 1;
1087 	  sound_toggle = 1;
1088 	}
1089 
1090 	strcpy(sound_prefix, sounddir);
1091 	strcat(sound_prefix, "/");
1092 
1093 	if (sound_toggle) {
1094 	  strcpy(buf, sounddir);
1095 	  strcat(buf, "/nt_intro");
1096 	  StartSound(buf);
1097 	}
1098 #endif
1099 }
1100 
1101 #if defined(HAVE_SDL) || defined(sgi)
1102 static int sound2wave[NUM_SOUNDS+1] = {
1103 	/* NO_SOUND */			-1,
1104 	/* FIRE_TORP_SOUND */		FIRE_TORP_WAV,
1105 	/* PHASER_SOUND */		PHASER_WAV,
1106 	/* FIRE_PLASMA_SOUND */		FIRE_PLASMA_WAV,
1107 	/* EXPLOSION_SOUND */		EXPLOSION_WAV,
1108 	/* SBEXPLOSION_SOUND */		SBEXPLOSION_WAV,
1109 	/* CLOAK_SOUND */		CLOAK_WAV,
1110 	/* UNCLOAK_SOUND */		UNCLOAK_WAV,
1111 	/* SHIELD_DOWN_SOUND */		SHIELD_DOWN_WAV,
1112 	/* SHIELD_UP_SOUND */		SHIELD_UP_WAV,
1113 	/* TORP_HIT_SOUND */		TORP_HIT_WAV,
1114 	/* REDALERT_SOUND */		REDALERT_WAV,
1115 	/* BUZZER_SOUND */		BUZZER_WAV,
1116 #if defined(sgi)
1117 	/* ENGINE_SOUND */		ENGINE_WAV,
1118 #else
1119 	/* text in soundrefresh() says engine sound is not supported
1120 	 * so we'll disable it although there is an ENGINE_WAV */
1121 	/* ENGINE_SOUND */		-1,
1122 #endif
1123 	/* THERMAL_SOUND */		THERMAL_WAV,
1124 	/* ENTER_SHIP_SOUND */		ENTER_SHIP_WAV,
1125 	/* SELF_DESTRUCT_SOUND */	SELF_DESTRUCT_WAV,
1126 	/* PLASMA_HIT_SOUND */		PLASMA_HIT_WAV,
1127 	/* MESSAGE_SOUND */		MESSAGE_WAV,
1128 	/* MESSAGE1_SOUND */		MESSAGE_WAV,
1129 	/* MESSAGE2_SOUND */		MESSAGE_WAV,
1130 	/* MESSAGE3_SOUND */		MESSAGE_WAV,
1131 	/* MESSAGE4_SOUND */		MESSAGE_WAV,
1132 	/* MESSAGE5_SOUND */		MESSAGE_WAV,
1133 	/* MESSAGE6_SOUND */		MESSAGE_WAV,
1134 	/* MESSAGE7_SOUND */		MESSAGE_WAV,
1135 	/* MESSAGE8_SOUND */		MESSAGE_WAV,
1136 	/* MESSAGE9_SOUND */		MESSAGE_WAV,
1137 	/* OTHER_FIRE_TORP_SOUND */	FIRE_TORP_OTHER_WAV,
1138 	/* OTHER_PHASER_SOUND */	PHASER_OTHER_WAV,
1139 	/* OTHER_FIRE_PLASMA_SOUND */	FIRE_PLASMA_OTHER_WAV,
1140 	/* OTHER_EXPLOSION_SOUND */	EXPLOSION_OTHER_WAV,
1141 	/* OTHER_SBEXPLOSION_SOUND */	SBEXPLOSION_OTHER_WAV
1142 };
1143 #endif
1144 
1145 #if defined(HAVE_SDL) || defined(sgi)
get_waveform(int type)1146 static int get_waveform(int type) {
1147 	int waveform;
1148 
1149 	if (type <= 0 || type > NUM_SOUNDS) {			/* check sound index */
1150 #ifdef DEBUG
1151 		(void) fprintf(stderr, "panic: non-existent sound number: %i\n", type);
1152 #endif
1153 		return -1;
1154 	}
1155 
1156 	if ((waveform = sound2wave[type]) >= NUM_WAVES) {	/* check waveform index */
1157 #ifdef DEBUG
1158 		(void) fprintf(stderr, "panic: non-existent waveform number: %i\n", waveform);
1159 #endif
1160 		return -1;
1161 	}
1162 	return waveform;
1163 }
1164 #endif
1165 
Play_Sound(int type)1166 void Play_Sound(int type) {
1167 #if defined(HAVE_SDL) || defined(sgi)
1168 	int waveform;
1169 
1170 	if (!sound_init || (waveform=get_waveform(type)) < 0)
1171 		return;
1172 
1173 #if defined(sgi)
1174 	if (type > OTHER_SOUND_OFFSET && !soundOther)
1175 		return;
1176 
1177 	sfxPlay(sounds[waveform]);
1178 
1179 #else
1180 	if (sounds[waveform])
1181 	  if (Mix_PlayChannel(-1, sounds[waveform], 0) < 0) {
1182 	    (void) fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
1183 	  }
1184 #endif
1185 
1186 #else
1187 	char buf[PATH_MAX];
1188 
1189 	/* Don't play other ship's sounds if turned off */
1190 	if (type > OTHER_SOUND_OFFSET && !soundOther)
1191 		return;
1192 
1193 	if (sound_toggle && sounds[type].flag &&
1194 	   ((sounds[type].priority >= sounds[current_sound].priority) || !SoundPlaying())) {
1195 		STRNCPY(buf, sound_prefix, PATH_MAX);
1196 		strcat(buf, sounds[type].name);
1197 		StartSound(buf);
1198 		current_sound = type;
1199 	}
1200 	if (!(sound_toggle))
1201 		current_sound = NO_SOUND;
1202 #endif
1203 }
1204 
1205 #if !defined(sgi)	/* avoid calling null functions at all */
Abort_Sound(int type)1206 void Abort_Sound(int type) {
1207 #if !defined(HAVE_SDL)
1208 	if ((current_sound != NO_SOUND) && (type == current_sound))
1209 		StopSound();
1210 #endif
1211 }
1212 #endif
1213 
1214 #if defined(sgi)
1215 /*
1216  * Play a pitch-bended engine sound loop while player is alive.
1217  */
Engine_Sound(int speed,int maxspeed)1218 void Engine_Sound(int speed, int maxspeed) {
1219 	static int engine_on = 0;
1220 	static float opitch = 0.0f;
1221 	float pitch;
1222 
1223 	if (!sound_init)
1224 		return;
1225 
1226 	if ((speed < 0) && (maxspeed < 0)) {	/* stop sound */
1227 		sfxDisable(sounds[ENGINE_WAV]);
1228 		engine_on = 0;
1229 		opitch = 0.0f;
1230 		return;
1231 	}
1232 	if (speed == 0)
1233 		pitch = 0.0f;
1234 	else	pitch = 0.25f * (float)speed * (1.0f / (float)maxspeed);
1235 
1236 	if (!engine_on || opitch != pitch) {
1237 		sfxEnable(sounds[ENGINE_WAV]);
1238 		sfxPlayPitch(sounds[ENGINE_WAV], pitch);
1239 		engine_on = 1;
1240 		opitch = pitch;
1241 	}
1242 	return;
1243 }
1244 #endif
1245 
1246 /* Sound options window stuff */
1247 
1248 #define SOUND_TOGGLE  0
1249 #define SOUND_OTHER   MESSAGE_SOUND + 1
1250 #define SOUND_INIT    MESSAGE_SOUND + 2
1251 #define SOUND_DONE    MESSAGE_SOUND + 3
1252 
1253 #if !defined(HAVE_SDL)
1254 static void soundrefresh(int i);
1255 #endif
1256 
sound_window_height(void)1257 int sound_window_height(void) {
1258 #if defined(HAVE_SDL)
1259 	return 1;
1260 #else
1261 	return MESSAGE_SOUND + 4;
1262 #endif
1263 }
1264 
soundwindow(void)1265 void soundwindow(void) {
1266 #if defined(HAVE_SDL)
1267 	char *buf="All or nothing with SDL sound. Sorry";
1268 	W_WriteText(soundWin, 0, 0, textColor, buf, strlen(buf), 0);
1269 #else
1270 	int     i;
1271 
1272 	for (i=0; i <= SOUND_DONE; i++)
1273 		soundrefresh(i);
1274 #endif
1275 
1276 	/* Map window */
1277 	W_MapWindow(soundWin);
1278 }
1279 
1280 #if !defined(HAVE_SDL)
soundrefresh(int i)1281 static void soundrefresh(int i) {
1282 	char buf[200], *flag;
1283 
1284 	if (i == SOUND_TOGGLE) {
1285 		(void) snprintf(buf, sizeof buf, "Sound is turned %s", (sound_toggle == 1) ? "ON" : "OFF");
1286 	} else if (i < SOUND_OTHER) {
1287 #if defined(sgi)
1288 		flag = (sfxIsEnabled(sounds[i]) ? "ON" : "OFF");
1289 #else
1290 		flag = ((sounds[i].flag == 1) ? "ON" : "OFF");
1291 #endif
1292 		switch (i) {
1293 		  case FIRE_TORP_SOUND:
1294 			(void) snprintf(buf, sizeof buf, "Fire torp sound is %s", flag);
1295 			break;
1296 
1297 		  case PHASER_SOUND:
1298 			(void) snprintf(buf, sizeof buf, "Phaser sound is %s", flag);
1299 			break;
1300 
1301 		  case FIRE_PLASMA_SOUND:
1302 			(void) snprintf(buf, sizeof buf, "Fire plasma sound is %s", flag);
1303 			break;
1304 
1305 		  case EXPLOSION_SOUND:
1306 			(void) snprintf(buf, sizeof buf, "Explosion sound is %s", flag);
1307 			break;
1308 
1309 		  case CLOAK_SOUND:
1310 			(void) snprintf(buf, sizeof buf, "Cloak sound is %s", flag);
1311 			break;
1312 
1313 		  case UNCLOAK_SOUND:
1314 			(void) snprintf(buf, sizeof buf, "Uncloak sound is %s", flag);
1315 			break;
1316 
1317 		  case SHIELD_DOWN_SOUND:
1318 			(void) snprintf(buf, sizeof buf, "Shield down  sound is %s", flag);
1319 			break;
1320 
1321 		  case SHIELD_UP_SOUND:
1322 			(void) snprintf(buf, sizeof buf, "Shield up sound is %s", flag);
1323 			break;
1324 
1325 		  case TORP_HIT_SOUND:
1326 			(void) snprintf(buf, sizeof buf, "Torp hit sound is %s", flag);
1327 			break;
1328 
1329 		  case REDALERT_SOUND:
1330 			(void) snprintf(buf, sizeof buf, "Red alert sound is %s", flag);
1331 			break;
1332 
1333 		  case ENGINE_SOUND:
1334 #if defined(sgi)
1335 			(void) snprintf(buf, sizeof buf, "Engine sound is %s", flag);
1336 #else
1337 			(void) snprintf(buf, sizeof buf, "Engine sound is not supported");
1338 #endif
1339 			break;
1340 
1341 		  case ENTER_SHIP_SOUND:
1342 			(void) snprintf(buf, sizeof buf, "Enter ship sound is %s", flag);
1343 			break;
1344 
1345 		  case SELF_DESTRUCT_SOUND:
1346 			(void) snprintf(buf, sizeof buf, "Self destruct sound is %s", flag);
1347 			break;
1348 
1349 		  case PLASMA_HIT_SOUND:
1350 			(void) snprintf(buf, sizeof buf, "Plasma hit sound is %s", flag);
1351 			break;
1352 
1353 		  case MESSAGE_SOUND:
1354 			(void) snprintf(buf, sizeof buf, "Message sound is %s", flag);
1355 			break;
1356 		}
1357 
1358 	} else if (i == SOUND_OTHER)
1359 		(void) snprintf(buf, sizeof buf, "Other ship's sound is %s", soundOther == 1 ? "ON" : "OFF");
1360 #if defined(sgi)
1361 	else if (i == SOUND_INIT)
1362 		(void) snprintf(buf, sizeof buf, sound_init ? "Reset audio hardware"
1363 							   : "Initialize audio hardware");
1364 #else
1365 	else if (i == SOUND_INIT)
1366 		(void) snprintf(buf, sizeof buf, sound_init ? "Restart external sound player"
1367 							   : "Initialize external sound player");
1368 #endif
1369 	else if (i == SOUND_DONE)
1370 		(void) snprintf(buf, sizeof buf, "Done");
1371 	else
1372 		(void) fprintf(stderr, "Uh oh, bogus refresh number in soundrefresh\n");
1373 
1374 	W_WriteText(soundWin, 0, i, textColor, buf, strlen(buf), 0);
1375 }
1376 #endif /* HAVE_SDL */
1377 
soundaction(W_Event * data)1378 void soundaction(W_Event * data) {
1379 #if defined(sgi)
1380 	printf("sorry, not yet implemented\n");
1381 
1382 #elif !defined(HAVE_SDL)
1383   int     i, j;
1384 
1385   i = data->y;
1386 
1387   if (i == SOUND_TOGGLE) {
1388       if (sound_init)
1389 	sound_toggle = (sound_toggle == 1) ? 0 : 1;
1390       soundrefresh(SOUND_TOGGLE);
1391       /* text in soundrefresh() says engine sound is not supported
1392       if (!sound_toggle) {
1393 	  Abort_Sound(ENGINE_SOUND);
1394       } else {
1395 	  Play_Sound(ENGINE_SOUND);
1396       }
1397       */
1398     }
1399   else if (i < SOUND_OTHER)
1400     {
1401       sounds[i].flag = (sounds[i].flag == 1) ? 0 : 1;
1402       if (i + OTHER_SOUND_OFFSET <= NUM_SOUNDS)
1403 	sounds[i + OTHER_SOUND_OFFSET].flag = sounds[i].flag;
1404 
1405       soundrefresh(i);
1406       Play_Sound(i);
1407       if (i == MESSAGE_SOUND)
1408 	{
1409 	  for (j = MESSAGE1_SOUND; j <= MESSAGE9_SOUND; j++)
1410 	    sounds[j].flag = sounds[MESSAGE_SOUND].flag;
1411 	}
1412       /* case ENGINE: st_engine = (st_engine == 1) ? 0 : 0; soundrefresh * *
1413        * (ENGINE); if (st_engine && sound_toggle) { Play_Sound * *
1414        * (ENGINE_SOUND); } else { Abort_Sound (ENGINE_SOUND); } break; */
1415 
1416     }
1417   else if (i == SOUND_OTHER)
1418     {
1419       soundOther = !soundOther;
1420       soundrefresh(SOUND_OTHER);
1421     }
1422   else if (i == SOUND_INIT)
1423     {
1424       Exit_Sound();
1425       sound_init = 1;
1426       Init_Sound();
1427       soundrefresh(SOUND_INIT);
1428       soundrefresh(SOUND_TOGGLE);
1429     }
1430   else
1431     {
1432       sounddone();
1433     }
1434 #endif /* HAVE_SDL */
1435 }
1436 
sounddone(void)1437 void sounddone(void) {
1438 
1439 	W_UnmapWindow(soundWin);
1440 	return;
1441 }
1442 
1443 #endif /* SOUND */
1444