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