rnd-20020505-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(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   SoundInfo *snd_info;
655   int i, k;
656
657   if (snd_ctrl.music)
658     snd_ctrl.nr = snd_ctrl.nr % num_music;
659   else if (snd_ctrl.nr >= num_sounds)
660     return;
661
662   snd_info = (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
663   if (snd_info == NULL)
664   {
665 #if 1
666     printf("sound/music %d undefined\n", snd_ctrl.nr);
667 #endif
668     return;
669   }
670
671   /* if playlist is full, remove oldest sound */
672   if (playing_sounds == MAX_SOUNDS_PLAYING)
673   {
674     int longest = 0, longest_nr = 0;
675
676     for (i=0; i<MAX_SOUNDS_PLAYING; i++)
677     {
678 #if !defined(PLATFORM_MSDOS)
679       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
680 #else
681       int actual = playlist[i].playingpos;
682 #endif
683
684       if (i != audio.music_channel && !playlist[i].loop && actual > longest)
685       {
686         longest = actual;
687         longest_nr = i;
688       }
689     }
690 #if defined(PLATFORM_MSDOS)
691     voice_set_volume(playlist[longest_nr].voice, 0);
692     deallocate_voice(playlist[longest_nr].voice);
693 #endif
694     playlist[longest_nr] = emptySoundControl;
695     playing_sounds--;
696   }
697
698   /* check if sound is already being played (and how often) */
699   for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
700     if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
701       k++;
702
703   /* restart loop sounds only if they are just fading out */
704   if (k >= 1 && snd_ctrl.loop)
705   {
706     for(i=0; i<MAX_SOUNDS_PLAYING; i++)
707     {
708       if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
709           playlist[i].fade_sound)
710       {
711         playlist[i].fade_sound = FALSE;
712         playlist[i].volume = PSND_MAX_VOLUME;
713 #if defined(PLATFORM_MSDOS)
714         playlist[i].loop = PSND_LOOP;
715         voice_stop_volumeramp(playlist[i].voice);
716         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
717 #endif
718       }
719     }
720
721     return;
722   }
723
724   /* don't play sound more than n times simultaneously (with n == 2 for now) */
725   if (k >= 2)
726   {
727     int longest = 0, longest_nr = 0;
728
729     /* look for oldest equal sound */
730     for(i=0; i<MAX_SOUNDS_PLAYING; i++)
731     {
732       int actual;
733
734       if (!playlist[i].active ||
735           i == audio.music_channel ||
736           playlist[i].nr != snd_ctrl.nr)
737         continue;
738
739 #if !defined(PLATFORM_MSDOS)
740       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
741 #else
742       actual = playlist[i].playingpos;
743 #endif
744       if (actual >= longest)
745       {
746         longest = actual;
747         longest_nr = i;
748       }
749     }
750
751 #if defined(PLATFORM_MSDOS)
752     voice_set_volume(playlist[longest_nr].voice, 0);
753     deallocate_voice(playlist[longest_nr].voice);
754 #endif
755     playlist[longest_nr] = emptySoundControl;
756     playing_sounds--;
757   }
758
759   /* add new sound to playlist */
760   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
761   {
762     if (!playlist[i].active ||
763         (snd_ctrl.music && i == audio.music_channel))
764     {
765       snd_ctrl.data_ptr = snd_info->data_ptr;
766       snd_ctrl.data_len = snd_info->data_len;
767       snd_ctrl.format   = snd_info->format;
768
769       playlist[i] = snd_ctrl;
770       playing_sounds++;
771
772 #if defined(PLATFORM_MSDOS)
773       playlist[i].voice = allocate_voice((SAMPLE *)playlist[i].data_ptr);
774
775       if (snd_ctrl.loop)
776         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
777
778       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
779       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
780       voice_start(playlist[i].voice);       
781 #endif
782       break;
783     }
784   }
785 }
786 #endif /* !PLATFORM_WIN32 */
787
788 /*
789 void SoundServer_FadeSound(int nr)
790 {
791   int i;
792
793   if (!playing_sounds)
794     return;
795
796   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
797     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
798       playlist[i].fade_sound = TRUE;
799 }
800 */
801
802 #if !defined(PLATFORM_WIN32)
803 #if defined(PLATFORM_MSDOS)
804 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
805 {
806   int nr = snd_ctrl.nr;
807   int i;
808
809   if (!playing_sounds)
810     return;
811
812   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
813   {
814     if ((i == audio.music_channel && snd_ctrl.music) ||
815         (i != audio.music_channel && playlist[i].nr == nr))
816     {
817 #if defined(PLATFORM_MSDOS)
818       voice_set_volume(playlist[i].voice, 0);
819       deallocate_voice(playlist[i].voice);
820 #endif
821       playlist[i] = emptySoundControl;
822       playing_sounds--;
823     }
824   }
825
826 #if !defined(PLATFORM_MSDOS)
827   if (!playing_sounds)
828     close(audio.device_fd);
829 #endif
830 }
831
832 static void SoundServer_StopAllSounds()
833 {
834   int i;
835
836   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
837   {
838 #if defined(PLATFORM_MSDOS)
839     voice_set_volume(playlist[i].voice, 0);
840     deallocate_voice(playlist[i].voice);
841 #endif
842     playlist[i]=emptySoundControl;
843   }
844   playing_sounds = 0;
845
846 #if !defined(PLATFORM_MSDOS)
847   close(audio.device_fd);
848 #endif
849 }
850 #endif /* PLATFORM_MSDOS */
851 #endif /* !PLATFORM_WIN32 */
852
853
854 /* ------------------------------------------------------------------------- */
855 /* platform dependant audio initialization code                              */
856 /* ------------------------------------------------------------------------- */
857
858 #if defined(AUDIO_LINUX_IOCTL)
859 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
860 {
861   /* "ioctl()" expects pointer to 'int' value for stereo flag
862      (boolean is defined as 'char', which will not work here) */
863   unsigned int fragment_spec = 0;
864   int fragment_size_query;
865   int stereo = TRUE;
866   struct
867   {
868     int format_ioctl;
869     int format_result;
870   }
871   formats[] =
872   {
873     /* supported audio format in preferred order */
874     { AFMT_S16_LE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
875     { AFMT_S16_BE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
876     { AFMT_U8,          AUDIO_FORMAT_U8                    },
877     { -1,               -1 }
878   };
879   int i;
880
881   /* determine logarithm (log2) of the fragment size */
882   while ((1 << fragment_spec) < afmt->fragment_size)
883     fragment_spec++;
884
885   /* use two fragments (play one fragment, prepare the other);
886      one fragment would result in interrupted audio output, more
887      than two fragments would raise audio output latency to much */
888   fragment_spec |= 0x00020000;
889
890   /* Example for fragment specification:
891      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
892      - (with stereo the effective buffer size will shrink to 256)
893      => fragment_size = 0x00020009 */
894
895   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
896     Error(ERR_EXIT_SOUND_SERVER,
897           "cannot set fragment size of /dev/dsp -- no sounds");
898
899   i = 0;
900   afmt->format = 0;
901   while (formats[i].format_result != -1)
902   {
903     unsigned int audio_format = formats[i].format_ioctl;
904     if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
905     {
906       afmt->format = formats[i].format_result;
907       break;
908     }
909   }
910
911   if (afmt->format == 0)        /* no supported audio format found */
912     Error(ERR_EXIT_SOUND_SERVER,
913           "cannot set audio format of /dev/dsp -- no sounds");
914
915   /* try if we can use stereo sound */
916   afmt->stereo = TRUE;
917   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
918     afmt->stereo = FALSE;
919
920   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
921     Error(ERR_EXIT_SOUND_SERVER,
922           "cannot set sample rate of /dev/dsp -- no sounds");
923
924   /* get the real fragmentation size; this should return 512 */
925   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
926     Error(ERR_EXIT_SOUND_SERVER,
927           "cannot get fragment size of /dev/dsp -- no sounds");
928   if (fragment_size_query != afmt->fragment_size)
929     Error(ERR_EXIT_SOUND_SERVER,
930           "cannot set fragment size of /dev/dsp -- no sounds");
931 }
932 #endif  /* AUDIO_LINUX_IOCTL */
933
934 #if defined(PLATFORM_NETBSD)
935 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
936 {
937   audio_info_t a_info;
938   boolean stereo = TRUE;
939
940   AUDIO_INITINFO(&a_info);
941   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
942   a_info.play.precision = 8;
943   a_info.play.channels = 2;
944   a_info.play.sample_rate = sample_rate;
945   a_info.blocksize = fragment_size;
946
947   afmt->format = AUDIO_FORMAT_U8;
948   afmt->stereo = TRUE;
949
950   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
951   {
952     /* try to disable stereo */
953     a_info.play.channels = 1;
954
955     afmt->stereo = FALSE;
956
957     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
958       Error(ERR_EXIT_SOUND_SERVER,
959             "cannot set sample rate of /dev/audio -- no sounds");
960   }
961 }
962 #endif /* PLATFORM_NETBSD */
963
964 #if defined(PLATFORM_HPUX)
965 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
966 {
967   struct audio_describe ainfo;
968   int audio_ctl;
969
970   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
971   if (audio_ctl == -1)
972     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
973
974   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
975     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
976
977   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
978     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
979
980   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
981   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
982
983   afmt->format = AUDIO_FORMAT_U8;
984   afmt->stereo = FALSE;
985   afmt->sample_rate = 8000;
986
987   close(audio_ctl);
988 }
989 #endif /* PLATFORM_HPUX */
990
991 #if defined(PLATFORM_UNIX)
992 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
993 {
994 #if defined(AUDIO_LINUX_IOCTL)
995   InitAudioDevice_Linux(afmt);
996 #elif defined(PLATFORM_NETBSD)
997   InitAudioDevice_NetBSD(afmt);
998 #elif defined(PLATFORM_HPUX)
999   InitAudioDevice_HPUX(afmt);
1000 #endif
1001 }
1002 #endif /* PLATFORM_UNIX */
1003
1004 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1005
1006 /* these two are stolen from "sox"... :) */
1007
1008 /*
1009 ** This routine converts from linear to ulaw.
1010 **
1011 ** Craig Reese: IDA/Supercomputing Research Center
1012 ** Joe Campbell: Department of Defense
1013 ** 29 September 1989
1014 **
1015 ** References:
1016 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1017 ** 2) "A New Digital Technique for Implementation of Any
1018 **     Continuous PCM Companding Law," Villeret, Michel,
1019 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1020 **     1973, pg. 11.12-11.17
1021 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1022 **     for Analog-to_Digital Conversion Techniques,"
1023 **     17 February 1987
1024 **
1025 ** Input: Signed 16 bit linear sample
1026 ** Output: 8 bit ulaw sample
1027 */
1028
1029 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
1030 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
1031 #define CLIP 32635
1032
1033 static unsigned char linear_to_ulaw(int sample)
1034 {
1035   static int exp_lut[256] =
1036   {
1037     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1038     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1039     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1040     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1041     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1042     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1043     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1044     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1045     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1046     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1047     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1048     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1049     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1050     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1051     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1052     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1053   };
1054
1055   int sign, exponent, mantissa;
1056   unsigned char ulawbyte;
1057
1058   /* Get the sample into sign-magnitude. */
1059   sign = (sample >> 8) & 0x80;          /* set aside the sign */
1060   if (sign != 0)
1061     sample = -sample;                   /* get magnitude */
1062   if (sample > CLIP)
1063     sample = CLIP;                      /* clip the magnitude */
1064
1065   /* Convert from 16 bit linear to ulaw. */
1066   sample = sample + BIAS;
1067   exponent = exp_lut[( sample >> 7 ) & 0xFF];
1068   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1069   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1070 #ifdef ZEROTRAP
1071   if (ulawbyte == 0)
1072     ulawbyte = 0x02;                    /* optional CCITT trap */
1073 #endif
1074
1075   return(ulawbyte);
1076 }
1077
1078 /*
1079 ** This routine converts from ulaw to 16 bit linear.
1080 **
1081 ** Craig Reese: IDA/Supercomputing Research Center
1082 ** 29 September 1989
1083 **
1084 ** References:
1085 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1086 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1087 **     for Analog-to_Digital Conversion Techniques,"
1088 **     17 February 1987
1089 **
1090 ** Input: 8 bit ulaw sample
1091 ** Output: signed 16 bit linear sample
1092 */
1093
1094 static int ulaw_to_linear(unsigned char ulawbyte)
1095 {
1096   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1097   int sign, exponent, mantissa, sample;
1098
1099   ulawbyte = ~ ulawbyte;
1100   sign = ( ulawbyte & 0x80 );
1101   exponent = ( ulawbyte >> 4 ) & 0x07;
1102   mantissa = ulawbyte & 0x0F;
1103   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1104   if (sign != 0)
1105     sample = -sample;
1106
1107   return(sample);
1108 }
1109 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1110
1111
1112 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1113 /* ========================================================================= */
1114 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1115
1116 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1117 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1118
1119 static SoundInfo *Load_WAV(char *filename)
1120 {
1121   SoundInfo *snd_info;
1122 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1123   byte sound_header_buffer[WAV_HEADER_SIZE];
1124   char chunk_name[CHUNK_ID_LEN + 1];
1125   int chunk_size;
1126   FILE *file;
1127   int i;
1128 #endif
1129
1130   if (!audio.sound_available)
1131     return NULL;
1132
1133 #if 0
1134   printf("loading WAV file '%s'\n", filename);
1135 #endif
1136
1137   snd_info = checked_calloc(sizeof(SoundInfo));
1138
1139 #if defined(TARGET_SDL)
1140
1141   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1142   {
1143     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1144     free(snd_info);
1145     return NULL;
1146   }
1147
1148 #elif defined(TARGET_ALLEGRO)
1149
1150   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1151   {
1152     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1153     free(snd_info);
1154     return NULL;
1155   }
1156
1157 #else   /* PLATFORM_UNIX */
1158
1159   if ((file = fopen(filename, MODE_READ)) == NULL)
1160   {
1161     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1162     free(snd_info);
1163     return NULL;
1164   }
1165
1166   /* read chunk id "RIFF" */
1167   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1168   if (strcmp(chunk_name, "RIFF") != 0)
1169   {
1170     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1171     fclose(file);
1172     free(snd_info);
1173     return NULL;
1174   }
1175
1176   /* read "RIFF" type id "WAVE" */
1177   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1178   if (strcmp(chunk_name, "WAVE") != 0)
1179   {
1180     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1181     fclose(file);
1182     free(snd_info);
1183     return NULL;
1184   }
1185
1186   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1187   {
1188     if (strcmp(chunk_name, "fmt ") == 0)
1189     {
1190       /* read header information */
1191       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1192         sound_header_buffer[i] = fgetc(file);
1193
1194       if (chunk_size > WAV_HEADER_SIZE)
1195         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1196     }
1197     else if (strcmp(chunk_name, "data") == 0)
1198     {
1199       snd_info->data_len = chunk_size;
1200       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1201
1202       /* read sound data */
1203       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1204           snd_info->data_len)
1205       {
1206         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1207         fclose(file);
1208         free(snd_info->data_ptr);
1209         free(snd_info);
1210         return NULL;
1211       }
1212
1213       /* check for odd number of sample bytes (data chunk is word aligned) */
1214       if ((chunk_size % 2) == 1)
1215         ReadUnusedBytesFromFile(file, 1);
1216     }
1217     else        /* unknown chunk -- ignore */
1218       ReadUnusedBytesFromFile(file, chunk_size);
1219   }
1220
1221   fclose(file);
1222
1223   if (snd_info->data_ptr == NULL)
1224   {
1225     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1226     free(snd_info);
1227     return NULL;
1228   }
1229
1230   snd_info->format = AUDIO_FORMAT_U8;
1231
1232 #endif  /* PLATFORM_UNIX */
1233
1234   snd_info->type = SND_TYPE_WAV;
1235   snd_info->source_filename = getStringCopy(filename);
1236
1237   return snd_info;
1238 }
1239
1240 static void deleteSoundEntry(SoundInfo **snd_info)
1241 {
1242   if (*snd_info)
1243   {
1244     char *filename = (*snd_info)->source_filename;
1245
1246 #if 1
1247     printf("[decrementing reference counter of sound '%s']\n", filename);
1248 #endif
1249
1250     if (--(*snd_info)->num_references <= 0)
1251     {
1252 #if 1
1253       printf("[deleting sound '%s']\n", filename);
1254 #endif
1255
1256       /*
1257       FreeSound(*snd_info);
1258       */
1259       deleteNodeFromList(&SoundFileList, filename, FreeSound);
1260     }
1261
1262     *snd_info = NULL;
1263   }
1264 }
1265
1266 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1267 {
1268   ListNode *node;
1269
1270   /* check if the old and the new sound file are the same */
1271   if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1272   {
1273     /* The old and new sound are the same (have the same filename and path).
1274        This usually means that this sound does not exist in this sound set
1275        and a fallback to the existing sound is done. */
1276
1277 #if 0
1278     printf("[sound '%s' already exists (same list entry)]\n", filename);
1279 #endif
1280
1281     return;
1282   }
1283
1284   /* delete existing sound file entry */
1285   deleteSoundEntry(snd_info);
1286
1287   /* check if the new sound file already exists in the list of sounds */
1288   if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1289   {
1290 #if 0
1291       printf("[sound '%s' already exists (other list entry)]\n", filename);
1292 #endif
1293
1294       *snd_info = (SoundInfo *)node->content;
1295       (*snd_info)->num_references++;
1296   }
1297   else if ((*snd_info = Load_WAV(filename)) != NULL)    /* load new sound */
1298   {
1299     (*snd_info)->num_references = 1;
1300     addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1301   }
1302 }
1303
1304 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1305 {
1306   char *filename = getCustomSoundFilename(basename);
1307
1308   if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1309   {
1310     deleteSoundEntry(snd_info);
1311     return;
1312   }
1313
1314   if (filename == NULL)
1315   {
1316     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1317     return;
1318   }
1319
1320   replaceSoundEntry(snd_info, filename);
1321 }
1322
1323 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1324 {
1325   if (Sound == NULL)
1326     Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1327
1328   sound_effect = sounds_list;
1329   num_sounds = num_list_entries;
1330 }
1331
1332 void LoadSoundToList(char *basename, int list_pos)
1333 {
1334   if (Sound == NULL || list_pos >= num_sounds)
1335     return;
1336
1337 #if 0
1338   printf("loading sound '%s' ...  [%d]\n",
1339          basename, getNumNodes(SoundFileList));
1340 #endif
1341
1342   LoadCustomSound(&Sound[list_pos], basename);
1343
1344 #if 0
1345   printf("loading sound '%s' done [%d]\n",
1346          basename, getNumNodes(SoundFileList));
1347 #endif
1348 }
1349
1350 static MusicInfo *Load_MOD(char *filename)
1351 {
1352 #if defined(TARGET_SDL)
1353   MusicInfo *mod_info;
1354
1355   if (!audio.sound_available)
1356     return NULL;
1357
1358   mod_info = checked_calloc(sizeof(MusicInfo));
1359
1360   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1361   {
1362     Error(ERR_WARN, "cannot read music file '%s'", filename);
1363     free(mod_info);
1364     return NULL;
1365   }
1366
1367   mod_info->type = MUS_TYPE_MOD;
1368   mod_info->source_filename = getStringCopy(filename);
1369
1370   return mod_info;
1371 #else
1372   return NULL;
1373 #endif
1374 }
1375
1376 void LoadCustomMusic(void)
1377 {
1378   char *music_directory = getCustomMusicDirectory();
1379   DIR *dir;
1380   struct dirent *dir_entry;
1381
1382   if (!audio.sound_available)
1383     return;
1384
1385   if ((dir = opendir(music_directory)) == NULL)
1386   {
1387     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1388     audio.music_available = FALSE;
1389     return;
1390   }
1391
1392   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1393   {
1394     char *basename = dir_entry->d_name;
1395     char *filename = getPath2(music_directory, basename);
1396     MusicInfo *mus_info = NULL;
1397
1398     if (FileIsSound(basename))
1399       mus_info = Load_WAV(filename);
1400     else if (FileIsMusic(basename))
1401       mus_info = Load_MOD(filename);
1402
1403     free(filename);
1404
1405     if (mus_info)
1406     {
1407       num_music++;
1408       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1409       Music[num_music -1] = mus_info;
1410     }
1411   }
1412
1413   closedir(dir);
1414
1415   if (num_music == 0)
1416     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1417           music_directory);
1418 }
1419
1420 void PlayMusic(int nr)
1421 {
1422   if (!audio.music_available)
1423     return;
1424
1425 #if defined(TARGET_SDL)
1426
1427   nr = nr % num_music;
1428
1429   if (Music[nr]->type == MUS_TYPE_MOD)
1430   {
1431     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1432     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1433   }
1434   else                          /* play WAV music loop */
1435   {
1436     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1437     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1438   }
1439
1440 #else
1441
1442   PlaySoundMusic(nr);
1443
1444 #endif
1445 }
1446
1447 void PlaySound(int nr)
1448 {
1449   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1450 }
1451
1452 void PlaySoundStereo(int nr, int stereo)
1453 {
1454   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1455 }
1456
1457 void PlaySoundLoop(int nr)
1458 {
1459   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1460 }
1461
1462 void PlaySoundMusic(int nr)
1463 {
1464   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1465 }
1466
1467 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1468 {
1469   struct SoundControl snd_ctrl = emptySoundControl;
1470
1471   if (!audio.sound_available ||
1472       !audio.sound_enabled ||
1473       audio.sound_deactivated)
1474     return;
1475
1476   if (volume < PSND_MIN_VOLUME)
1477     volume = PSND_MIN_VOLUME;
1478   else if (volume > PSND_MAX_VOLUME)
1479     volume = PSND_MAX_VOLUME;
1480
1481   if (stereo < PSND_MAX_LEFT)
1482     stereo = PSND_MAX_LEFT;
1483   else if (stereo > PSND_MAX_RIGHT)
1484     stereo = PSND_MAX_RIGHT;
1485
1486   snd_ctrl.nr           = nr;
1487   snd_ctrl.volume       = volume;
1488   snd_ctrl.stereo       = stereo;
1489   snd_ctrl.loop         = (loop_type != PSND_NO_LOOP);
1490   snd_ctrl.music        = (loop_type == PSND_MUSIC);
1491   snd_ctrl.active       = TRUE;
1492
1493 #if 0
1494   /* now only used internally in sound server child process */
1495   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1496   snd_ctrl.data_len     = Sound[nr].data_len;
1497 #endif
1498
1499 #if defined(TARGET_SDL)
1500   Mix_Volume(-1, SOUND_MAX_VOLUME);
1501   Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1502 #elif defined(PLATFORM_UNIX)
1503   if (audio.soundserver_pid == 0)       /* we are child process */
1504     return;
1505
1506   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1507   {
1508     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1509     audio.sound_available = audio.sound_enabled = FALSE;
1510     return;
1511   }
1512 #elif defined(PLATFORM_MSDOS)
1513   sound_handler(snd_ctrl);
1514 #endif
1515 }
1516
1517 void FadeMusic(void)
1518 {
1519   if (!audio.sound_available)
1520     return;
1521
1522 #if defined(TARGET_SDL)
1523   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1524   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1525 #else
1526   StopSoundExt(-1, SSND_FADE_MUSIC);
1527 #endif
1528 }
1529
1530 void FadeSound(int nr)
1531 {
1532   StopSoundExt(nr, SSND_FADE_SOUND);
1533 }
1534
1535 void FadeSounds()
1536 {
1537   FadeMusic();
1538   StopSoundExt(-1, SSND_FADE_ALL);
1539 }
1540
1541 void StopMusic(void)
1542 {
1543 #if defined(TARGET_SDL)
1544   if (!audio.sound_available)
1545     return;
1546
1547   Mix_HaltMusic();
1548   Mix_HaltChannel(audio.music_channel);
1549 #else
1550   StopSoundExt(-1, SSND_STOP_MUSIC);
1551 #endif
1552 }
1553
1554 void StopSound(int nr)
1555 {
1556   StopSoundExt(nr, SSND_STOP_SOUND);
1557 }
1558
1559 void StopSounds()
1560 {
1561   StopSoundExt(-1, SSND_STOP_ALL);
1562 }
1563
1564 void StopSoundExt(int nr, int method)
1565 {
1566   struct SoundControl snd_ctrl = emptySoundControl;
1567
1568   if (!audio.sound_available)
1569     return;
1570
1571   if (method & SSND_FADING)
1572     snd_ctrl.fade_sound = TRUE;
1573
1574   if (method & SSND_ALL)
1575     snd_ctrl.stop_all_sounds = TRUE;
1576   else
1577   {
1578     snd_ctrl.stop_sound = TRUE;
1579     snd_ctrl.nr = nr;
1580   }
1581
1582   if (method & SSND_MUSIC)
1583     snd_ctrl.music = TRUE;
1584
1585 #if defined(TARGET_SDL)
1586
1587   if (method & SSND_FADING)
1588   {
1589     int i;
1590
1591     for (i=0; i<audio.channels; i++)
1592       if (i != audio.music_channel || snd_ctrl.music)
1593         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1594     if (snd_ctrl.music)
1595       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1596   }
1597   else
1598   {
1599     int i;
1600
1601     for (i=0; i<audio.channels; i++)
1602       if (i != audio.music_channel || snd_ctrl.music)
1603         Mix_HaltChannel(i);
1604     if (snd_ctrl.music)
1605       Mix_HaltMusic();
1606   }
1607
1608 #elif !defined(PLATFORM_MSDOS)
1609
1610   if (audio.soundserver_pid == 0)       /* we are child process */
1611     return;
1612
1613   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1614   {
1615     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1616     audio.sound_available = audio.sound_enabled = FALSE;
1617     return;
1618   }
1619 #else
1620   sound_handler(snd_ctrl);
1621 #endif
1622 }
1623
1624 ListNode *newListNode()
1625 {
1626   return checked_calloc(sizeof(ListNode));
1627 }
1628
1629 void addNodeToList(ListNode **node_first, char *key, void *content)
1630 {
1631   ListNode *node_new = newListNode();
1632
1633 #if 0
1634   printf("LIST: adding node with key '%s'\n", key);
1635 #endif
1636
1637   node_new->key = getStringCopy(key);
1638   node_new->content = content;
1639   node_new->next = *node_first;
1640   *node_first = node_new;
1641 }
1642
1643 void deleteNodeFromList(ListNode **node_first, char *key,
1644                         void (*destructor_function)(void *))
1645 {
1646   if (node_first == NULL || *node_first == NULL)
1647     return;
1648
1649   printf("[CHECKING LIST KEY '%s' == '%s']\n",
1650          (*node_first)->key, key);
1651
1652   if (strcmp((*node_first)->key, key) == 0)
1653   {
1654     printf("[DELETING LIST ENTRY]\n");
1655
1656     free((*node_first)->key);
1657     if (destructor_function)
1658       destructor_function((*node_first)->content);
1659     *node_first = (*node_first)->next;
1660   }
1661   else
1662     deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1663 }
1664
1665 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1666 {
1667   if (node_first == NULL)
1668     return NULL;
1669
1670   if (strcmp(node_first->key, key) == 0)
1671     return node_first;
1672   else
1673     return getNodeFromKey(node_first->next, key);
1674 }
1675
1676 int getNumNodes(ListNode *node_first)
1677 {
1678   return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1679 }
1680
1681 void dumpList(ListNode *node_first)
1682 {
1683   ListNode *node = node_first;
1684
1685   while (node)
1686   {
1687     printf("['%s' (%d)]\n", node->key,
1688            ((SoundInfo *)node->content)->num_references);
1689     node = node->next;
1690   }
1691
1692   printf("[%d nodes]\n", getNumNodes(node_first));
1693 }
1694
1695 static void LoadSoundsInfo()
1696 {
1697   char *filename = getCustomSoundConfigFilename();
1698   struct SetupFileList *setup_file_list;
1699   int i;
1700
1701   /* always start with reliable default values */
1702   for (i=0; i<num_sounds; i++)
1703     sound_effect[i].filename = NULL;
1704
1705   if (filename == NULL)
1706     return;
1707
1708   if ((setup_file_list = loadSetupFileList(filename)))
1709   {
1710     for (i=0; i<num_sounds; i++)
1711       sound_effect[i].filename =
1712         getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1713
1714     freeSetupFileList(setup_file_list);
1715
1716 #if 1
1717     for (i=0; i<num_sounds; i++)
1718     {
1719       printf("'%s' ", sound_effect[i].text);
1720       if (sound_effect[i].filename)
1721         printf("-> '%s'\n", sound_effect[i].filename);
1722       else
1723         printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1724     }
1725 #endif
1726   }
1727 }
1728
1729 static void ReloadCustomSounds()
1730 {
1731   int i;
1732
1733 #if 0
1734   printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1735 #endif
1736
1737   LoadSoundsInfo();
1738
1739   for(i=0; i<num_sounds; i++)
1740   {
1741     if (sound_effect[i].filename)
1742       LoadSoundToList(sound_effect[i].filename, i);
1743     else
1744       LoadSoundToList(sound_effect[i].default_filename, i);
1745   }
1746
1747   /*
1748   printf("list size == %d\n", getNumNodes(SoundFileList));
1749   */
1750
1751 #if 0
1752   dumpList(SoundFileList);
1753 #endif
1754 }
1755
1756 static void ReloadCustomMusic()
1757 {
1758 #if 0
1759   printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1760 #endif
1761
1762   FreeAllMusic();
1763
1764   LoadCustomMusic();
1765 }
1766
1767 static void InitReloadSoundsOrMusic(char *set_name, int type)
1768 {
1769 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1770   struct SoundControl snd_ctrl = emptySoundControl;
1771   TreeInfo *ti =
1772     (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1773   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1774   unsigned long str_size2 = strlen(ti->basepath) + 1;
1775   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1776 #endif
1777
1778   if (!audio.sound_available)
1779     return;
1780
1781 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1782   if (type == SND_RELOAD_SOUNDS)
1783     audio.func_reload_sounds();
1784   else
1785     audio.func_reload_music();
1786 #elif defined(PLATFORM_UNIX)
1787   if (audio.soundserver_pid == 0)       /* we are child process */
1788     return;
1789
1790   if (leveldir_current == NULL)         /* should never happen */
1791     Error(ERR_EXIT, "leveldir_current == NULL");
1792
1793   snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1794   snd_ctrl.reload_music  = (type == SND_RELOAD_MUSIC);
1795   snd_ctrl.data_len = strlen(set_name) + 1;
1796
1797   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1798             sizeof(snd_ctrl)) < 0 ||
1799       write(audio.soundserver_pipe[1], set_name,
1800             snd_ctrl.data_len) < 0 ||
1801       write(audio.soundserver_pipe[1], leveldir_current,
1802             sizeof(TreeInfo)) < 0 ||
1803       write(audio.soundserver_pipe[1], ti,
1804             sizeof(TreeInfo)) < 0 ||
1805       write(audio.soundserver_pipe[1], &str_size1,
1806             sizeof(unsigned long)) < 0 ||
1807       write(audio.soundserver_pipe[1], &str_size2,
1808             sizeof(unsigned long)) < 0 ||
1809       write(audio.soundserver_pipe[1], &str_size3,
1810             sizeof(unsigned long)) < 0 ||
1811       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1812             str_size1) < 0 ||
1813       write(audio.soundserver_pipe[1], ti->basepath,
1814             str_size2) < 0 ||
1815       write(audio.soundserver_pipe[1], ti->fullpath,
1816             str_size3) < 0)
1817   {
1818     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1819     audio.sound_available = audio.sound_enabled = FALSE;
1820     return;
1821   }
1822 #endif
1823 }
1824
1825 void InitReloadSounds(char *set_name)
1826 {
1827   InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1828 }
1829
1830 void InitReloadMusic(char *set_name)
1831 {
1832   InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1833 }
1834
1835 void FreeSound(void *ptr)
1836 {
1837   SoundInfo *sound = (SoundInfo *)ptr;
1838
1839   if (sound == NULL)
1840     return;
1841
1842   if (sound->data_ptr)
1843   {
1844 #if defined(TARGET_SDL)
1845     Mix_FreeChunk(sound->data_ptr);
1846 #elif defined(TARGET_ALLEGRO)
1847     destroy_sample(sound->data_ptr);
1848 #else   /* PLATFORM_UNIX */
1849     free(sound->data_ptr);
1850 #endif
1851   }
1852
1853   if (sound->source_filename)
1854     free(sound->source_filename);
1855
1856   free(sound);
1857 }
1858
1859 void FreeMusic(MusicInfo *music)
1860 {
1861   if (music == NULL)
1862     return;
1863
1864   if (music->data_ptr)
1865   {
1866 #if defined(TARGET_SDL)
1867     if (music->type == MUS_TYPE_MOD)
1868       Mix_FreeMusic(music->data_ptr);
1869     else
1870       Mix_FreeChunk(music->data_ptr);
1871 #elif defined(TARGET_ALLEGRO)
1872     destroy_sample(music->data_ptr);
1873 #else   /* PLATFORM_UNIX */
1874     free(music->data_ptr);
1875 #endif
1876   }
1877
1878   free(music);
1879 }
1880
1881 void FreeAllSounds()
1882 {
1883   int i;
1884
1885   if (Sound == NULL)
1886     return;
1887
1888   for(i=0; i<num_sounds; i++)
1889     FreeSound(Sound[i]);
1890
1891   free(Sound);
1892
1893   Sound = NULL;
1894   num_sounds = 0;
1895 }
1896
1897 void FreeAllMusic()
1898 {
1899   int i;
1900
1901   if (Music == NULL)
1902     return;
1903
1904   for(i=0; i<num_music; i++)
1905     FreeMusic(Music[i]);
1906
1907   free(Music);
1908
1909   Music = NULL;
1910   num_music = 0;
1911 }
1912
1913 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
1914 /* ========================================================================= */