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