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