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