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