rnd-20020424-2-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 static SoundInfo **Sound = NULL;
28 static MusicInfo **Music = NULL;
29 static int num_sounds = 0, num_music = 0;
30
31
32 /* ========================================================================= */
33 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
34
35 static int playing_sounds = 0;
36 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
37 static struct SoundControl emptySoundControl =
38 {
39   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
40 };
41
42 #if defined(PLATFORM_UNIX)
43 static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
44 static char premix_first_buffer[SND_BLOCKSIZE];
45 #if defined(AUDIO_STREAMING_DSP)
46 static char premix_left_buffer[SND_BLOCKSIZE];
47 static char premix_right_buffer[SND_BLOCKSIZE];
48 static int premix_last_buffer[SND_BLOCKSIZE];
49 #endif
50 static unsigned char playing_buffer[SND_BLOCKSIZE];
51 #endif
52
53 /* forward declaration of internal functions */
54 #if defined(AUDIO_STREAMING_DSP)
55 static void SoundServer_InsertNewSound(struct SoundControl);
56 #elif defined(PLATFORM_UNIX)
57 static unsigned char linear_to_ulaw(int);
58 static int ulaw_to_linear(unsigned char);
59 #endif
60
61 #if defined(AUDIO_LINUX_IOCTL)
62 static boolean InitAudioDevice_Linux();
63 #elif defined(PLATFORM_NETBSD)
64 static boolean InitAudioDevice_NetBSD();
65 #elif defined(PLATFORM_HPUX)
66 static boolean InitAudioDevice_HPUX();
67 #elif defined(PLATFORM_MSDOS)
68 static void SoundServer_InsertNewSound(struct SoundControl);
69 static void SoundServer_StopSound(int);
70 static void SoundServer_StopAllSounds();
71 #endif
72
73 #if defined(PLATFORM_UNIX)
74 static int OpenAudioDevice(char *audio_device_name)
75 {
76   int audio_fd;
77
78   /* check if desired audio device is accessible */
79   if (access(audio_device_name, W_OK) != 0)
80     return -1;
81
82   /* try to open audio device in non-blocking mode */
83   if ((audio_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
84     return audio_fd;
85
86   /* re-open audio device in blocking mode */
87   close(audio_fd);
88   audio_fd = open(audio_device_name, O_WRONLY);
89
90   return audio_fd;
91 }
92
93 static boolean TestAudioDevices(void)
94 {
95   static char *audio_device_name[] =
96   {
97     DEVICENAME_DSP,
98     DEVICENAME_AUDIO
99   };
100   int audio_fd = -1;
101   int i;
102
103   /* look for available audio devices, starting with preferred ones */
104   for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
105     if ((audio_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
106       break;
107
108   if (audio_fd < 0)
109   {
110     Error(ERR_WARN, "cannot open audio device -- no sound");
111     return FALSE;
112   }
113
114   close(audio_fd);
115
116   audio.device_name = audio_device_name[i];
117
118   return TRUE;
119 }
120
121 #if !defined(TARGET_SDL)
122 static boolean ForkAudioProcess(void)
123 {
124   if (pipe(audio.soundserver_pipe) < 0)
125   {
126     Error(ERR_WARN, "cannot create pipe -- no sounds");
127     return FALSE;
128   }
129
130   if ((audio.soundserver_pid = fork()) < 0)
131   {       
132     Error(ERR_WARN, "cannot create sound server process -- no sounds");
133     return FALSE;
134   }
135
136   if (audio.soundserver_pid == 0)       /* we are child process */
137   {
138     SoundServer();
139
140     /* never reached */
141     exit(0);
142   }
143   else                                  /* we are parent */
144     close(audio.soundserver_pipe[0]); /* no reading from pipe needed */
145
146   return TRUE;
147 }
148 #endif
149
150 void UnixOpenAudio(void)
151 {
152   if (!TestAudioDevices())
153     return;
154
155   audio.sound_available = TRUE;
156   audio.sound_enabled = TRUE;
157
158 #if defined(AUDIO_STREAMING_DSP)
159   audio.music_available = TRUE;
160   audio.loops_available = TRUE;
161 #endif
162 }
163
164 void UnixCloseAudio(void)
165 {
166   if (audio.device_fd)
167     close(audio.device_fd);
168
169   if (audio.soundserver_pid > 0)        /* we are parent process */
170     kill(audio.soundserver_pid, SIGTERM);
171 }
172 #endif  /* PLATFORM_UNIX */
173
174 void InitPlaylist(void)
175 {
176   int i;
177
178   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
179     playlist[i] = emptySoundControl;
180   playing_sounds = 0;
181 }
182
183 void StartSoundserver(void)
184 {
185   if (!audio.sound_available)
186     return;
187
188 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
189   if (!ForkAudioProcess())
190     audio.sound_available = FALSE;
191 #endif
192 }
193
194 #if defined(PLATFORM_UNIX)
195 void SoundServer(void)
196 {
197   int i;
198
199   struct SoundControl snd_ctrl;
200   fd_set sound_fdset;
201
202   close(audio.soundserver_pipe[1]);     /* no writing into pipe needed */
203
204   InitPlaylist();
205
206   stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
207   for(i=0; i<PSND_MAX_LEFT2RIGHT; i++)
208     stereo_volume[i] =
209       (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
210
211 #if defined(PLATFORM_HPUX)
212   InitAudioDevice_HPUX();
213 #endif
214
215   FD_ZERO(&sound_fdset); 
216   FD_SET(audio.soundserver_pipe[0], &sound_fdset);
217
218   while(1)      /* wait for sound playing commands from client */
219   {
220     FD_SET(audio.soundserver_pipe[0], &sound_fdset);
221     select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
222     if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
223       continue;
224     if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
225         != sizeof(snd_ctrl))
226       Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
227
228     if (snd_ctrl.reload_sounds || snd_ctrl.reload_music)
229     {
230       char *set_name = checked_malloc(snd_ctrl.data_len);
231       TreeInfo **ti_ptr =
232         (snd_ctrl.reload_sounds ? &artwork.snd_current : &artwork.mus_current);
233       TreeInfo *ti = *ti_ptr;
234       unsigned long str_size1, str_size2, str_size3;
235
236       printf("B\n");
237
238       if (leveldir_current == NULL)
239         leveldir_current = checked_calloc(sizeof(TreeInfo));
240       printf("B.1\n");
241       if (ti == NULL)
242         ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
243       printf("B.2\n");
244       if (leveldir_current->fullpath != NULL)
245         free(leveldir_current->fullpath);
246       printf("B.3 ['%s']\n", ti->basepath);
247 #if 0
248       if (ti->basepath != NULL)
249         free(ti->basepath);
250 #endif
251       printf("B.4\n");
252       if (ti->fullpath != NULL)
253         free(ti->fullpath);
254       printf("B.5\n");
255
256       printf("C\n");
257
258       if (read(audio.soundserver_pipe[0], set_name,
259                snd_ctrl.data_len) != snd_ctrl.data_len ||
260           read(audio.soundserver_pipe[0], leveldir_current,
261                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
262           read(audio.soundserver_pipe[0], ti,
263                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
264           read(audio.soundserver_pipe[0], &str_size1,
265                sizeof(unsigned long)) != sizeof(unsigned long) ||
266           read(audio.soundserver_pipe[0], &str_size2,
267                sizeof(unsigned long)) != sizeof(unsigned long) ||
268           read(audio.soundserver_pipe[0], &str_size3,
269                sizeof(unsigned long)) != sizeof(unsigned long))
270         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
271
272       printf("D\n");
273
274       leveldir_current->fullpath = checked_calloc(str_size1);
275       ti->basepath = checked_calloc(str_size2);
276       ti->fullpath = checked_calloc(str_size3);
277
278       if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
279                str_size1) != str_size1 ||
280           read(audio.soundserver_pipe[0], ti->basepath,
281                str_size2) != str_size2 ||
282           read(audio.soundserver_pipe[0], ti->fullpath,
283                str_size3) != str_size3)
284         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
285
286       printf("E\n");
287
288       InitPlaylist();
289
290       close(audio.device_fd);
291
292       printf("X\n");
293
294       if (snd_ctrl.reload_sounds)
295       {
296         artwork.sounds_set_current = set_name;
297         audio.func_reload_sounds();
298       }
299       else
300       {
301         artwork.music_set_current = set_name;
302         audio.func_reload_music();
303       }
304
305       free(set_name);
306
307       continue;
308     }
309
310 #if defined(AUDIO_STREAMING_DSP)
311
312     if (snd_ctrl.fade_sound)
313     {
314       if (!playing_sounds)
315         continue;
316
317       if (snd_ctrl.music)
318         playlist[audio.music_channel].fade_sound = TRUE;
319       else
320         for(i=0; i<MAX_SOUNDS_PLAYING; i++)
321           if (snd_ctrl.stop_all_sounds ||
322               (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
323             playlist[i].fade_sound = TRUE;
324     }
325     else if (snd_ctrl.stop_all_sounds)
326     {
327       if (!playing_sounds)
328         continue;
329
330       for(i=0; i<MAX_SOUNDS_PLAYING; i++)
331         playlist[i] = emptySoundControl;
332       playing_sounds = 0;
333
334       close(audio.device_fd);
335     }
336     else if (snd_ctrl.stop_sound)
337     {
338       if (!playing_sounds)
339         continue;
340
341       if (snd_ctrl.music)
342       {
343         playlist[audio.music_channel] = emptySoundControl;
344         playing_sounds--;
345       }
346
347       for(i=0; i<MAX_SOUNDS_PLAYING; i++)
348       {
349         if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
350         {
351           playlist[i] = emptySoundControl;
352           playing_sounds--;
353         }
354       }
355
356       if (!playing_sounds)
357         close(audio.device_fd);
358     }
359
360     if (playing_sounds || snd_ctrl.active)
361     {
362       struct timeval delay = { 0, 0 };
363       byte *sample_ptr;
364       long sample_size;
365       static long max_sample_size = 0;
366       static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
367       int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
368       static boolean stereo = TRUE;
369
370       if (playing_sounds ||
371           (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
372       {
373         if (!playing_sounds)    /* we just opened the audio device */
374         {
375 #if defined(AUDIO_LINUX_IOCTL)
376           stereo = InitAudioDevice_Linux(fragment_size, sample_rate);
377 #elif defined(PLATFORM_NETBSD)
378           stereo = InitAudioDevice_NetBSD(fragment_size, sample_rate);
379 #endif
380           max_sample_size = fragment_size / (stereo ? 2 : 1);
381         }
382
383         if (snd_ctrl.active)    /* new sound has arrived */
384           SoundServer_InsertNewSound(snd_ctrl);
385
386         while (playing_sounds &&
387                select(audio.soundserver_pipe[0] + 1,
388                       &sound_fdset, NULL, NULL, &delay) < 1)
389         {       
390           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
391
392           /* first clear the last premixing buffer */
393           memset(premix_last_buffer, 0, fragment_size * sizeof(int));
394
395           for(i=0;i<MAX_SOUNDS_PLAYING;i++)
396           {
397             int j;
398
399             if (!playlist[i].active)
400               continue;
401
402             /* get pointer and size of the actual sound sample */
403             sample_ptr = playlist[i].data_ptr + playlist[i].playingpos;
404             sample_size = MIN(max_sample_size,
405                               playlist[i].data_len - playlist[i].playingpos);
406             playlist[i].playingpos += sample_size;
407
408             /* fill the first mixing buffer with original sample */
409             memcpy(premix_first_buffer, sample_ptr, sample_size);
410
411             /* are we about to restart a looping sound? */
412             if (playlist[i].loop && sample_size < max_sample_size)
413             {
414               playlist[i].playingpos = max_sample_size - sample_size;
415               memcpy(premix_first_buffer + sample_size,
416                      playlist[i].data_ptr, max_sample_size - sample_size);
417               sample_size = max_sample_size;
418             }
419
420             /* decrease volume if sound is fading out */
421             if (playlist[i].fade_sound &&
422                 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
423               playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
424
425             /* adjust volume of actual sound sample */
426             if (playlist[i].volume != PSND_MAX_VOLUME)
427               for(j=0; j<sample_size; j++)
428                 premix_first_buffer[j] =
429                   (playlist[i].volume * (int)premix_first_buffer[j])
430                     >> PSND_MAX_VOLUME_BITS;
431
432             /* fill the last mixing buffer with stereo or mono sound */
433             if (stereo)
434             {
435               int middle_pos = PSND_MAX_LEFT2RIGHT/2;
436               int left_volume  = stereo_volume[middle_pos +playlist[i].stereo];
437               int right_volume = stereo_volume[middle_pos -playlist[i].stereo];
438
439               for(j=0; j<sample_size; j++)
440               {
441                 premix_left_buffer[j] =
442                   (left_volume * (int)premix_first_buffer[j])
443                     >> PSND_MAX_LEFT2RIGHT_BITS;
444                 premix_right_buffer[j] =
445                   (right_volume * (int)premix_first_buffer[j])
446                     >> PSND_MAX_LEFT2RIGHT_BITS;
447                 premix_last_buffer[2*j+0] += premix_left_buffer[j];
448                 premix_last_buffer[2*j+1] += premix_right_buffer[j];
449               }
450             }
451             else
452             {
453               for(j=0;j<sample_size;j++)
454                 premix_last_buffer[j] += (int)premix_first_buffer[j];
455             }
456
457             /* delete completed sound entries from the playlist */
458             if (playlist[i].playingpos >= playlist[i].data_len)
459             {
460               if (playlist[i].loop)
461                 playlist[i].playingpos = 0;
462               else
463               {
464                 playlist[i] = emptySoundControl;
465                 playing_sounds--;
466               }
467             }
468             else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
469             {
470               playlist[i] = emptySoundControl;
471               playing_sounds--;
472             }
473           }
474
475           /* put last mixing buffer to final playing buffer */
476           for(i=0; i<fragment_size; i++)
477           {
478             if (premix_last_buffer[i]<-255)
479               playing_buffer[i] = 0;
480             else if (premix_last_buffer[i]>255)
481               playing_buffer[i] = 255;
482             else
483               playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
484           }
485
486           /* finally play the sound fragment */
487           write(audio.device_fd, playing_buffer, fragment_size);
488         }
489
490         /* if no sounds playing, free device for other sound programs */
491         if (!playing_sounds)
492           close(audio.device_fd);
493       }
494     }
495
496 #else /* !AUDIO_STREAMING_DSP */
497
498     if (snd_ctrl.active && !snd_ctrl.loop)
499     {
500       struct timeval delay = { 0, 0 };
501       byte *sample_ptr;
502       long sample_size, max_sample_size = SND_BLOCKSIZE;
503       long sample_rate = 8000;  /* standard "/dev/audio" sampling rate */
504       int wait_percent = 90;    /* wait 90% of the real playing time */
505       int i;
506
507       if ((audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
508       {
509         playing_sounds = 1;
510
511         while (playing_sounds &&
512                select(audio.soundserver_pipe[0] + 1,
513                       &sound_fdset, NULL, NULL, &delay) < 1)
514         {       
515           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
516
517           /* get pointer and size of the actual sound sample */
518           sample_ptr = snd_ctrl.data_ptr + snd_ctrl.playingpos;
519           sample_size =
520             MIN(max_sample_size, snd_ctrl.data_len - snd_ctrl.playingpos);
521           snd_ctrl.playingpos += sample_size;
522
523           /* fill the first mixing buffer with original sample */
524           memcpy(premix_first_buffer,sample_ptr,sample_size);
525
526           /* adjust volume of actual sound sample */
527           if (snd_ctrl.volume != PSND_MAX_VOLUME)
528             for(i=0;i<sample_size;i++)
529               premix_first_buffer[i] =
530                 (snd_ctrl.volume * (int)premix_first_buffer[i])
531                   >> PSND_MAX_VOLUME_BITS;
532
533           for(i=0;i<sample_size;i++)
534             playing_buffer[i] =
535               linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
536
537           if (snd_ctrl.playingpos >= snd_ctrl.data_len)
538             playing_sounds = 0;
539
540           /* finally play the sound fragment */
541           write(audio.device_fd,playing_buffer,sample_size);
542
543           delay.tv_sec = 0;
544           delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
545         }
546         close(audio.device_fd);
547       }
548     }
549 #endif /* !AUDIO_STREAMING_DSP */
550   }
551 }
552 #endif /* PLATFORM_UNIX */
553
554 #if defined(PLATFORM_MSDOS)
555 static void sound_handler(struct SoundControl snd_ctrl)
556 {
557   int i;
558
559   if (snd_ctrl.fade_sound)
560   {
561     if (!playing_sounds)
562       return;
563
564     for (i=0; i<MAX_SOUNDS_PLAYING; i++)
565       if ((snd_ctrl.stop_all_sounds ||
566            (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
567            (i == audio.music_channel && snd_ctrl.music)) &&
568           !playlist[i].fade_sound)
569       {
570         playlist[i].fade_sound = TRUE;
571         if (voice_check(playlist[i].voice))
572           voice_ramp_volume(playlist[i].voice, 1000, 0);
573         playlist[i].loop = PSND_NO_LOOP;
574       }
575   }
576   else if (snd_ctrl.stop_all_sounds)
577   {
578     if (!playing_sounds)
579       return;
580     SoundServer_StopAllSounds();
581   }
582   else if (snd_ctrl.stop_sound)
583   {
584     if (!playing_sounds)
585       return;
586     SoundServer_StopSound(snd_ctrl);
587   }
588
589   for (i=0; i<MAX_SOUNDS_PLAYING; i++)
590   {
591     if (!playlist[i].active || playlist[i].loop)
592       continue;
593
594     playlist[i].playingpos = voice_get_position(playlist[i].voice);
595     playlist[i].volume = voice_get_volume(playlist[i].voice);
596     if (playlist[i].playingpos == -1 || !playlist[i].volume)
597     {
598       deallocate_voice(playlist[i].voice);
599       playlist[i] = emptySoundControl;
600       playing_sounds--;
601     }
602   }
603
604   if (snd_ctrl.active)
605     SoundServer_InsertNewSound(snd_ctrl);
606 }
607 #endif /* PLATFORM_MSDOS */
608
609 #if !defined(PLATFORM_WIN32)
610 static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
611 {
612   int i, k;
613
614   if (snd_ctrl.music)
615     snd_ctrl.nr = snd_ctrl.nr % num_music;
616
617   /* if playlist is full, remove oldest sound */
618   if (playing_sounds == MAX_SOUNDS_PLAYING)
619   {
620     int longest = 0, longest_nr = 0;
621
622     for (i=0; i<MAX_SOUNDS_PLAYING; i++)
623     {
624 #if !defined(PLATFORM_MSDOS)
625       int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
626 #else
627       int actual = playlist[i].playingpos;
628 #endif
629
630       if (i != audio.music_channel && !playlist[i].loop && actual > longest)
631       {
632         longest = actual;
633         longest_nr = i;
634       }
635     }
636 #if defined(PLATFORM_MSDOS)
637     voice_set_volume(playlist[longest_nr].voice, 0);
638     deallocate_voice(playlist[longest_nr].voice);
639 #endif
640     playlist[longest_nr] = emptySoundControl;
641     playing_sounds--;
642   }
643
644   /* check if sound is already being played (and how often) */
645   for (k=0,i=0; i<MAX_SOUNDS_PLAYING; i++)
646     if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
647       k++;
648
649   /* restart loop sounds only if they are just fading out */
650   if (k >= 1 && snd_ctrl.loop)
651   {
652     for(i=0; i<MAX_SOUNDS_PLAYING; i++)
653     {
654       if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr &&
655           playlist[i].fade_sound)
656       {
657         playlist[i].fade_sound = FALSE;
658         playlist[i].volume = PSND_MAX_VOLUME;
659 #if defined(PLATFORM_MSDOS)
660         playlist[i].loop = PSND_LOOP;
661         voice_stop_volumeramp(playlist[i].voice);
662         voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
663 #endif
664       }
665     }
666
667     return;
668   }
669
670   /* don't play sound more than n times simultaneously (with n == 2 for now) */
671   if (k >= 2)
672   {
673     int longest = 0, longest_nr = 0;
674
675     /* look for oldest equal sound */
676     for(i=0; i<MAX_SOUNDS_PLAYING; i++)
677     {
678       int actual;
679
680       if (!playlist[i].active ||
681           i == audio.music_channel ||
682           playlist[i].nr != snd_ctrl.nr)
683         continue;
684
685 #if !defined(PLATFORM_MSDOS)
686       actual = 100 * playlist[i].playingpos / playlist[i].data_len;
687 #else
688       actual = playlist[i].playingpos;
689 #endif
690       if (actual >= longest)
691       {
692         longest = actual;
693         longest_nr = i;
694       }
695     }
696
697 #if defined(PLATFORM_MSDOS)
698     voice_set_volume(playlist[longest_nr].voice, 0);
699     deallocate_voice(playlist[longest_nr].voice);
700 #endif
701     playlist[longest_nr] = emptySoundControl;
702     playing_sounds--;
703   }
704
705   /* add new sound to playlist */
706   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
707   {
708     if (!playlist[i].active ||
709         (snd_ctrl.music && i == audio.music_channel))
710     {
711       SoundInfo *snd_info =
712         (snd_ctrl.music ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
713
714       snd_ctrl.data_ptr = snd_info->data_ptr;
715       snd_ctrl.data_len = snd_info->data_len;
716
717       playlist[i] = snd_ctrl;
718       playing_sounds++;
719
720 #if defined(PLATFORM_MSDOS)
721       playlist[i].voice = allocate_voice(playlist[i].data_ptr);
722
723       if (snd_ctrl.loop)
724         voice_set_playmode(playlist[i].voice, PLAYMODE_LOOP);
725
726       voice_set_volume(playlist[i].voice, snd_ctrl.volume);
727       voice_set_pan(playlist[i].voice, snd_ctrl.stereo);
728       voice_start(playlist[i].voice);       
729 #endif
730       break;
731     }
732   }
733 }
734 #endif /* !PLATFORM_WIN32 */
735
736 /*
737 void SoundServer_FadeSound(int nr)
738 {
739   int i;
740
741   if (!playing_sounds)
742     return;
743
744   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
745     if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
746       playlist[i].fade_sound = TRUE;
747 }
748 */
749
750 #if !defined(PLATFORM_WIN32)
751 #if defined(PLATFORM_MSDOS)
752 static void SoundServer_StopSound(struct SoundControl snd_ctrl)
753 {
754   int nr = snd_ctrl.nr;
755   int i;
756
757   if (!playing_sounds)
758     return;
759
760   for(i=0; i<MAX_SOUNDS_PLAYING; i++)
761   {
762     if ((i == audio.music_channel && snd_ctrl.music) ||
763         (i != audio.music_channel && playlist[i].nr == nr))
764     {
765 #if defined(PLATFORM_MSDOS)
766       voice_set_volume(playlist[i].voice, 0);
767       deallocate_voice(playlist[i].voice);
768 #endif
769       playlist[i] = emptySoundControl;
770       playing_sounds--;
771     }
772   }
773
774 #if !defined(PLATFORM_MSDOS)
775   if (!playing_sounds)
776     close(audio.device_fd);
777 #endif
778 }
779
780 static void SoundServer_StopAllSounds()
781 {
782   int i;
783
784   for(i=0;i<MAX_SOUNDS_PLAYING;i++)
785   {
786 #if defined(PLATFORM_MSDOS)
787     voice_set_volume(playlist[i].voice, 0);
788     deallocate_voice(playlist[i].voice);
789 #endif
790     playlist[i]=emptySoundControl;
791   }
792   playing_sounds = 0;
793
794 #if !defined(PLATFORM_MSDOS)
795   close(audio.device_fd);
796 #endif
797 }
798 #endif /* PLATFORM_MSDOS */
799 #endif /* !PLATFORM_WIN32 */
800
801
802 /* ------------------------------------------------------------------------- */
803 /* platform dependant audio initialization code                              */
804 /* ------------------------------------------------------------------------- */
805
806 #if defined(AUDIO_LINUX_IOCTL)
807 static boolean InitAudioDevice_Linux(long fragment_size, int sample_rate)
808 {
809   /* "ioctl()" expects pointer to 'int' value for stereo flag
810      (boolean is defined as 'char', which will not work here) */
811   int stereo = TRUE;
812   unsigned long fragment_spec = 0;
813
814   /* determine logarithm (log2) of the fragment size */
815   for (fragment_spec=0; (1 << fragment_spec) < fragment_size;
816        fragment_spec++);
817
818   /* use two fragments (play one fragment, prepare the other);
819      one fragment would result in interrupted audio output, more
820      than two fragments would raise audio output latency to much */
821   fragment_spec |= 0x00020000;
822
823   /* Example for fragment specification:
824      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
825      - (with stereo the effective buffer size will shrink to 256)
826      => fragment_size = 0x00020009 */
827
828   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
829     Error(ERR_EXIT_SOUND_SERVER,
830           "cannot set fragment size of /dev/dsp -- no sounds");
831
832   /* try if we can use stereo sound */
833   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
834   {
835 #ifdef DEBUG
836     static boolean reported = FALSE;
837
838     if (!reported)
839     {
840       Error(ERR_RETURN, "cannot get stereo sound on /dev/dsp");
841       reported = TRUE;
842     }
843 #endif
844     stereo = FALSE;
845   }
846
847   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &sample_rate) < 0)
848     Error(ERR_EXIT_SOUND_SERVER,
849           "cannot set sample rate of /dev/dsp -- no sounds");
850
851   /* get the real fragmentation size; this should return 512 */
852   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size) < 0)
853     Error(ERR_EXIT_SOUND_SERVER,
854           "cannot get fragment size of /dev/dsp -- no sounds");
855
856   return (boolean)stereo;
857 }
858 #endif  /* AUDIO_LINUX_IOCTL */
859
860 #if defined(PLATFORM_NETBSD)
861 static boolean InitAudioDevice_NetBSD(long fragment_size, int sample_rate)
862 {
863   audio_info_t a_info;
864   boolean stereo = TRUE;
865
866   AUDIO_INITINFO(&a_info);
867   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
868   a_info.play.precision = 8;
869   a_info.play.channels = 2;
870   a_info.play.sample_rate = sample_rate;
871   a_info.blocksize = fragment_size;
872
873   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
874   {
875     /* try to disable stereo */
876     a_info.play.channels = 1;
877     stereo = FALSE;
878
879     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
880       Error(ERR_EXIT_SOUND_SERVER,
881             "cannot set sample rate of /dev/audio -- no sounds");
882   }
883
884   return stereo;
885 }
886 #endif /* PLATFORM_NETBSD */
887
888 #if defined(PLATFORM_HPUX)
889 static boolean InitAudioDevice_HPUX()
890 {
891   struct audio_describe ainfo;
892   int audio_ctl;
893
894   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
895   if (audio_ctl == -1)
896     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
897
898   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
899     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
900
901   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
902     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
903
904   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
905   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
906
907   close(audio_ctl);
908
909   return TRUE;  /* to provide common interface for InitAudioDevice_...() */
910 }
911 #endif /* PLATFORM_HPUX */
912
913 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
914
915 /* these two are stolen from "sox"... :) */
916
917 /*
918 ** This routine converts from linear to ulaw.
919 **
920 ** Craig Reese: IDA/Supercomputing Research Center
921 ** Joe Campbell: Department of Defense
922 ** 29 September 1989
923 **
924 ** References:
925 ** 1) CCITT Recommendation G.711  (very difficult to follow)
926 ** 2) "A New Digital Technique for Implementation of Any
927 **     Continuous PCM Companding Law," Villeret, Michel,
928 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
929 **     1973, pg. 11.12-11.17
930 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
931 **     for Analog-to_Digital Conversion Techniques,"
932 **     17 February 1987
933 **
934 ** Input: Signed 16 bit linear sample
935 ** Output: 8 bit ulaw sample
936 */
937
938 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
939 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
940 #define CLIP 32635
941
942 static unsigned char linear_to_ulaw(int sample)
943 {
944   static int exp_lut[256] =
945   {
946     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
947     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
948     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
949     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
950     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
951     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
952     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
953     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
954     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
955     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
956     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
957     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
958     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
959     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
960     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
961     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
962   };
963
964   int sign, exponent, mantissa;
965   unsigned char ulawbyte;
966
967   /* Get the sample into sign-magnitude. */
968   sign = (sample >> 8) & 0x80;          /* set aside the sign */
969   if (sign != 0)
970     sample = -sample;                   /* get magnitude */
971   if (sample > CLIP)
972     sample = CLIP;                      /* clip the magnitude */
973
974   /* Convert from 16 bit linear to ulaw. */
975   sample = sample + BIAS;
976   exponent = exp_lut[( sample >> 7 ) & 0xFF];
977   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
978   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
979 #ifdef ZEROTRAP
980   if (ulawbyte == 0)
981     ulawbyte = 0x02;                    /* optional CCITT trap */
982 #endif
983
984   return(ulawbyte);
985 }
986
987 /*
988 ** This routine converts from ulaw to 16 bit linear.
989 **
990 ** Craig Reese: IDA/Supercomputing Research Center
991 ** 29 September 1989
992 **
993 ** References:
994 ** 1) CCITT Recommendation G.711  (very difficult to follow)
995 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
996 **     for Analog-to_Digital Conversion Techniques,"
997 **     17 February 1987
998 **
999 ** Input: 8 bit ulaw sample
1000 ** Output: signed 16 bit linear sample
1001 */
1002
1003 static int ulaw_to_linear(unsigned char ulawbyte)
1004 {
1005   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1006   int sign, exponent, mantissa, sample;
1007
1008   ulawbyte = ~ ulawbyte;
1009   sign = ( ulawbyte & 0x80 );
1010   exponent = ( ulawbyte >> 4 ) & 0x07;
1011   mantissa = ulawbyte & 0x0F;
1012   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1013   if (sign != 0)
1014     sample = -sample;
1015
1016   return(sample);
1017 }
1018 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1019
1020
1021 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1022 /* ========================================================================= */
1023 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1024
1025 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1026 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1027
1028 static SoundInfo *Load_WAV(char *filename)
1029 {
1030   SoundInfo *snd_info;
1031 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1032   byte sound_header_buffer[WAV_HEADER_SIZE];
1033   char chunk_name[CHUNK_ID_LEN + 1];
1034   int chunk_size;
1035   FILE *file;
1036   int i;
1037 #endif
1038
1039   if (!audio.sound_available)
1040     return NULL;
1041
1042   snd_info = checked_calloc(sizeof(SoundInfo));
1043
1044 #if defined(TARGET_SDL)
1045
1046   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1047   {
1048     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1049     free(snd_info);
1050     return NULL;
1051   }
1052
1053 #elif defined(TARGET_ALLEGRO)
1054
1055   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1056   {
1057     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1058     free(snd_info);
1059     return NULL;
1060   }
1061
1062 #else   /* PLATFORM_UNIX */
1063
1064   if ((file = fopen(filename, MODE_READ)) == NULL)
1065   {
1066     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1067     free(snd_info);
1068     return NULL;
1069   }
1070
1071   /* read chunk id "RIFF" */
1072   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1073   if (strcmp(chunk_name, "RIFF") != 0)
1074   {
1075     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1076     fclose(file);
1077     free(snd_info);
1078     return NULL;
1079   }
1080
1081   /* read "RIFF" type id "WAVE" */
1082   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1083   if (strcmp(chunk_name, "WAVE") != 0)
1084   {
1085     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1086     fclose(file);
1087     free(snd_info);
1088     return NULL;
1089   }
1090
1091   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1092   {
1093     if (strcmp(chunk_name, "fmt ") == 0)
1094     {
1095       /* read header information */
1096       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1097         sound_header_buffer[i] = fgetc(file);
1098
1099       if (chunk_size > WAV_HEADER_SIZE)
1100         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1101     }
1102     else if (strcmp(chunk_name, "data") == 0)
1103     {
1104       snd_info->data_len = chunk_size;
1105       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1106
1107       /* read sound data */
1108       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1109           snd_info->data_len)
1110       {
1111         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1112         fclose(file);
1113         free(snd_info->data_ptr);
1114         free(snd_info);
1115         return NULL;
1116       }
1117
1118       /* check for odd number of sample bytes (data chunk is word aligned) */
1119       if ((chunk_size % 2) == 1)
1120         ReadUnusedBytesFromFile(file, 1);
1121     }
1122     else        /* unknown chunk -- ignore */
1123       ReadUnusedBytesFromFile(file, chunk_size);
1124   }
1125
1126   fclose(file);
1127
1128   if (snd_info->data_ptr == NULL)
1129   {
1130     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1131     free(snd_info);
1132     return NULL;
1133   }
1134
1135   for (i=0; i<snd_info->data_len; i++)
1136     ((byte *)snd_info->data_ptr)[i] = ((byte *)snd_info->data_ptr)[i] ^ 0x80;
1137
1138 #endif  /* PLATFORM_UNIX */
1139
1140   snd_info->type = SND_TYPE_WAV;
1141   snd_info->source_filename = getStringCopy(filename);
1142
1143   return snd_info;
1144 }
1145
1146 SoundInfo *LoadCustomSound(char *basename)
1147 {
1148   char *filename = getCustomSoundFilename(basename);
1149
1150   if (filename == NULL)
1151   {
1152     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1153     return FALSE;
1154   }
1155
1156   printf("-> '%s'\n", filename);
1157
1158   return Load_WAV(filename);
1159 }
1160
1161 void InitSoundList(int num_list_entries)
1162 {
1163   Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1164   num_sounds = num_list_entries;
1165 }
1166
1167 void LoadSoundToList(char *basename, int list_pos)
1168 {
1169   if (Sound == NULL || list_pos >= num_sounds)
1170     return;
1171
1172   if (Sound[list_pos])
1173     FreeSound(Sound[list_pos]);
1174
1175   Sound[list_pos] = LoadCustomSound(basename);
1176 }
1177
1178 static MusicInfo *Load_MOD(char *filename)
1179 {
1180 #if defined(TARGET_SDL)
1181   MusicInfo *mod_info;
1182
1183   if (!audio.sound_available)
1184     return NULL;
1185
1186   mod_info = checked_calloc(sizeof(MusicInfo));
1187
1188   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1189   {
1190     Error(ERR_WARN, "cannot read music file '%s'", filename);
1191     free(mod_info);
1192     return NULL;
1193   }
1194
1195   mod_info->type = MUS_TYPE_MOD;
1196   mod_info->source_filename = getStringCopy(filename);
1197
1198   return mod_info;
1199 #else
1200   return NULL;
1201 #endif
1202 }
1203
1204 void LoadCustomMusic(void)
1205 {
1206   char *music_directory = getCustomMusicDirectory();
1207   DIR *dir;
1208   struct dirent *dir_entry;
1209
1210   if (!audio.sound_available)
1211     return;
1212
1213   if ((dir = opendir(music_directory)) == NULL)
1214   {
1215     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1216     audio.music_available = FALSE;
1217     return;
1218   }
1219
1220   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1221   {
1222     char *basename = dir_entry->d_name;
1223     char *filename = getPath2(music_directory, basename);
1224     MusicInfo *mus_info = NULL;
1225
1226     if (FileIsSound(filename))
1227       mus_info = Load_WAV(filename);
1228     else if (FileIsMusic(filename))
1229       mus_info = Load_MOD(filename);
1230
1231     free(filename);
1232
1233     if (mus_info)
1234     {
1235       num_music++;
1236       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1237       Music[num_music -1] = mus_info;
1238     }
1239   }
1240
1241   closedir(dir);
1242
1243   if (num_music == 0)
1244     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1245           music_directory);
1246 }
1247
1248 void PlayMusic(int nr)
1249 {
1250   if (!audio.music_available)
1251     return;
1252
1253 #if defined(TARGET_SDL)
1254
1255   if (Music[nr]->type == MUS_TYPE_MOD)
1256   {
1257     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1258     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1259   }
1260   else                          /* play WAV music loop */
1261   {
1262     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1263     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1264   }
1265
1266 #else
1267
1268   PlaySoundMusic(nr);
1269
1270 #endif
1271 }
1272
1273 void PlaySound(int nr)
1274 {
1275   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1276 }
1277
1278 void PlaySoundStereo(int nr, int stereo)
1279 {
1280   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1281 }
1282
1283 void PlaySoundLoop(int nr)
1284 {
1285   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1286 }
1287
1288 void PlaySoundMusic(int nr)
1289 {
1290   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1291 }
1292
1293 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1294 {
1295   struct SoundControl snd_ctrl = emptySoundControl;
1296
1297   if (!audio.sound_available ||
1298       !audio.sound_enabled ||
1299       audio.sound_deactivated)
1300     return;
1301
1302   if (volume < PSND_MIN_VOLUME)
1303     volume = PSND_MIN_VOLUME;
1304   else if (volume > PSND_MAX_VOLUME)
1305     volume = PSND_MAX_VOLUME;
1306
1307   if (stereo < PSND_MAX_LEFT)
1308     stereo = PSND_MAX_LEFT;
1309   else if (stereo > PSND_MAX_RIGHT)
1310     stereo = PSND_MAX_RIGHT;
1311
1312   snd_ctrl.nr           = nr;
1313   snd_ctrl.volume       = volume;
1314   snd_ctrl.stereo       = stereo;
1315   snd_ctrl.loop         = (loop_type != PSND_NO_LOOP);
1316   snd_ctrl.music        = (loop_type == PSND_MUSIC);
1317   snd_ctrl.active       = TRUE;
1318
1319 #if 0
1320   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1321   snd_ctrl.data_len     = Sound[nr].data_len;
1322 #endif
1323
1324 #if defined(TARGET_SDL)
1325   Mix_Volume(-1, SOUND_MAX_VOLUME);
1326   Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1327 #elif defined(PLATFORM_UNIX)
1328   if (audio.soundserver_pid == 0)       /* we are child process */
1329     return;
1330
1331   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1332   {
1333     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1334     audio.sound_available = audio.sound_enabled = FALSE;
1335     return;
1336   }
1337 #elif defined(PLATFORM_MSDOS)
1338   sound_handler(snd_ctrl);
1339 #endif
1340 }
1341
1342 void FadeMusic(void)
1343 {
1344   if (!audio.sound_available)
1345     return;
1346
1347 #if defined(TARGET_SDL)
1348   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1349   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1350 #else
1351   StopSoundExt(-1, SSND_FADE_MUSIC);
1352 #endif
1353 }
1354
1355 void FadeSound(int nr)
1356 {
1357   StopSoundExt(nr, SSND_FADE_SOUND);
1358 }
1359
1360 void FadeSounds()
1361 {
1362   FadeMusic();
1363   StopSoundExt(-1, SSND_FADE_ALL);
1364 }
1365
1366 void StopMusic(void)
1367 {
1368 #if defined(TARGET_SDL)
1369   if (!audio.sound_available)
1370     return;
1371
1372   Mix_HaltMusic();
1373   Mix_HaltChannel(audio.music_channel);
1374 #else
1375   StopSoundExt(-1, SSND_STOP_MUSIC);
1376 #endif
1377 }
1378
1379 void StopSound(int nr)
1380 {
1381   StopSoundExt(nr, SSND_STOP_SOUND);
1382 }
1383
1384 void StopSounds()
1385 {
1386   StopSoundExt(-1, SSND_STOP_ALL);
1387 }
1388
1389 void StopSoundExt(int nr, int method)
1390 {
1391   struct SoundControl snd_ctrl = emptySoundControl;
1392
1393   if (!audio.sound_available)
1394     return;
1395
1396   if (method & SSND_FADING)
1397     snd_ctrl.fade_sound = TRUE;
1398
1399   if (method & SSND_ALL)
1400     snd_ctrl.stop_all_sounds = TRUE;
1401   else
1402   {
1403     snd_ctrl.stop_sound = TRUE;
1404     snd_ctrl.nr = nr;
1405   }
1406
1407   if (method & SSND_MUSIC)
1408     snd_ctrl.music = TRUE;
1409
1410 #if defined(TARGET_SDL)
1411
1412   if (method & SSND_FADING)
1413   {
1414     int i;
1415
1416     for (i=0; i<audio.channels; i++)
1417       if (i != audio.music_channel || snd_ctrl.music)
1418         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1419     if (snd_ctrl.music)
1420       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1421   }
1422   else
1423   {
1424     int i;
1425
1426     for (i=0; i<audio.channels; i++)
1427       if (i != audio.music_channel || snd_ctrl.music)
1428         Mix_HaltChannel(i);
1429     if (snd_ctrl.music)
1430       Mix_HaltMusic();
1431   }
1432
1433 #elif !defined(PLATFORM_MSDOS)
1434
1435   if (audio.soundserver_pid == 0)       /* we are child process */
1436     return;
1437
1438   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1439   {
1440     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1441     audio.sound_available = audio.sound_enabled = FALSE;
1442     return;
1443   }
1444 #else
1445   sound_handler(snd_ctrl);
1446 #endif
1447 }
1448
1449 static void InitReloadSoundsOrMusic(char *set_name, int type)
1450 {
1451   struct SoundControl snd_ctrl = emptySoundControl;
1452   TreeInfo *ti =
1453     (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1454   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1455   unsigned long str_size2 = strlen(ti->basepath) + 1;
1456   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1457
1458   if (!audio.sound_available)
1459     return;
1460
1461   if (leveldir_current == NULL)
1462     Error(ERR_EXIT, "leveldir_current == NULL");
1463
1464   snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1465   snd_ctrl.reload_music  = (type == SND_RELOAD_MUSIC);
1466   snd_ctrl.data_len = strlen(set_name) + 1;
1467
1468 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1469   if (type == SND_RELOAD_SOUNDS)
1470     audio.audio.func_reload_sounds();
1471   else
1472     audio.audio.func_reload_music();
1473 #elif defined(PLATFORM_UNIX)
1474   if (audio.soundserver_pid == 0)       /* we are child process */
1475     return;
1476
1477   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1478             sizeof(snd_ctrl)) < 0 ||
1479       write(audio.soundserver_pipe[1], set_name,
1480             snd_ctrl.data_len) < 0 ||
1481       write(audio.soundserver_pipe[1], leveldir_current,
1482             sizeof(TreeInfo)) < 0 ||
1483       write(audio.soundserver_pipe[1], ti,
1484             sizeof(TreeInfo)) < 0 ||
1485       write(audio.soundserver_pipe[1], &str_size1,
1486             sizeof(unsigned long)) < 0 ||
1487       write(audio.soundserver_pipe[1], &str_size2,
1488             sizeof(unsigned long)) < 0 ||
1489       write(audio.soundserver_pipe[1], &str_size3,
1490             sizeof(unsigned long)) < 0 ||
1491       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1492             str_size1) < 0 ||
1493       write(audio.soundserver_pipe[1], ti->basepath,
1494             str_size2) < 0 ||
1495       write(audio.soundserver_pipe[1], ti->fullpath,
1496             str_size3) < 0)
1497   {
1498     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1499     audio.sound_available = audio.sound_enabled = FALSE;
1500     return;
1501   }
1502
1503   printf("A\n");
1504
1505 #endif
1506 }
1507
1508 void InitReloadSounds(char *set_name)
1509 {
1510   InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1511 }
1512
1513 void InitReloadMusic(char *set_name)
1514 {
1515   InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1516 }
1517
1518 void FreeSound(SoundInfo *sound)
1519 {
1520   if (sound == NULL)
1521     return;
1522
1523   if (sound->data_ptr)
1524   {
1525 #if defined(TARGET_SDL)
1526     Mix_FreeChunk(sound->data_ptr);
1527 #elif defined(TARGET_ALLEGRO)
1528     destroy_sample(sound->data_ptr);
1529 #else   /* PLATFORM_UNIX */
1530     free(sound->data_ptr);
1531 #endif
1532   }
1533
1534   free(sound);
1535 }
1536
1537 void FreeMusic(MusicInfo *music)
1538 {
1539   if (music == NULL)
1540     return;
1541
1542   if (music->data_ptr)
1543   {
1544 #if defined(TARGET_SDL)
1545     if (music->type == MUS_TYPE_MOD)
1546       Mix_FreeMusic(music->data_ptr);
1547     else
1548       Mix_FreeChunk(music->data_ptr);
1549 #elif defined(TARGET_ALLEGRO)
1550     destroy_sample(music->data_ptr);
1551 #else   /* PLATFORM_UNIX */
1552     free(music->data_ptr);
1553 #endif
1554   }
1555
1556   free(music);
1557 }
1558
1559 void FreeAllSounds()
1560 {
1561   int i;
1562
1563   if (Sound == NULL)
1564     return;
1565
1566   for(i=0; i<num_sounds; i++)
1567     FreeSound(Sound[i]);
1568
1569   free(Sound);
1570   Sound = NULL;
1571 }
1572
1573 void FreeAllMusic()
1574 {
1575   int i;
1576
1577   if (Music == NULL)
1578     return;
1579
1580   for(i=0; i<num_music; i++)
1581     FreeMusic(Music[i]);
1582
1583   free(Music);
1584   Music = NULL;
1585 }
1586
1587 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
1588 /* ========================================================================= */