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