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