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