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