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