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