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