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