rnd-20020430-3-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(void *);
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   ListNode *node;
1237
1238   if (filename == NULL)         /* (should never happen) */
1239   {
1240     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1241     return;
1242   }
1243
1244   if (*snd_info)
1245   {
1246     char *filename_old = (*snd_info)->source_filename;
1247
1248     if (strcmp(filename, filename_old) == 0)
1249     {
1250       /* The old and new sound are the same (have the same filename and path).
1251          This usually means that this sound does not exist in this sound set
1252          and a fallback to the existing sound is done. */
1253
1254 #if 1
1255       printf("[sound '%s' already exists (same list entry)]\n", filename);
1256 #endif
1257
1258       return;
1259     }
1260
1261 #if 1
1262     printf("[decrementing reference counter of sound '%s']\n", filename_old);
1263 #endif
1264
1265     if (--(*snd_info)->num_references <= 0)
1266     {
1267 #if 1
1268       printf("[deleting sound '%s']\n", filename_old);
1269 #endif
1270
1271       /*
1272       FreeSound(*snd_info);
1273       */
1274       deleteNodeFromList(&SoundFileList, filename_old, FreeSound);
1275     }
1276   }
1277
1278   /* check if this sound already exists in the list of sounds */
1279   node = getNodeFromKey(SoundFileList, filename);
1280   if (node)
1281   {
1282 #if 1
1283       printf("[sound '%s' already exists (other list entry)]\n", filename);
1284 #endif
1285
1286       *snd_info = (SoundInfo *)node->content;
1287       (*snd_info)->num_references++;
1288
1289       return;
1290   }
1291
1292   *snd_info = Load_WAV(filename);
1293   (*snd_info)->num_references = 1;
1294
1295   addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1296 }
1297
1298 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1299 {
1300   if (Sound == NULL)
1301     Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1302
1303   sound_effect = sounds_list;
1304   num_sounds = num_list_entries;
1305 }
1306
1307 void LoadSoundToList(char *basename, int list_pos)
1308 {
1309   if (Sound == NULL || list_pos >= num_sounds)
1310     return;
1311
1312   printf("loading sound '%s' ...  [%d]\n",
1313          basename, getNumNodes(SoundFileList));
1314
1315   LoadCustomSound(&Sound[list_pos], basename);
1316
1317   printf("loading sound '%s' done [%d]\n",
1318          basename, getNumNodes(SoundFileList));
1319 }
1320
1321 static MusicInfo *Load_MOD(char *filename)
1322 {
1323 #if defined(TARGET_SDL)
1324   MusicInfo *mod_info;
1325
1326   if (!audio.sound_available)
1327     return NULL;
1328
1329   mod_info = checked_calloc(sizeof(MusicInfo));
1330
1331   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1332   {
1333     Error(ERR_WARN, "cannot read music file '%s'", filename);
1334     free(mod_info);
1335     return NULL;
1336   }
1337
1338   mod_info->type = MUS_TYPE_MOD;
1339   mod_info->source_filename = getStringCopy(filename);
1340
1341   return mod_info;
1342 #else
1343   return NULL;
1344 #endif
1345 }
1346
1347 void LoadCustomMusic(void)
1348 {
1349   char *music_directory = getCustomMusicDirectory();
1350   DIR *dir;
1351   struct dirent *dir_entry;
1352
1353   if (!audio.sound_available)
1354     return;
1355
1356   if ((dir = opendir(music_directory)) == NULL)
1357   {
1358     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1359     audio.music_available = FALSE;
1360     return;
1361   }
1362
1363   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1364   {
1365     char *basename = dir_entry->d_name;
1366     char *filename = getPath2(music_directory, basename);
1367     MusicInfo *mus_info = NULL;
1368
1369     if (FileIsSound(basename))
1370       mus_info = Load_WAV(filename);
1371     else if (FileIsMusic(basename))
1372       mus_info = Load_MOD(filename);
1373
1374     free(filename);
1375
1376     if (mus_info)
1377     {
1378       num_music++;
1379       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1380       Music[num_music -1] = mus_info;
1381     }
1382   }
1383
1384   closedir(dir);
1385
1386   if (num_music == 0)
1387     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1388           music_directory);
1389 }
1390
1391 void PlayMusic(int nr)
1392 {
1393   if (!audio.music_available)
1394     return;
1395
1396 #if defined(TARGET_SDL)
1397
1398   nr = nr % num_music;
1399
1400   if (Music[nr]->type == MUS_TYPE_MOD)
1401   {
1402     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1403     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1404   }
1405   else                          /* play WAV music loop */
1406   {
1407     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1408     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1409   }
1410
1411 #else
1412
1413   PlaySoundMusic(nr);
1414
1415 #endif
1416 }
1417
1418 void PlaySound(int nr)
1419 {
1420   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1421 }
1422
1423 void PlaySoundStereo(int nr, int stereo)
1424 {
1425   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1426 }
1427
1428 void PlaySoundLoop(int nr)
1429 {
1430   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1431 }
1432
1433 void PlaySoundMusic(int nr)
1434 {
1435   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1436 }
1437
1438 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1439 {
1440   struct SoundControl snd_ctrl = emptySoundControl;
1441
1442   if (!audio.sound_available ||
1443       !audio.sound_enabled ||
1444       audio.sound_deactivated)
1445     return;
1446
1447   if (volume < PSND_MIN_VOLUME)
1448     volume = PSND_MIN_VOLUME;
1449   else if (volume > PSND_MAX_VOLUME)
1450     volume = PSND_MAX_VOLUME;
1451
1452   if (stereo < PSND_MAX_LEFT)
1453     stereo = PSND_MAX_LEFT;
1454   else if (stereo > PSND_MAX_RIGHT)
1455     stereo = PSND_MAX_RIGHT;
1456
1457   snd_ctrl.nr           = nr;
1458   snd_ctrl.volume       = volume;
1459   snd_ctrl.stereo       = stereo;
1460   snd_ctrl.loop         = (loop_type != PSND_NO_LOOP);
1461   snd_ctrl.music        = (loop_type == PSND_MUSIC);
1462   snd_ctrl.active       = TRUE;
1463
1464 #if 0
1465   /* now only used internally in sound server child process */
1466   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1467   snd_ctrl.data_len     = Sound[nr].data_len;
1468 #endif
1469
1470 #if defined(TARGET_SDL)
1471   Mix_Volume(-1, SOUND_MAX_VOLUME);
1472   Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1473 #elif defined(PLATFORM_UNIX)
1474   if (audio.soundserver_pid == 0)       /* we are child process */
1475     return;
1476
1477   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1478   {
1479     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1480     audio.sound_available = audio.sound_enabled = FALSE;
1481     return;
1482   }
1483 #elif defined(PLATFORM_MSDOS)
1484   sound_handler(snd_ctrl);
1485 #endif
1486 }
1487
1488 void FadeMusic(void)
1489 {
1490   if (!audio.sound_available)
1491     return;
1492
1493 #if defined(TARGET_SDL)
1494   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1495   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1496 #else
1497   StopSoundExt(-1, SSND_FADE_MUSIC);
1498 #endif
1499 }
1500
1501 void FadeSound(int nr)
1502 {
1503   StopSoundExt(nr, SSND_FADE_SOUND);
1504 }
1505
1506 void FadeSounds()
1507 {
1508   FadeMusic();
1509   StopSoundExt(-1, SSND_FADE_ALL);
1510 }
1511
1512 void StopMusic(void)
1513 {
1514 #if defined(TARGET_SDL)
1515   if (!audio.sound_available)
1516     return;
1517
1518   Mix_HaltMusic();
1519   Mix_HaltChannel(audio.music_channel);
1520 #else
1521   StopSoundExt(-1, SSND_STOP_MUSIC);
1522 #endif
1523 }
1524
1525 void StopSound(int nr)
1526 {
1527   StopSoundExt(nr, SSND_STOP_SOUND);
1528 }
1529
1530 void StopSounds()
1531 {
1532   StopSoundExt(-1, SSND_STOP_ALL);
1533 }
1534
1535 void StopSoundExt(int nr, int method)
1536 {
1537   struct SoundControl snd_ctrl = emptySoundControl;
1538
1539   if (!audio.sound_available)
1540     return;
1541
1542   if (method & SSND_FADING)
1543     snd_ctrl.fade_sound = TRUE;
1544
1545   if (method & SSND_ALL)
1546     snd_ctrl.stop_all_sounds = TRUE;
1547   else
1548   {
1549     snd_ctrl.stop_sound = TRUE;
1550     snd_ctrl.nr = nr;
1551   }
1552
1553   if (method & SSND_MUSIC)
1554     snd_ctrl.music = TRUE;
1555
1556 #if defined(TARGET_SDL)
1557
1558   if (method & SSND_FADING)
1559   {
1560     int i;
1561
1562     for (i=0; i<audio.channels; i++)
1563       if (i != audio.music_channel || snd_ctrl.music)
1564         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1565     if (snd_ctrl.music)
1566       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1567   }
1568   else
1569   {
1570     int i;
1571
1572     for (i=0; i<audio.channels; i++)
1573       if (i != audio.music_channel || snd_ctrl.music)
1574         Mix_HaltChannel(i);
1575     if (snd_ctrl.music)
1576       Mix_HaltMusic();
1577   }
1578
1579 #elif !defined(PLATFORM_MSDOS)
1580
1581   if (audio.soundserver_pid == 0)       /* we are child process */
1582     return;
1583
1584   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1585   {
1586     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1587     audio.sound_available = audio.sound_enabled = FALSE;
1588     return;
1589   }
1590 #else
1591   sound_handler(snd_ctrl);
1592 #endif
1593 }
1594
1595 ListNode *newListNode()
1596 {
1597   return checked_calloc(sizeof(ListNode));
1598 }
1599
1600 void addNodeToList(ListNode **node_first, char *key, void *content)
1601 {
1602   ListNode *node_new = newListNode();
1603
1604 #if 0
1605   printf("LIST: adding node with key '%s'\n", key);
1606 #endif
1607
1608   node_new->key = getStringCopy(key);
1609   node_new->content = content;
1610   node_new->next = *node_first;
1611   *node_first = node_new;
1612 }
1613
1614 void deleteNodeFromList(ListNode **node_first, char *key,
1615                         void (*destructor_function)(void *))
1616 {
1617   if (node_first == NULL || *node_first == NULL)
1618     return;
1619
1620   printf("[CHECKING LIST KEY '%s' == '%s']\n",
1621          (*node_first)->key, key);
1622
1623   if (strcmp((*node_first)->key, key) == 0)
1624   {
1625     printf("[DELETING LIST ENTRY]\n");
1626
1627     free((*node_first)->key);
1628     if (destructor_function)
1629       destructor_function((*node_first)->content);
1630     *node_first = (*node_first)->next;
1631   }
1632   else
1633     deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1634 }
1635
1636 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1637 {
1638   if (node_first == NULL)
1639     return NULL;
1640
1641   if (strcmp(node_first->key, key) == 0)
1642     return node_first;
1643   else
1644     return getNodeFromKey(node_first->next, key);
1645 }
1646
1647 int getNumNodes(ListNode *node_first)
1648 {
1649   return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1650 }
1651
1652 void dumpList(ListNode *node_first)
1653 {
1654   ListNode *node = node_first;
1655
1656   while (node)
1657   {
1658     printf("['%s' (%d)]\n", node->key,
1659            ((SoundInfo *)node->content)->num_references);
1660     node = node->next;
1661   }
1662
1663   printf("[%d nodes]\n", getNumNodes(node_first));
1664 }
1665
1666 static void LoadSoundsInfo()
1667 {
1668   char *filename = getCustomSoundConfigFilename();
1669   struct SetupFileList *setup_file_list;
1670   int i;
1671
1672   /* always start with reliable default values */
1673   for (i=0; i<num_sounds; i++)
1674     sound_effect[i].filename = NULL;
1675
1676   if (filename == NULL)
1677     return;
1678
1679   if ((setup_file_list = loadSetupFileList(filename)))
1680   {
1681     for (i=0; i<num_sounds; i++)
1682       sound_effect[i].filename =
1683         getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1684
1685     freeSetupFileList(setup_file_list);
1686
1687 #if 1
1688     for (i=0; i<num_sounds; i++)
1689     {
1690       printf("'%s' ", sound_effect[i].text);
1691       if (sound_effect[i].filename)
1692         printf("-> '%s'\n", sound_effect[i].filename);
1693       else
1694         printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1695     }
1696 #endif
1697   }
1698 }
1699
1700 static void ReloadCustomSounds()
1701 {
1702   int i;
1703
1704 #if 1
1705   printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1706 #endif
1707
1708   LoadSoundsInfo();
1709
1710   for(i=0; i<num_sounds; i++)
1711   {
1712     if (sound_effect[i].filename)
1713       LoadSoundToList(sound_effect[i].filename, i);
1714     else
1715       LoadSoundToList(sound_effect[i].default_filename, i);
1716   }
1717
1718   /*
1719   printf("list size == %d\n", getNumNodes(SoundFileList));
1720   */
1721   dumpList(SoundFileList);
1722 }
1723
1724 static void ReloadCustomMusic()
1725 {
1726 #if 1
1727   printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1728 #endif
1729
1730   FreeAllMusic();
1731
1732   LoadCustomMusic();
1733 }
1734
1735 static void InitReloadSoundsOrMusic(char *set_name, int type)
1736 {
1737 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1738   struct SoundControl snd_ctrl = emptySoundControl;
1739   TreeInfo *ti =
1740     (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1741   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1742   unsigned long str_size2 = strlen(ti->basepath) + 1;
1743   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1744 #endif
1745
1746   if (!audio.sound_available)
1747     return;
1748
1749 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1750   if (type == SND_RELOAD_SOUNDS)
1751     audio.func_reload_sounds();
1752   else
1753     audio.func_reload_music();
1754 #elif defined(PLATFORM_UNIX)
1755   if (audio.soundserver_pid == 0)       /* we are child process */
1756     return;
1757
1758   if (leveldir_current == NULL)         /* should never happen */
1759     Error(ERR_EXIT, "leveldir_current == NULL");
1760
1761   snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1762   snd_ctrl.reload_music  = (type == SND_RELOAD_MUSIC);
1763   snd_ctrl.data_len = strlen(set_name) + 1;
1764
1765   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1766             sizeof(snd_ctrl)) < 0 ||
1767       write(audio.soundserver_pipe[1], set_name,
1768             snd_ctrl.data_len) < 0 ||
1769       write(audio.soundserver_pipe[1], leveldir_current,
1770             sizeof(TreeInfo)) < 0 ||
1771       write(audio.soundserver_pipe[1], ti,
1772             sizeof(TreeInfo)) < 0 ||
1773       write(audio.soundserver_pipe[1], &str_size1,
1774             sizeof(unsigned long)) < 0 ||
1775       write(audio.soundserver_pipe[1], &str_size2,
1776             sizeof(unsigned long)) < 0 ||
1777       write(audio.soundserver_pipe[1], &str_size3,
1778             sizeof(unsigned long)) < 0 ||
1779       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1780             str_size1) < 0 ||
1781       write(audio.soundserver_pipe[1], ti->basepath,
1782             str_size2) < 0 ||
1783       write(audio.soundserver_pipe[1], ti->fullpath,
1784             str_size3) < 0)
1785   {
1786     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1787     audio.sound_available = audio.sound_enabled = FALSE;
1788     return;
1789   }
1790 #endif
1791 }
1792
1793 void InitReloadSounds(char *set_name)
1794 {
1795   InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1796 }
1797
1798 void InitReloadMusic(char *set_name)
1799 {
1800   InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1801 }
1802
1803 void FreeSound(void *ptr)
1804 {
1805   SoundInfo *sound = (SoundInfo *)ptr;
1806
1807   if (sound == NULL)
1808     return;
1809
1810   if (sound->data_ptr)
1811   {
1812 #if defined(TARGET_SDL)
1813     Mix_FreeChunk(sound->data_ptr);
1814 #elif defined(TARGET_ALLEGRO)
1815     destroy_sample(sound->data_ptr);
1816 #else   /* PLATFORM_UNIX */
1817     free(sound->data_ptr);
1818 #endif
1819   }
1820
1821   if (sound->source_filename)
1822     free(sound->source_filename);
1823
1824   free(sound);
1825 }
1826
1827 void FreeMusic(MusicInfo *music)
1828 {
1829   if (music == NULL)
1830     return;
1831
1832   if (music->data_ptr)
1833   {
1834 #if defined(TARGET_SDL)
1835     if (music->type == MUS_TYPE_MOD)
1836       Mix_FreeMusic(music->data_ptr);
1837     else
1838       Mix_FreeChunk(music->data_ptr);
1839 #elif defined(TARGET_ALLEGRO)
1840     destroy_sample(music->data_ptr);
1841 #else   /* PLATFORM_UNIX */
1842     free(music->data_ptr);
1843 #endif
1844   }
1845
1846   free(music);
1847 }
1848
1849 void FreeAllSounds()
1850 {
1851   int i;
1852
1853   if (Sound == NULL)
1854     return;
1855
1856   for(i=0; i<num_sounds; i++)
1857     FreeSound(Sound[i]);
1858
1859   free(Sound);
1860
1861   Sound = NULL;
1862   num_sounds = 0;
1863 }
1864
1865 void FreeAllMusic()
1866 {
1867   int i;
1868
1869   if (Music == NULL)
1870     return;
1871
1872   for(i=0; i<num_music; i++)
1873     FreeMusic(Music[i]);
1874
1875   free(Music);
1876
1877   Music = NULL;
1878   num_music = 0;
1879 }
1880
1881 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
1882 /* ========================================================================= */