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