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