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