rnd-20020509-1-src
[rocksndiamonds.git] / src / libgame / sound.c
1 /***********************************************************
2 * Artsoft Retro-Game Library                               *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * sound.c                                                  *
12 ***********************************************************/
13
14 #include <string.h>
15 #include <sys/time.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <dirent.h>
19 #include <signal.h>
20
21 #include "system.h"
22 #include "sound.h"
23 #include "misc.h"
24 #include "setup.h"
25
26
27 struct ListNode
28 {
29   char *key;
30   void *content;
31   struct ListNode *next;
32 };
33 typedef struct ListNode ListNode;
34
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
40
41
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
47
48
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
51
52 static struct AudioFormatInfo afmt =
53 {
54   TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
55 };
56
57 static int playing_sounds = 0;
58 static struct SoundControl playlist[NUM_MIXER_CHANNELS];
59 static struct SoundControl emptySoundControl =
60 {
61 #if 1
62   FALSE, -1, 0, 0, FALSE, 0, 0, 0, NULL
63 #else
64   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
65 #endif
66 };
67
68 #if defined(PLATFORM_UNIX)
69 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
70 static short premix_first_buffer[SND_BLOCKSIZE];
71 #if defined(AUDIO_STREAMING_DSP)
72 static short premix_left_buffer[SND_BLOCKSIZE];
73 static short premix_right_buffer[SND_BLOCKSIZE];
74 static long premix_last_buffer[SND_BLOCKSIZE];
75 #endif
76 static byte playing_buffer[SND_BLOCKSIZE];
77 #endif
78
79 /* forward declaration of internal functions */
80 #if defined(AUDIO_STREAMING_DSP)
81 static void SoundServer_InsertNewSound(struct SoundControl);
82 static void InitAudioDevice_DSP(struct AudioFormatInfo *);
83 #elif defined(PLATFORM_HPUX)
84 static void InitAudioDevice_HPUX(struct AudioFormatInfo *);
85 #elif defined(PLATFORM_UNIX)
86 static unsigned char linear_to_ulaw(int);
87 static int ulaw_to_linear(unsigned char);
88 #elif defined(PLATFORM_MSDOS)
89 static void SoundServer_InsertNewSound(struct SoundControl);
90 static void SoundServer_StopSound(struct SoundControl);
91 static void SoundServer_StopAllSounds();
92 #endif
93
94 static void ReloadCustomSounds();
95 static void ReloadCustomMusic();
96 static void FreeSound(void *);
97
98 #if defined(PLATFORM_UNIX)
99 static int OpenAudioDevice(char *audio_device_name)
100 {
101   int audio_device_fd;
102
103   /* check if desired audio device is accessible */
104   if (access(audio_device_name, W_OK) != 0)
105     return -1;
106
107   /* try to open audio device in non-blocking mode */
108   if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
109     return audio_device_fd;
110
111   /* re-open audio device in blocking mode */
112   close(audio_device_fd);
113   audio_device_fd = open(audio_device_name, O_WRONLY);
114
115   return audio_device_fd;
116 }
117
118 static void CloseAudioDevice(int *audio_device_fd)
119 {
120   if (*audio_device_fd == 0)
121     return;
122
123   close(*audio_device_fd);
124   *audio_device_fd = -1;
125 }
126
127 static boolean TestAudioDevices(void)
128 {
129   static char *audio_device_name[] =
130   {
131     DEVICENAME_DSP,
132     DEVICENAME_AUDIO
133   };
134   int audio_device_fd = -1;
135   int i;
136
137   /* look for available audio devices, starting with preferred ones */
138   for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
139     if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
140       break;
141
142   if (audio_device_fd < 0)
143   {
144     Error(ERR_WARN, "cannot open audio device -- no sound");
145     return FALSE;
146   }
147
148   close(audio_device_fd);
149
150   audio.device_name = audio_device_name[i];
151
152   return TRUE;
153 }
154
155 #if !defined(TARGET_SDL)
156 static boolean ForkAudioProcess(void)
157 {
158   if (pipe(audio.soundserver_pipe) < 0)
159   {
160     Error(ERR_WARN, "cannot create pipe -- no sounds");
161     return FALSE;
162   }
163
164   if ((audio.soundserver_pid = fork()) < 0)
165   {       
166     Error(ERR_WARN, "cannot create sound server process -- no sounds");
167     return FALSE;
168   }
169
170   if (audio.soundserver_pid == 0)       /* we are child process */
171   {
172     SoundServer();
173
174     /* never reached */
175     exit(0);
176   }
177   else                                  /* we are parent */
178     close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
179
180   return TRUE;
181 }
182 #endif
183
184 void UnixOpenAudio(void)
185 {
186   if (!TestAudioDevices())
187     return;
188
189   audio.sound_available = TRUE;
190   audio.sound_enabled = TRUE;
191
192 #if defined(AUDIO_STREAMING_DSP)
193   audio.music_available = TRUE;
194   audio.loops_available = TRUE;
195 #endif
196 }
197
198 void UnixCloseAudio(void)
199 {
200   if (audio.device_fd)
201     close(audio.device_fd);
202
203   if (audio.soundserver_pid > 0)        /* we are parent process */
204     kill(audio.soundserver_pid, SIGTERM);
205 }
206 #endif  /* PLATFORM_UNIX */
207
208 void InitPlaylist(void)
209 {
210   int i;
211
212   for(i=0; i<NUM_MIXER_CHANNELS; i++)
213     playlist[i] = emptySoundControl;
214   playing_sounds = 0;
215 }
216
217 #if 1
218 static void PlaylistRemoveSound(int pos)
219 {
220   if (!playing_sounds || !playlist[pos].active)
221     return;
222
223   playlist[pos] = emptySoundControl;
224   playing_sounds--;
225
226   if (!playing_sounds)
227     CloseAudioDevice(&audio.device_fd);
228 }
229
230 static void WriteReloadInfoToPipe(char *set_name, int type)
231 {
232   struct SoundControl snd_ctrl = emptySoundControl;
233   TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
234                   artwork.mus_current);
235   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
236   unsigned long str_size2 = strlen(ti->basepath) + 1;
237   unsigned long str_size3 = strlen(ti->fullpath) + 1;
238
239   snd_ctrl.state = type;
240   snd_ctrl.data_len = strlen(set_name) + 1;
241
242   if (write(audio.soundserver_pipe[1], &snd_ctrl,
243             sizeof(snd_ctrl)) < 0 ||
244       write(audio.soundserver_pipe[1], set_name,
245             snd_ctrl.data_len) < 0 ||
246       write(audio.soundserver_pipe[1], leveldir_current,
247             sizeof(TreeInfo)) < 0 ||
248       write(audio.soundserver_pipe[1], ti,
249             sizeof(TreeInfo)) < 0 ||
250       write(audio.soundserver_pipe[1], &str_size1,
251             sizeof(unsigned long)) < 0 ||
252       write(audio.soundserver_pipe[1], &str_size2,
253             sizeof(unsigned long)) < 0 ||
254       write(audio.soundserver_pipe[1], &str_size3,
255             sizeof(unsigned long)) < 0 ||
256       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
257             str_size1) < 0 ||
258       write(audio.soundserver_pipe[1], ti->basepath,
259             str_size2) < 0 ||
260       write(audio.soundserver_pipe[1], ti->fullpath,
261             str_size3) < 0)
262   {
263     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
264     audio.sound_available = audio.sound_enabled = FALSE;
265     return;
266   }
267 }
268
269 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
270 {
271   TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
272                        &artwork.snd_current : &artwork.mus_current);
273   TreeInfo *ti = *ti_ptr;
274   unsigned long str_size1, str_size2, str_size3;
275   static char *set_name = NULL;
276
277   if (set_name)
278     free(set_name);
279
280   set_name = checked_malloc(snd_ctrl.data_len);
281
282   if (leveldir_current == NULL)
283     leveldir_current = checked_calloc(sizeof(TreeInfo));
284   if (ti == NULL)
285     ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
286   if (leveldir_current->fullpath != NULL)
287     free(leveldir_current->fullpath);
288   if (ti->basepath != NULL)
289     free(ti->basepath);
290   if (ti->fullpath != NULL)
291     free(ti->fullpath);
292
293   if (read(audio.soundserver_pipe[0], set_name,
294            snd_ctrl.data_len) != snd_ctrl.data_len ||
295       read(audio.soundserver_pipe[0], leveldir_current,
296            sizeof(TreeInfo)) != sizeof(TreeInfo) ||
297       read(audio.soundserver_pipe[0], ti,
298            sizeof(TreeInfo)) != sizeof(TreeInfo) ||
299       read(audio.soundserver_pipe[0], &str_size1,
300            sizeof(unsigned long)) != sizeof(unsigned long) ||
301       read(audio.soundserver_pipe[0], &str_size2,
302            sizeof(unsigned long)) != sizeof(unsigned long) ||
303       read(audio.soundserver_pipe[0], &str_size3,
304            sizeof(unsigned long)) != sizeof(unsigned long))
305     Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
306
307   leveldir_current->fullpath = checked_calloc(str_size1);
308   ti->basepath = checked_calloc(str_size2);
309   ti->fullpath = checked_calloc(str_size3);
310
311   if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
312            str_size1) != str_size1 ||
313       read(audio.soundserver_pipe[0], ti->basepath,
314            str_size2) != str_size2 ||
315       read(audio.soundserver_pipe[0], ti->fullpath,
316            str_size3) != str_size3)
317     Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
318
319   if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
320     artwork.sounds_set_current = set_name;
321   else
322     artwork.music_set_current = set_name;
323 }
324
325 static void HandleSoundRequest(struct SoundControl snd_ctrl)
326 {
327   int i;
328
329   if (IS_RELOADING(snd_ctrl))
330   {
331     ReadReloadInfoFromPipe(snd_ctrl);
332     InitPlaylist();
333     CloseAudioDevice(&audio.device_fd);
334
335     if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
336       ReloadCustomSounds();
337     else
338       ReloadCustomMusic();
339   }
340   else if (IS_FADING(snd_ctrl))
341   {
342     if (!playing_sounds)
343       return;
344
345     if (IS_MUSIC(snd_ctrl))
346     {
347       playlist[MUSIC_CHANNEL].state |= SND_CTRL_FADE;
348       return;
349     }
350
351     for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
352       if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
353         playlist[i].state |= SND_CTRL_FADE;
354   }
355   else if (IS_STOPPING(snd_ctrl))
356   {
357     if (!playing_sounds)
358       return;
359
360     if (IS_MUSIC(snd_ctrl))
361     {
362       PlaylistRemoveSound(MUSIC_CHANNEL);
363       return;
364     }
365
366     for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
367       if (playlist[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
368         PlaylistRemoveSound(i);
369   }
370 }
371 #endif
372
373 void StartSoundserver(void)
374 {
375   if (!audio.sound_available)
376     return;
377
378 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
379   if (!ForkAudioProcess())
380     audio.sound_available = FALSE;
381 #endif
382 }
383
384 #if defined(PLATFORM_UNIX)
385 void SoundServer(void)
386 {
387   int i;
388
389   struct SoundControl snd_ctrl;
390   fd_set sound_fdset;
391
392   close(audio.soundserver_pipe[1]);     /* no writing into pipe needed */
393
394   InitPlaylist();
395
396   stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
397   for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
398     stereo_volume[i] =
399       (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
400
401 #if defined(PLATFORM_HPUX)
402   InitAudioDevice_HPUX(&afmt);
403 #endif
404
405   FD_ZERO(&sound_fdset); 
406   FD_SET(audio.soundserver_pipe[0], &sound_fdset);
407
408   while(1)      /* wait for sound playing commands from client */
409   {
410     FD_SET(audio.soundserver_pipe[0], &sound_fdset);
411     select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
412     if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
413       continue;
414     if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
415         != sizeof(snd_ctrl))
416       Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
417
418     HandleSoundRequest(snd_ctrl);
419
420     if (IS_RELOADING(snd_ctrl))
421       continue;
422
423 #if defined(AUDIO_STREAMING_DSP)
424
425     if (playing_sounds || snd_ctrl.active)
426     {
427       if (playing_sounds ||
428           (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
429       {
430         struct timeval delay = { 0, 0 };
431
432         if (!playing_sounds)    /* we just opened the audio device */
433           InitAudioDevice_DSP(&afmt);
434
435         if (snd_ctrl.active)    /* new sound has arrived */
436           SoundServer_InsertNewSound(snd_ctrl);
437
438         while (playing_sounds &&
439                select(audio.soundserver_pipe[0] + 1,
440                       &sound_fdset, NULL, NULL, &delay) < 1)
441         {       
442           int max_sample_size;
443           int fragment_size = afmt.fragment_size;
444           int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
445           boolean stereo = afmt.stereo;
446
447           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
448
449           max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
450
451           /* first clear the last premixing buffer */
452           memset(premix_last_buffer, 0,
453                  max_sample_size * (stereo ? 2 : 1) * sizeof(long));
454
455           for(i=0; i<NUM_MIXER_CHANNELS; i++)
456           {
457             void *sample_ptr;
458             int sample_len;
459             int sample_pos;
460             int sample_size;
461             int j;
462
463             if (!playlist[i].active)
464               continue;
465
466             /* pointer, lenght and actual playing position of sound sample */
467             sample_ptr = playlist[i].data_ptr;
468             sample_len = playlist[i].data_len;
469             sample_pos = playlist[i].playingpos;
470             sample_size = MIN(max_sample_size, sample_len - sample_pos);
471             playlist[i].playingpos += sample_size;
472
473             /* copy original sample to first mixing buffer */
474             if (playlist[i].format == AUDIO_FORMAT_U8)
475               for (j=0; j<sample_size; j++)
476                 premix_first_buffer[j] =
477                   ((short)(((byte *)sample_ptr)[sample_pos + j] ^ 0x80)) << 8;
478             else        /* AUDIO_FORMAT_S16 */
479               for (j=0; j<sample_size; j++)
480                 premix_first_buffer[j] =
481                   ((short *)sample_ptr)[sample_pos + j];
482
483             /* are we about to restart a looping sound? */
484             if (IS_LOOP(playlist[i]) && sample_size < max_sample_size)
485             {
486               while (sample_size < max_sample_size)
487               {
488                 int restarted_sample_size =
489                   MIN(max_sample_size - sample_size, sample_len);
490
491                 if (playlist[i].format == AUDIO_FORMAT_U8)
492                   for (j=0; j<restarted_sample_size; j++)
493                     premix_first_buffer[sample_size + j] =
494                       ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
495                 else
496                   for (j=0; j<restarted_sample_size; j++)
497                     premix_first_buffer[sample_size + j] =
498                       ((short *)sample_ptr)[j];
499
500                 playlist[i].playingpos = restarted_sample_size;
501                 sample_size += restarted_sample_size;
502               }
503             }
504
505             /* decrease volume if sound is fading out */
506             if (IS_FADING(playlist[i]) &&
507                 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
508               playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
509
510             /* adjust volume of actual sound sample */
511             if (playlist[i].volume != PSND_MAX_VOLUME)
512               for(j=0; j<sample_size; j++)
513                 premix_first_buffer[j] =
514                   (playlist[i].volume * (long)premix_first_buffer[j])
515                     >> PSND_MAX_VOLUME_BITS;
516
517             /* fill the last mixing buffer with stereo or mono sound */
518             if (stereo)
519             {
520               int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
521               int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
522               int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
523
524               for(j=0; j<sample_size; j++)
525               {
526                 premix_left_buffer[j] =
527                   (left_volume * premix_first_buffer[j])
528                     >> PSND_MAX_LEFT2RIGHT_BITS;
529                 premix_right_buffer[j] =
530                   (right_volume * premix_first_buffer[j])
531                     >> PSND_MAX_LEFT2RIGHT_BITS;
532
533                 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
534                 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
535               }
536             }
537             else
538             {
539               for(j=0; j<sample_size; j++)
540                 premix_last_buffer[j] += premix_first_buffer[j];
541             }
542
543             /* delete completed sound entries from the playlist */
544             if (playlist[i].playingpos >= playlist[i].data_len)
545             {
546               if (IS_LOOP(playlist[i]))
547                 playlist[i].playingpos = 0;
548               else
549               {
550                 playlist[i] = emptySoundControl;
551                 playing_sounds--;
552               }
553             }
554             else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
555             {
556               playlist[i] = emptySoundControl;
557               playing_sounds--;
558             }
559           }
560
561           /* prepare final playing buffer according to system audio format */
562           for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
563           {
564             /* cut off at 17 bit value */
565             if (premix_last_buffer[i] < -65535)
566               premix_last_buffer[i] = -65535;
567             else if (premix_last_buffer[i] > 65535)
568               premix_last_buffer[i] = 65535;
569
570             /* shift to 16 bit value */
571             premix_last_buffer[i] >>= 1;
572
573             if (afmt.format & AUDIO_FORMAT_U8)
574             {
575               playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
576             }
577             else if (afmt.format & AUDIO_FORMAT_LE)     /* 16 bit */
578             {
579               playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
580               playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
581             }
582             else                                        /* big endian */
583             {
584               playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
585               playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
586             }
587           }
588
589           /* finally play the sound fragment */
590           write(audio.device_fd, playing_buffer, fragment_size);
591         }
592
593         /* if no sounds playing, free device for other sound programs */
594         if (!playing_sounds)
595           close(audio.device_fd);
596       }
597     }
598
599 #else /* !AUDIO_STREAMING_DSP */
600
601     if (snd_ctrl.active && !IS_LOOP(snd_ctrl))
602     {
603       struct timeval delay = { 0, 0 };
604       byte *sample_ptr;
605       long sample_size, max_sample_size = SND_BLOCKSIZE;
606       long sample_rate = 8000;  /* standard "/dev/audio" sampling rate */
607       int wait_percent = 90;    /* wait 90% of the real playing time */
608       int i;
609
610       if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
611       {
612         playing_sounds = 1;
613
614         while (playing_sounds &&
615                select(audio.soundserver_pipe[0] + 1,
616                       &sound_fdset, NULL, NULL, &delay) < 1)
617         {       
618           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
619
620           /* get pointer and size of the actual sound sample */
621           sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
622           sample_size =
623             MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
624           snd_ctrl.playingpos += sample_size;
625
626           /* fill the first mixing buffer with original sample */
627           memcpy(premix_first_buffer,sample_ptr,sample_size);
628
629           /* adjust volume of actual sound sample */
630           if (snd_ctrl.volume != PSND_MAX_VOLUME)
631             for(i=0;i<sample_size;i++)
632               premix_first_buffer[i] =
633                 (snd_ctrl.volume * (int)premix_first_buffer[i])
634                   >> PSND_MAX_VOLUME_BITS;
635
636           for(i=0;i<sample_size;i++)
637             playing_buffer[i] =
638               linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
639
640           if (snd_ctrl.playingpos >= snd_ctrl.data_len)
641             playing_sounds = 0;
642
643           /* finally play the sound fragment */
644           write(audio.device_fd,playing_buffer,sample_size);
645
646           delay.tv_sec = 0;
647           delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
648         }
649         close(audio.device_fd);
650       }
651     }
652 #endif /* !AUDIO_STREAMING_DSP */
653   }
654 }
655 #endif /* PLATFORM_UNIX */
656
657 #if defined(PLATFORM_MSDOS)
658 static void sound_handler(struct SoundControl snd_ctrl)
659 {
660   int i;
661
662   if (snd_ctrl.fade_sound)
663   {
664     if (!playing_sounds)
665       return;
666
667     for (i=0; i<NUM_MIXER_CHANNELS; i++)
668       if ((snd_ctrl.stop_all_sounds ||
669            (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
670            (i == audio.music_channel && snd_ctrl.music)) &&
671           !playlist[i].fade_sound)
672       {
673         playlist[i].fade_sound = TRUE;
674         if (voice_check(playlist[i].voice))
675           voice_ramp_volume(playlist[i].voice, 1000, 0);
676         playlist[i].state &= ~SND_CTRL_IS_LOOP;
677       }
678   }
679   else if (snd_ctrl.stop_all_sounds)
680   {
681     if (!playing_sounds)
682       return;
683     SoundServer_StopAllSounds();
684   }
685   else if (snd_ctrl.stop_sound)
686   {
687     if (!playing_sounds)
688       return;
689     SoundServer_StopSound(snd_ctrl);
690   }
691
692   for (i=0; i<NUM_MIXER_CHANNELS; i++)
693   {
694     if (!playlist[i].active || playlist[i].loop)
695       continue;
696
697     playlist[i].playingpos = voice_get_position(playlist[i].voice);
698     playlist[i].volume = voice_get_volume(playlist[i].voice);
699     if (playlist[i].playingpos == -1 || !playlist[i].volume)
700     {
701       deallocate_voice(playlist[i].voice);
702       playlist[i] = emptySoundControl;
703       playing_sounds--;
704     }
705   }
706
707   if (snd_ctrl.active)
708     SoundServer_InsertNewSound(snd_ctrl);
709 }
710 #endif /* PLATFORM_MSDOS */
711
712 #if 0
713 #if defined(TARGET_SDL)
714 static void sound_handler_SDL(struct SoundControl snd_ctrl)
715 {
716   /* copy sound_handler() here ... */
717 }
718 #endif /* TARGET_SDL */
719 #endif
720
721 #if !defined(PLATFORM_WIN32)
722 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
723 {
724   SoundInfo *snd_info;
725   int i, k;
726
727 #if 0
728   printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
729 #endif
730
731   if (IS_MUSIC(snd_ctrl))
732     snd_ctrl.nr = snd_ctrl.nr % num_music;
733   else if (snd_ctrl.nr >= num_sounds)
734     return;
735
736   snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
737   if (snd_info == NULL)
738   {
739 #if 0
740     printf("sound/music %d undefined\n", snd_ctrl.nr);
741 #endif
742     return;
743   }
744
745 #if 0
746   printf("-> %d\n", playing_sounds);
747 #endif
748
749   if (playing_sounds == NUM_MIXER_CHANNELS)
750   {
751     for (i=0; i<NUM_MIXER_CHANNELS; i++)
752     {
753       if (playlist[i].data_ptr == NULL)
754       {
755 #if 1
756         printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
757 #endif
758
759         playlist[i] = emptySoundControl;
760         playing_sounds--;
761       }
762     }
763   }
764
765   /* if playlist is full, remove oldest sound */
766   if (playing_sounds == NUM_MIXER_CHANNELS)
767   {
768     int longest = 0, longest_nr = 0;
769
770     for (i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
771     {
772 #if !defined(PLATFORM_MSDOS)
773       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
774 #else
775       int actual = playlist[i].playingpos;
776 #endif
777
778       if (!IS_LOOP(playlist[i]) && actual > longest)
779       {
780         longest = actual;
781         longest_nr = i;
782       }
783     }
784 #if defined(PLATFORM_MSDOS)
785     voice_set_volume(playlist[longest_nr].voice, 0);
786     deallocate_voice(playlist[longest_nr].voice);
787 #endif
788     playlist[longest_nr] = emptySoundControl;
789     playing_sounds--;
790   }
791
792   /* check if sound is already being played (and how often) */
793   for (k=0, i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
794     if (playlist[i].nr == snd_ctrl.nr)
795       k++;
796
797   /* restart loop sounds only if they are just fading out */
798   if (k >= 1 && IS_LOOP(snd_ctrl))
799   {
800     for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
801     {
802       if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
803       {
804         playlist[i].state &= ~SND_CTRL_FADE;
805         playlist[i].volume = PSND_MAX_VOLUME;
806 #if defined(PLATFORM_MSDOS)
807         playlist[i].state |= SND_CTRL_LOOP;
808         voice_stop_volumeramp(playlist[i].voice);
809         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
810 #endif
811       }
812     }
813
814     return;
815   }
816
817   /* don't play sound more than n times simultaneously (with n == 2 for now) */
818   if (k >= 2)
819   {
820     int longest = 0, longest_nr = 0;
821
822     /* look for oldest equal sound */
823     for(i=FIRST_SOUND_CHANNEL; i<NUM_MIXER_CHANNELS; i++)
824     {
825       int actual;
826
827       if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
828         continue;
829
830 #if !defined(PLATFORM_MSDOS)
831       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
832 #else
833       actual = playlist[i].playingpos;
834 #endif
835       if (actual >= longest)
836       {
837         longest = actual;
838         longest_nr = i;
839       }
840     }
841
842 #if defined(PLATFORM_MSDOS)
843     voice_set_volume(playlist[longest_nr].voice, 0);
844     deallocate_voice(playlist[longest_nr].voice);
845 #endif
846     playlist[longest_nr] = emptySoundControl;
847     playing_sounds--;
848   }
849
850   /* add new sound to playlist */
851   for(i=0; i<NUM_MIXER_CHANNELS; i++)
852   {
853 #if 0
854     printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
855 #endif
856
857     /*
858     if (!playlist[i].active ||
859         (IS_MUSIC(snd_ctrl) && i == MUSIC_CHANNEL))
860     */
861     if ((i == MUSIC_CHANNEL && IS_MUSIC(snd_ctrl)) ||
862         (i != MUSIC_CHANNEL && !playlist[i].active))
863     {
864       snd_ctrl.data_ptr = snd_info->data_ptr;
865       snd_ctrl.data_len = snd_info->data_len;
866       snd_ctrl.format   = snd_info->format;
867
868 #if 1
869       if (snd_info->data_len == 0)
870       {
871         printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
872       }
873 #endif
874
875 #if 1
876       if (IS_MUSIC(snd_ctrl) && i == MUSIC_CHANNEL && playlist[i].active)
877       {
878         printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
879
880 #if 1
881         playlist[i] = emptySoundControl;
882         playing_sounds--;
883 #endif
884       }
885 #endif
886
887       playlist[i] = snd_ctrl;
888       playing_sounds++;
889
890 #if 0
891       printf("NEW SOUND %d ADDED TO PLAYLIST\n", snd_ctrl.nr);
892 #endif
893
894 #if defined(PLATFORM_MSDOS)
895       playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
896
897       if (snd_ctrl.loop)
898         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
899
900       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
901       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
902       voice_start(playlist[i].voice);       
903 #endif
904       break;
905     }
906   }
907 }
908 #endif /* !PLATFORM_WIN32 */
909
910 /*
911 void SoundServer_FadeSound(int nr)
912 {
913   int i;
914
915   if (!playing_sounds)
916     return;
917
918   for(i=0;i<NUM_MIXER_CHANNELS;i++)
919     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
920       playlist[i].fade_sound = TRUE;
921 }
922 */
923
924 #if !defined(PLATFORM_WIN32)
925 #if defined(PLATFORM_MSDOS)
926 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
927 {
928   int nr = snd_ctrl.nr;
929   int i;
930
931   if (!playing_sounds)
932     return;
933
934   for(i=0; i<NUM_MIXER_CHANNELS; i++)
935   {
936     if ((i == audio.music_channel && snd_ctrl.music) ||
937         (i != audio.music_channel && playlist[i].nr == nr))
938     {
939 #if defined(PLATFORM_MSDOS)
940       voice_set_volume(playlist[i].voice, 0);
941       deallocate_voice(playlist[i].voice);
942 #endif
943       playlist[i] = emptySoundControl;
944       playing_sounds--;
945     }
946   }
947
948 #if !defined(PLATFORM_MSDOS)
949   if (!playing_sounds)
950     close(audio.device_fd);
951 #endif
952 }
953
954 static void SoundServer_StopAllSounds()
955 {
956   int i;
957
958   for(i=0; i<NUM_MIXER_CHANNELS; i++)
959   {
960 #if defined(PLATFORM_MSDOS)
961     voice_set_volume(playlist[i].voice, 0);
962     deallocate_voice(playlist[i].voice);
963 #endif
964     playlist[i] = emptySoundControl;
965   }
966   playing_sounds = 0;
967
968 #if !defined(PLATFORM_MSDOS)
969   close(audio.device_fd);
970 #endif
971 }
972 #endif /* PLATFORM_MSDOS */
973 #endif /* !PLATFORM_WIN32 */
974
975
976 /* ------------------------------------------------------------------------- */
977 /* platform dependant audio initialization code                              */
978 /* ------------------------------------------------------------------------- */
979
980 #if defined(AUDIO_LINUX_IOCTL)
981 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
982 {
983   /* "ioctl()" expects pointer to 'int' value for stereo flag
984      (boolean is defined as 'char', which will not work here) */
985   unsigned int fragment_spec = 0;
986   int fragment_size_query;
987   int stereo = TRUE;
988   struct
989   {
990     int format_ioctl;
991     int format_result;
992   }
993   formats[] =
994   {
995     /* supported audio format in preferred order */
996     { AFMT_S16_LE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
997     { AFMT_S16_BE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
998     { AFMT_U8,          AUDIO_FORMAT_U8                    },
999     { -1,               -1 }
1000   };
1001   int i;
1002
1003   /* determine logarithm (log2) of the fragment size */
1004   while ((1 << fragment_spec) < afmt->fragment_size)
1005     fragment_spec++;
1006
1007   /* use two fragments (play one fragment, prepare the other);
1008      one fragment would result in interrupted audio output, more
1009      than two fragments would raise audio output latency to much */
1010   fragment_spec |= 0x00020000;
1011
1012   /* Example for fragment specification:
1013      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
1014      - (with stereo the effective buffer size will shrink to 256)
1015      => fragment_size = 0x00020009 */
1016
1017   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
1018     Error(ERR_EXIT_SOUND_SERVER,
1019           "cannot set fragment size of /dev/dsp -- no sounds");
1020
1021   i = 0;
1022   afmt->format = 0;
1023   while (formats[i].format_result != -1)
1024   {
1025     unsigned int audio_format = formats[i].format_ioctl;
1026     if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
1027     {
1028       afmt->format = formats[i].format_result;
1029       break;
1030     }
1031   }
1032
1033   if (afmt->format == 0)        /* no supported audio format found */
1034     Error(ERR_EXIT_SOUND_SERVER,
1035           "cannot set audio format of /dev/dsp -- no sounds");
1036
1037   /* try if we can use stereo sound */
1038   afmt->stereo = TRUE;
1039   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
1040     afmt->stereo = FALSE;
1041
1042   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
1043     Error(ERR_EXIT_SOUND_SERVER,
1044           "cannot set sample rate of /dev/dsp -- no sounds");
1045
1046   /* get the real fragmentation size; this should return 512 */
1047   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
1048     Error(ERR_EXIT_SOUND_SERVER,
1049           "cannot get fragment size of /dev/dsp -- no sounds");
1050   if (fragment_size_query != afmt->fragment_size)
1051     Error(ERR_EXIT_SOUND_SERVER,
1052           "cannot set fragment size of /dev/dsp -- no sounds");
1053 }
1054 #endif  /* AUDIO_LINUX_IOCTL */
1055
1056 #if defined(PLATFORM_NETBSD)
1057 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1058 {
1059   audio_info_t a_info;
1060   boolean stereo = TRUE;
1061
1062   AUDIO_INITINFO(&a_info);
1063   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1064   a_info.play.precision = 8;
1065   a_info.play.channels = 2;
1066   a_info.play.sample_rate = sample_rate;
1067   a_info.blocksize = fragment_size;
1068
1069   afmt->format = AUDIO_FORMAT_U8;
1070   afmt->stereo = TRUE;
1071
1072   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1073   {
1074     /* try to disable stereo */
1075     a_info.play.channels = 1;
1076
1077     afmt->stereo = FALSE;
1078
1079     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1080       Error(ERR_EXIT_SOUND_SERVER,
1081             "cannot set sample rate of /dev/audio -- no sounds");
1082   }
1083 }
1084 #endif /* PLATFORM_NETBSD */
1085
1086 #if defined(PLATFORM_HPUX)
1087 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1088 {
1089   struct audio_describe ainfo;
1090   int audio_ctl;
1091
1092   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1093   if (audio_ctl == -1)
1094     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1095
1096   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1097     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1098
1099   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1100     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1101
1102   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1103   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1104
1105   afmt->format = AUDIO_FORMAT_U8;
1106   afmt->stereo = FALSE;
1107   afmt->sample_rate = 8000;
1108
1109   close(audio_ctl);
1110 }
1111 #endif /* PLATFORM_HPUX */
1112
1113 #if defined(PLATFORM_UNIX)
1114 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
1115 {
1116 #if defined(AUDIO_LINUX_IOCTL)
1117   InitAudioDevice_Linux(afmt);
1118 #elif defined(PLATFORM_NETBSD)
1119   InitAudioDevice_NetBSD(afmt);
1120 #elif defined(PLATFORM_HPUX)
1121   InitAudioDevice_HPUX(afmt);
1122 #endif
1123 }
1124 #endif /* PLATFORM_UNIX */
1125
1126 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1127
1128 /* these two are stolen from "sox"... :) */
1129
1130 /*
1131 ** This routine converts from linear to ulaw.
1132 **
1133 ** Craig Reese: IDA/Supercomputing Research Center
1134 ** Joe Campbell: Department of Defense
1135 ** 29 September 1989
1136 **
1137 ** References:
1138 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1139 ** 2) "A New Digital Technique for Implementation of Any
1140 **     Continuous PCM Companding Law," Villeret, Michel,
1141 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1142 **     1973, pg. 11.12-11.17
1143 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1144 **     for Analog-to_Digital Conversion Techniques,"
1145 **     17 February 1987
1146 **
1147 ** Input: Signed 16 bit linear sample
1148 ** Output: 8 bit ulaw sample
1149 */
1150
1151 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
1152 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
1153 #define CLIP 32635
1154
1155 static unsigned char linear_to_ulaw(int sample)
1156 {
1157   static int exp_lut[256] =
1158   {
1159     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1160     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1161     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1162     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1163     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1164     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1165     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1166     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1167     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1168     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1169     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1170     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1171     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1172     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1173     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1174     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1175   };
1176
1177   int sign, exponent, mantissa;
1178   unsigned char ulawbyte;
1179
1180   /* Get the sample into sign-magnitude. */
1181   sign = (sample >> 8) & 0x80;          /* set aside the sign */
1182   if (sign != 0)
1183     sample = -sample;                   /* get magnitude */
1184   if (sample > CLIP)
1185     sample = CLIP;                      /* clip the magnitude */
1186
1187   /* Convert from 16 bit linear to ulaw. */
1188   sample = sample + BIAS;
1189   exponent = exp_lut[( sample >> 7 ) & 0xFF];
1190   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1191   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1192 #ifdef ZEROTRAP
1193   if (ulawbyte == 0)
1194     ulawbyte = 0x02;                    /* optional CCITT trap */
1195 #endif
1196
1197   return(ulawbyte);
1198 }
1199
1200 /*
1201 ** This routine converts from ulaw to 16 bit linear.
1202 **
1203 ** Craig Reese: IDA/Supercomputing Research Center
1204 ** 29 September 1989
1205 **
1206 ** References:
1207 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1208 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1209 **     for Analog-to_Digital Conversion Techniques,"
1210 **     17 February 1987
1211 **
1212 ** Input: 8 bit ulaw sample
1213 ** Output: signed 16 bit linear sample
1214 */
1215
1216 static int ulaw_to_linear(unsigned char ulawbyte)
1217 {
1218   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1219   int sign, exponent, mantissa, sample;
1220
1221   ulawbyte = ~ ulawbyte;
1222   sign = ( ulawbyte & 0x80 );
1223   exponent = ( ulawbyte >> 4 ) & 0x07;
1224   mantissa = ulawbyte & 0x0F;
1225   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1226   if (sign != 0)
1227     sample = -sample;
1228
1229   return(sample);
1230 }
1231 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1232
1233
1234 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1235 /* ========================================================================= */
1236 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1237
1238 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1239 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1240
1241 static SoundInfo *Load_WAV(char *filename)
1242 {
1243   SoundInfo *snd_info;
1244 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1245   byte sound_header_buffer[WAV_HEADER_SIZE];
1246   char chunk_name[CHUNK_ID_LEN + 1];
1247   int chunk_size;
1248   FILE *file;
1249   int i;
1250 #endif
1251
1252   if (!audio.sound_available)
1253     return NULL;
1254
1255 #if 0
1256   printf("loading WAV file '%s'\n", filename);
1257 #endif
1258
1259   snd_info = checked_calloc(sizeof(SoundInfo));
1260
1261 #if defined(TARGET_SDL)
1262
1263   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1264   {
1265     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1266     free(snd_info);
1267     return NULL;
1268   }
1269
1270 #elif defined(TARGET_ALLEGRO)
1271
1272   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1273   {
1274     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1275     free(snd_info);
1276     return NULL;
1277   }
1278
1279 #else   /* PLATFORM_UNIX */
1280
1281   if ((file = fopen(filename, MODE_READ)) == NULL)
1282   {
1283     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1284     free(snd_info);
1285     return NULL;
1286   }
1287
1288   /* read chunk id "RIFF" */
1289   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1290   if (strcmp(chunk_name, "RIFF") != 0)
1291   {
1292     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1293     fclose(file);
1294     free(snd_info);
1295     return NULL;
1296   }
1297
1298   /* read "RIFF" type id "WAVE" */
1299   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1300   if (strcmp(chunk_name, "WAVE") != 0)
1301   {
1302     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1303     fclose(file);
1304     free(snd_info);
1305     return NULL;
1306   }
1307
1308   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1309   {
1310     if (strcmp(chunk_name, "fmt ") == 0)
1311     {
1312       /* read header information */
1313       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1314         sound_header_buffer[i] = fgetc(file);
1315
1316       if (chunk_size > WAV_HEADER_SIZE)
1317         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1318     }
1319     else if (strcmp(chunk_name, "data") == 0)
1320     {
1321       snd_info->data_len = chunk_size;
1322       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1323
1324       /* read sound data */
1325       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1326           snd_info->data_len)
1327       {
1328         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1329         fclose(file);
1330         free(snd_info->data_ptr);
1331         free(snd_info);
1332         return NULL;
1333       }
1334
1335       /* check for odd number of sample bytes (data chunk is word aligned) */
1336       if ((chunk_size % 2) == 1)
1337         ReadUnusedBytesFromFile(file, 1);
1338     }
1339     else        /* unknown chunk -- ignore */
1340       ReadUnusedBytesFromFile(file, chunk_size);
1341   }
1342
1343   fclose(file);
1344
1345   if (snd_info->data_ptr == NULL)
1346   {
1347     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1348     free(snd_info);
1349     return NULL;
1350   }
1351
1352   snd_info->format = AUDIO_FORMAT_U8;
1353
1354 #endif  /* PLATFORM_UNIX */
1355
1356   snd_info->type = SND_TYPE_WAV;
1357   snd_info->source_filename = getStringCopy(filename);
1358
1359   return snd_info;
1360 }
1361
1362 static void deleteSoundEntry(SoundInfo **snd_info)
1363 {
1364   if (*snd_info)
1365   {
1366     char *filename = (*snd_info)->source_filename;
1367
1368 #if 0
1369     printf("[decrementing reference counter of sound '%s']\n", filename);
1370 #endif
1371
1372     if (--(*snd_info)->num_references <= 0)
1373     {
1374 #if 0
1375       printf("[deleting sound '%s']\n", filename);
1376 #endif
1377
1378       /*
1379       FreeSound(*snd_info);
1380       */
1381       deleteNodeFromList(&SoundFileList, filename, FreeSound);
1382     }
1383
1384     *snd_info = NULL;
1385   }
1386 }
1387
1388 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1389 {
1390   ListNode *node;
1391
1392   /* check if the old and the new sound file are the same */
1393   if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1394   {
1395     /* The old and new sound are the same (have the same filename and path).
1396        This usually means that this sound does not exist in this sound set
1397        and a fallback to the existing sound is done. */
1398
1399 #if 0
1400     printf("[sound '%s' already exists (same list entry)]\n", filename);
1401 #endif
1402
1403     return;
1404   }
1405
1406   /* delete existing sound file entry */
1407   deleteSoundEntry(snd_info);
1408
1409   /* check if the new sound file already exists in the list of sounds */
1410   if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1411   {
1412 #if 0
1413       printf("[sound '%s' already exists (other list entry)]\n", filename);
1414 #endif
1415
1416       *snd_info = (SoundInfo *)node->content;
1417       (*snd_info)->num_references++;
1418   }
1419   else if ((*snd_info = Load_WAV(filename)) != NULL)    /* load new sound */
1420   {
1421     (*snd_info)->num_references = 1;
1422     addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1423   }
1424 }
1425
1426 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1427 {
1428   char *filename = getCustomSoundFilename(basename);
1429
1430   if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1431   {
1432     deleteSoundEntry(snd_info);
1433     return;
1434   }
1435
1436   if (filename == NULL)
1437   {
1438     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1439     return;
1440   }
1441
1442   replaceSoundEntry(snd_info, filename);
1443 }
1444
1445 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1446 {
1447   if (Sound == NULL)
1448     Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1449
1450   sound_effect = sounds_list;
1451   num_sounds = num_list_entries;
1452 }
1453
1454 void LoadSoundToList(char *basename, int list_pos)
1455 {
1456   if (Sound == NULL || list_pos >= num_sounds)
1457     return;
1458
1459 #if 0
1460   printf("loading sound '%s' ...  [%d]\n",
1461          basename, getNumNodes(SoundFileList));
1462 #endif
1463
1464   LoadCustomSound(&Sound[list_pos], basename);
1465
1466 #if 0
1467   printf("loading sound '%s' done [%d]\n",
1468          basename, getNumNodes(SoundFileList));
1469 #endif
1470 }
1471
1472 static MusicInfo *Load_MOD(char *filename)
1473 {
1474 #if defined(TARGET_SDL)
1475   MusicInfo *mod_info;
1476
1477   if (!audio.sound_available)
1478     return NULL;
1479
1480   mod_info = checked_calloc(sizeof(MusicInfo));
1481
1482   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1483   {
1484     Error(ERR_WARN, "cannot read music file '%s'", filename);
1485     free(mod_info);
1486     return NULL;
1487   }
1488
1489   mod_info->type = MUS_TYPE_MOD;
1490   mod_info->source_filename = getStringCopy(filename);
1491
1492   return mod_info;
1493 #else
1494   return NULL;
1495 #endif
1496 }
1497
1498 void LoadCustomMusic(void)
1499 {
1500   char *music_directory = getCustomMusicDirectory();
1501   DIR *dir;
1502   struct dirent *dir_entry;
1503
1504   if (!audio.sound_available)
1505     return;
1506
1507   if ((dir = opendir(music_directory)) == NULL)
1508   {
1509     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1510     audio.music_available = FALSE;
1511     return;
1512   }
1513
1514   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1515   {
1516     char *basename = dir_entry->d_name;
1517     char *filename = getPath2(music_directory, basename);
1518     MusicInfo *mus_info = NULL;
1519
1520     if (FileIsSound(basename))
1521       mus_info = Load_WAV(filename);
1522     else if (FileIsMusic(basename))
1523       mus_info = Load_MOD(filename);
1524
1525     free(filename);
1526
1527     if (mus_info)
1528     {
1529       num_music++;
1530       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1531       Music[num_music -1] = mus_info;
1532     }
1533   }
1534
1535   closedir(dir);
1536
1537   if (num_music == 0)
1538     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1539           music_directory);
1540 }
1541
1542 void PlayMusic(int nr)
1543 {
1544   if (!audio.music_available)
1545     return;
1546
1547 #if defined(TARGET_SDL)
1548
1549   nr = nr % num_music;
1550
1551   if (Music[nr]->type == MUS_TYPE_MOD)
1552   {
1553     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1554     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1555   }
1556   else                          /* play WAV music loop */
1557   {
1558     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1559     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1560   }
1561
1562 #else
1563
1564   PlaySoundMusic(nr);
1565
1566 #endif
1567 }
1568
1569 void PlaySound(int nr)
1570 {
1571   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1572 }
1573
1574 void PlaySoundStereo(int nr, int stereo)
1575 {
1576   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1577 }
1578
1579 void PlaySoundLoop(int nr)
1580 {
1581   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1582 }
1583
1584 void PlaySoundMusic(int nr)
1585 {
1586   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1587 }
1588
1589 void PlaySoundExt(int nr, int volume, int stereo, int state)
1590 {
1591   struct SoundControl snd_ctrl = emptySoundControl;
1592
1593   if (!audio.sound_available ||
1594       !audio.sound_enabled ||
1595       audio.sound_deactivated)
1596     return;
1597
1598   if (volume < PSND_MIN_VOLUME)
1599     volume = PSND_MIN_VOLUME;
1600   else if (volume > PSND_MAX_VOLUME)
1601     volume = PSND_MAX_VOLUME;
1602
1603   if (stereo < PSND_MAX_LEFT)
1604     stereo = PSND_MAX_LEFT;
1605   else if (stereo > PSND_MAX_RIGHT)
1606     stereo = PSND_MAX_RIGHT;
1607
1608   snd_ctrl.active = TRUE;
1609   snd_ctrl.nr     = nr;
1610   snd_ctrl.volume = volume;
1611   snd_ctrl.stereo = stereo;
1612   snd_ctrl.state  = state;
1613
1614 #if defined(TARGET_SDL)
1615   if (Sound[nr])
1616   {
1617     Mix_Volume(-1, SOUND_MAX_VOLUME);
1618     Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1619   }
1620 #elif defined(PLATFORM_UNIX)
1621   if (audio.soundserver_pid == 0)       /* we are child process */
1622     return;
1623
1624   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1625   {
1626     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1627     audio.sound_available = audio.sound_enabled = FALSE;
1628     return;
1629   }
1630 #elif defined(PLATFORM_MSDOS)
1631   sound_handler(snd_ctrl);
1632 #endif
1633 }
1634
1635 void FadeMusic(void)
1636 {
1637   if (!audio.sound_available)
1638     return;
1639
1640 #if defined(TARGET_SDL)
1641   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1642   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1643 #else
1644   StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1645 #endif
1646 }
1647
1648 void FadeSound(int nr)
1649 {
1650   StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1651 }
1652
1653 void FadeSounds()
1654 {
1655   FadeMusic();
1656   StopSoundExt(-1, SND_CTRL_FADE_ALL);
1657 }
1658
1659 void StopMusic(void)
1660 {
1661 #if defined(TARGET_SDL)
1662   if (!audio.sound_available)
1663     return;
1664
1665   Mix_HaltMusic();
1666   Mix_HaltChannel(audio.music_channel);
1667 #else
1668   StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1669 #endif
1670 }
1671
1672 void StopSound(int nr)
1673 {
1674   StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1675 }
1676
1677 void StopSounds()
1678 {
1679   StopMusic();
1680   StopSoundExt(-1, SND_CTRL_STOP_ALL);
1681 }
1682
1683 void StopSoundExt(int nr, int state)
1684 {
1685   struct SoundControl snd_ctrl = emptySoundControl;
1686
1687   if (!audio.sound_available)
1688     return;
1689
1690   snd_ctrl.nr    = nr;
1691   snd_ctrl.state = state;
1692
1693 #if defined(TARGET_SDL)
1694
1695   if (state & SND_CTRL_FADE)
1696   {
1697     int i;
1698
1699     for (i=0; i<audio.channels; i++)
1700       if (i != audio.music_channel || snd_ctrl.music)
1701         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1702     if (state & SND_CTRL_MUSIC)
1703       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1704   }
1705   else
1706   {
1707     int i;
1708
1709     for (i=0; i<audio.channels; i++)
1710       if (i != audio.music_channel || snd_ctrl.music)
1711         Mix_HaltChannel(i);
1712     if (state & SND_CTRL_MUSIC)
1713       Mix_HaltMusic();
1714   }
1715
1716 #elif !defined(PLATFORM_MSDOS)
1717
1718   if (audio.soundserver_pid == 0)       /* we are child process */
1719     return;
1720
1721   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1722   {
1723     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1724     audio.sound_available = audio.sound_enabled = FALSE;
1725     return;
1726   }
1727 #else /* PLATFORM_MSDOS */
1728   sound_handler(snd_ctrl);
1729 #endif
1730 }
1731
1732 ListNode *newListNode()
1733 {
1734   return checked_calloc(sizeof(ListNode));
1735 }
1736
1737 void addNodeToList(ListNode **node_first, char *key, void *content)
1738 {
1739   ListNode *node_new = newListNode();
1740
1741 #if 0
1742   printf("LIST: adding node with key '%s'\n", key);
1743 #endif
1744
1745   node_new->key = getStringCopy(key);
1746   node_new->content = content;
1747   node_new->next = *node_first;
1748   *node_first = node_new;
1749 }
1750
1751 void deleteNodeFromList(ListNode **node_first, char *key,
1752                         void (*destructor_function)(void *))
1753 {
1754   if (node_first == NULL || *node_first == NULL)
1755     return;
1756
1757 #if 0
1758   printf("[CHECKING LIST KEY '%s' == '%s']\n",
1759          (*node_first)->key, key);
1760 #endif
1761
1762   if (strcmp((*node_first)->key, key) == 0)
1763   {
1764 #if 0
1765     printf("[DELETING LIST ENTRY]\n");
1766 #endif
1767
1768     free((*node_first)->key);
1769     if (destructor_function)
1770       destructor_function((*node_first)->content);
1771     *node_first = (*node_first)->next;
1772   }
1773   else
1774     deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1775 }
1776
1777 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1778 {
1779   if (node_first == NULL)
1780     return NULL;
1781
1782   if (strcmp(node_first->key, key) == 0)
1783     return node_first;
1784   else
1785     return getNodeFromKey(node_first->next, key);
1786 }
1787
1788 int getNumNodes(ListNode *node_first)
1789 {
1790   return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1791 }
1792
1793 void dumpList(ListNode *node_first)
1794 {
1795   ListNode *node = node_first;
1796
1797   while (node)
1798   {
1799     printf("['%s' (%d)]\n", node->key,
1800            ((SoundInfo *)node->content)->num_references);
1801     node = node->next;
1802   }
1803
1804   printf("[%d nodes]\n", getNumNodes(node_first));
1805 }
1806
1807 static void LoadSoundsInfo()
1808 {
1809   char *filename = getCustomSoundConfigFilename();
1810   struct SetupFileList *setup_file_list;
1811   int i;
1812
1813   /* always start with reliable default values */
1814   for (i=0; i<num_sounds; i++)
1815     sound_effect[i].filename = NULL;
1816
1817   if (filename == NULL)
1818     return;
1819
1820   if ((setup_file_list = loadSetupFileList(filename)))
1821   {
1822     for (i=0; i<num_sounds; i++)
1823       sound_effect[i].filename =
1824         getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1825
1826     freeSetupFileList(setup_file_list);
1827
1828 #if 1
1829     for (i=0; i<num_sounds; i++)
1830     {
1831       printf("'%s' ", sound_effect[i].text);
1832       if (sound_effect[i].filename)
1833         printf("-> '%s'\n", sound_effect[i].filename);
1834       else
1835         printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1836     }
1837 #endif
1838   }
1839 }
1840
1841 static void ReloadCustomSounds()
1842 {
1843   int i;
1844
1845 #if 0
1846   printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1847 #endif
1848
1849   LoadSoundsInfo();
1850
1851 #if 0
1852   printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1853 #endif
1854
1855   for(i=0; i<num_sounds; i++)
1856   {
1857     if (sound_effect[i].filename)
1858       LoadSoundToList(sound_effect[i].filename, i);
1859     else
1860       LoadSoundToList(sound_effect[i].default_filename, i);
1861   }
1862
1863   /*
1864   printf("list size == %d\n", getNumNodes(SoundFileList));
1865   */
1866
1867 #if 0
1868   dumpList(SoundFileList);
1869 #endif
1870 }
1871
1872 static void ReloadCustomMusic()
1873 {
1874 #if 0
1875   printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1876 #endif
1877
1878   FreeAllMusic();
1879
1880   LoadCustomMusic();
1881 }
1882
1883 static void InitReloadSoundsOrMusic(char *set_name, int type)
1884 {
1885 #if 0
1886 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1887   struct SoundControl snd_ctrl = emptySoundControl;
1888   TreeInfo *ti = (state == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
1889                   artwork.mus_current);
1890   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1891   unsigned long str_size2 = strlen(ti->basepath) + 1;
1892   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1893 #endif
1894 #endif
1895
1896   if (!audio.sound_available)
1897     return;
1898
1899 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1900   if (type == SND_CTRL_RELOAD_SOUNDS)
1901     ReloadCustomSounds();
1902   else
1903     ReloadCustomMusic();
1904 #elif defined(PLATFORM_UNIX)
1905   if (audio.soundserver_pid == 0)       /* we are child process */
1906     return;
1907
1908   if (leveldir_current == NULL)         /* should never happen */
1909     Error(ERR_EXIT, "leveldir_current == NULL");
1910
1911 #if 1
1912   WriteReloadInfoToPipe(set_name, type);
1913 #else
1914
1915   snd_ctrl.state = type;
1916   snd_ctrl.data_len = strlen(set_name) + 1;
1917
1918   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1919             sizeof(snd_ctrl)) < 0 ||
1920       write(audio.soundserver_pipe[1], set_name,
1921             snd_ctrl.data_len) < 0 ||
1922       write(audio.soundserver_pipe[1], leveldir_current,
1923             sizeof(TreeInfo)) < 0 ||
1924       write(audio.soundserver_pipe[1], ti,
1925             sizeof(TreeInfo)) < 0 ||
1926       write(audio.soundserver_pipe[1], &str_size1,
1927             sizeof(unsigned long)) < 0 ||
1928       write(audio.soundserver_pipe[1], &str_size2,
1929             sizeof(unsigned long)) < 0 ||
1930       write(audio.soundserver_pipe[1], &str_size3,
1931             sizeof(unsigned long)) < 0 ||
1932       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1933             str_size1) < 0 ||
1934       write(audio.soundserver_pipe[1], ti->basepath,
1935             str_size2) < 0 ||
1936       write(audio.soundserver_pipe[1], ti->fullpath,
1937             str_size3) < 0)
1938   {
1939     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1940     audio.sound_available = audio.sound_enabled = FALSE;
1941     return;
1942   }
1943 #endif
1944
1945 #endif
1946 }
1947
1948 void InitReloadSounds(char *set_name)
1949 {
1950   InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_SOUNDS);
1951 }
1952
1953 void InitReloadMusic(char *set_name)
1954 {
1955   InitReloadSoundsOrMusic(set_name, SND_CTRL_RELOAD_MUSIC);
1956 }
1957
1958 void FreeSound(void *ptr)
1959 {
1960   SoundInfo *sound = (SoundInfo *)ptr;
1961
1962   if (sound == NULL)
1963     return;
1964
1965   if (sound->data_ptr)
1966   {
1967 #if defined(TARGET_SDL)
1968     Mix_FreeChunk(sound->data_ptr);
1969 #elif defined(TARGET_ALLEGRO)
1970     destroy_sample(sound->data_ptr);
1971 #else   /* PLATFORM_UNIX */
1972     free(sound->data_ptr);
1973 #endif
1974   }
1975
1976   if (sound->source_filename)
1977     free(sound->source_filename);
1978
1979   free(sound);
1980 }
1981
1982 void FreeMusic(MusicInfo *music)
1983 {
1984   if (music == NULL)
1985     return;
1986
1987   if (music->data_ptr)
1988   {
1989 #if defined(TARGET_SDL)
1990     if (music->type == MUS_TYPE_MOD)
1991       Mix_FreeMusic(music->data_ptr);
1992     else
1993       Mix_FreeChunk(music->data_ptr);
1994 #elif defined(TARGET_ALLEGRO)
1995     destroy_sample(music->data_ptr);
1996 #else   /* PLATFORM_UNIX */
1997     free(music->data_ptr);
1998 #endif
1999   }
2000
2001   free(music);
2002 }
2003
2004 void FreeAllSounds()
2005 {
2006   int i;
2007
2008   if (Sound == NULL)
2009     return;
2010
2011   printf("%s: FREEING SOUNDS ...\n",
2012          audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2013
2014   for(i=0; i<num_sounds; i++)
2015     deleteSoundEntry(&Sound[i]);
2016   /*
2017     FreeSound(Sound[i]);
2018   */
2019
2020   printf("%s: FREEING SOUNDS -- DONE\n",
2021          audio.soundserver_pid == 0 ? "CHILD" : "PARENT");
2022
2023   free(Sound);
2024
2025   Sound = NULL;
2026   num_sounds = 0;
2027 }
2028
2029 void FreeAllMusic()
2030 {
2031   int i;
2032
2033   if (Music == NULL)
2034     return;
2035
2036   for(i=0; i<num_music; i++)
2037     FreeMusic(Music[i]);
2038
2039   free(Music);
2040
2041   Music = NULL;
2042   num_music = 0;
2043 }
2044
2045 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
2046 /* ========================================================================= */