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