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