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