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