rnd-20020427-5-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 struct AudioFormatInfo afmt =
36 {
37   TRUE, 0, DEFAULT_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_FRAGMENT_SIZE
38 };
39
40 static int playing_sounds = 0;
41 static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
42 static struct SoundControl emptySoundControl =
43 {
44   -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, 0,0, 0,NULL
45 };
46
47 #if defined(PLATFORM_UNIX)
48 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
49 static short premix_first_buffer[SND_BLOCKSIZE];
50 #if defined(AUDIO_STREAMING_DSP)
51 static short premix_left_buffer[SND_BLOCKSIZE];
52 static short premix_right_buffer[SND_BLOCKSIZE];
53 static long premix_last_buffer[SND_BLOCKSIZE];
54 #endif
55 static byte playing_buffer[SND_BLOCKSIZE];
56 #endif
57
58 /* forward declaration of internal functions */
59 #if defined(AUDIO_STREAMING_DSP)
60 static void SoundServer_InsertNewSound(struct SoundControl);
61 static void InitAudioDevice_DSP(struct AudioFormatInfo *);
62 #elif defined(PLATFORM_HPUX)
63 static void InitAudioDevice_HPUX(struct AudioFormatInfo *);
64 #elif defined(PLATFORM_UNIX)
65 static unsigned char linear_to_ulaw(int);
66 static int ulaw_to_linear(unsigned char);
67 #elif defined(PLATFORM_MSDOS)
68 static void SoundServer_InsertNewSound(struct SoundControl);
69 static void SoundServer_StopSound(struct SoundControl);
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(&afmt);
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       if (leveldir_current == NULL)
237         leveldir_current = checked_calloc(sizeof(TreeInfo));
238       if (ti == NULL)
239         ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
240       if (leveldir_current->fullpath != NULL)
241         free(leveldir_current->fullpath);
242       if (ti->basepath != NULL)
243         free(ti->basepath);
244       if (ti->fullpath != NULL)
245         free(ti->fullpath);
246
247       if (read(audio.soundserver_pipe[0], set_name,
248                snd_ctrl.data_len) != snd_ctrl.data_len ||
249           read(audio.soundserver_pipe[0], leveldir_current,
250                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
251           read(audio.soundserver_pipe[0], ti,
252                sizeof(TreeInfo)) != sizeof(TreeInfo) ||
253           read(audio.soundserver_pipe[0], &str_size1,
254                sizeof(unsigned long)) != sizeof(unsigned long) ||
255           read(audio.soundserver_pipe[0], &str_size2,
256                sizeof(unsigned long)) != sizeof(unsigned long) ||
257           read(audio.soundserver_pipe[0], &str_size3,
258                sizeof(unsigned long)) != sizeof(unsigned long))
259         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
260
261       leveldir_current->fullpath = checked_calloc(str_size1);
262       ti->basepath = checked_calloc(str_size2);
263       ti->fullpath = checked_calloc(str_size3);
264
265       if (read(audio.soundserver_pipe[0], leveldir_current->fullpath,
266                str_size1) != str_size1 ||
267           read(audio.soundserver_pipe[0], ti->basepath,
268                str_size2) != str_size2 ||
269           read(audio.soundserver_pipe[0], ti->fullpath,
270                str_size3) != str_size3)
271         Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
272
273       InitPlaylist();
274
275       close(audio.device_fd);
276
277       if (snd_ctrl.reload_sounds)
278       {
279         artwork.sounds_set_current = set_name;
280         audio.func_reload_sounds();
281       }
282       else
283       {
284         artwork.music_set_current = set_name;
285         audio.func_reload_music();
286       }
287
288       free(set_name);
289
290       continue;
291     }
292
293 #if defined(AUDIO_STREAMING_DSP)
294
295     if (snd_ctrl.fade_sound)
296     {
297       if (!playing_sounds)
298         continue;
299
300       if (snd_ctrl.music)
301         playlist[audio.music_channel].fade_sound = TRUE;
302       else
303         for(i=0; i<MAX_SOUNDS_PLAYING; i++)
304           if (snd_ctrl.stop_all_sounds ||
305               (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr))
306             playlist[i].fade_sound = TRUE;
307     }
308     else if (snd_ctrl.stop_all_sounds)
309     {
310       if (!playing_sounds)
311         continue;
312
313       for(i=0; i<MAX_SOUNDS_PLAYING; i++)
314         playlist[i] = emptySoundControl;
315       playing_sounds = 0;
316
317       close(audio.device_fd);
318     }
319     else if (snd_ctrl.stop_sound)
320     {
321       if (!playing_sounds)
322         continue;
323
324       if (snd_ctrl.music)
325       {
326         playlist[audio.music_channel] = emptySoundControl;
327         playing_sounds--;
328       }
329
330       for(i=0; i<MAX_SOUNDS_PLAYING; i++)
331       {
332         if (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr)
333         {
334           playlist[i] = emptySoundControl;
335           playing_sounds--;
336         }
337       }
338
339       if (!playing_sounds)
340         close(audio.device_fd);
341     }
342
343     if (playing_sounds || snd_ctrl.active)
344     {
345       if (playing_sounds ||
346           (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0)
347       {
348         struct timeval delay = { 0, 0 };
349
350         if (!playing_sounds)    /* we just opened the audio device */
351           InitAudioDevice_DSP(&afmt);
352
353         if (snd_ctrl.active)    /* new sound has arrived */
354           SoundServer_InsertNewSound(snd_ctrl);
355
356         while (playing_sounds &&
357                select(audio.soundserver_pipe[0] + 1,
358                       &sound_fdset, NULL, NULL, &delay) < 1)
359         {       
360           short *sample_ptr;
361           int sample_size;
362           int max_sample_size;
363           int fragment_size = afmt.fragment_size;
364           int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
365           boolean stereo = afmt.stereo;
366
367           FD_SET(audio.soundserver_pipe[0], &sound_fdset);
368
369           max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
370
371           /* first clear the last premixing buffer */
372           memset(premix_last_buffer, 0,
373                  max_sample_size * (stereo ? 2 : 1) * sizeof(long));
374
375           for(i=0; i<MAX_SOUNDS_PLAYING; i++)
376           {
377             int j;
378
379             if (!playlist[i].active)
380               continue;
381
382             /* get pointer and size of the actual sound sample */
383             sample_ptr = (short *)playlist[i].data_ptr +playlist[i].playingpos;
384             sample_size = MIN(max_sample_size,
385                               playlist[i].data_len - playlist[i].playingpos);
386             playlist[i].playingpos += sample_size;
387
388             /* fill the first mixing buffer with original sample */
389             memcpy(premix_first_buffer, sample_ptr,
390                    sample_size * sizeof(short));
391
392             /* are we about to restart a looping sound? */
393             if (playlist[i].loop && sample_size < max_sample_size)
394             {
395               playlist[i].playingpos = max_sample_size - sample_size;
396               memcpy(premix_first_buffer + sample_size * sizeof(short),
397                      playlist[i].data_ptr,
398                      (max_sample_size - sample_size) * sizeof(short));
399               sample_size = max_sample_size;
400             }
401
402             /* decrease volume if sound is fading out */
403             if (playlist[i].fade_sound &&
404                 playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
405               playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
406
407             /* adjust volume of actual sound sample */
408             if (playlist[i].volume != PSND_MAX_VOLUME)
409               for(j=0; j<sample_size; j++)
410                 premix_first_buffer[j] =
411                   (playlist[i].volume * (long)premix_first_buffer[j])
412                     >> PSND_MAX_VOLUME_BITS;
413
414             /* fill the last mixing buffer with stereo or mono sound */
415             if (stereo)
416             {
417               int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
418               int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
419               int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
420
421               for(j=0; j<sample_size; j++)
422               {
423                 premix_left_buffer[j] =
424                   (left_volume * premix_first_buffer[j])
425                     >> PSND_MAX_LEFT2RIGHT_BITS;
426                 premix_right_buffer[j] =
427                   (right_volume * premix_first_buffer[j])
428                     >> PSND_MAX_LEFT2RIGHT_BITS;
429
430                 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
431                 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
432               }
433             }
434             else
435             {
436               for(j=0; j<sample_size; j++)
437                 premix_last_buffer[j] += premix_first_buffer[j];
438             }
439
440             /* delete completed sound entries from the playlist */
441             if (playlist[i].playingpos >= playlist[i].data_len)
442             {
443               if (playlist[i].loop)
444                 playlist[i].playingpos = 0;
445               else
446               {
447                 playlist[i] = emptySoundControl;
448                 playing_sounds--;
449               }
450             }
451             else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
452             {
453               playlist[i] = emptySoundControl;
454               playing_sounds--;
455             }
456           }
457
458           /* prepare final playing buffer according to system audio format */
459           for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
460           {
461             /* cut off at 17 bit value */
462             if (premix_last_buffer[i] < -65535)
463               premix_last_buffer[i] = -65535;
464             else if (premix_last_buffer[i] > 65535)
465               premix_last_buffer[i] = 65535;
466
467             /* shift to 16 bit value */
468             premix_last_buffer[i] >>= 1;
469
470             if (afmt.format & AUDIO_FORMAT_U8)
471             {
472               playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
473             }
474             else if (afmt.format & AUDIO_FORMAT_LE)     /* 16 bit */
475             {
476               playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
477               playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
478             }
479             else                                        /* big endian */
480             {
481               playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
482               playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
483             }
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((SAMPLE *)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 void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
808 {
809   /* "ioctl()" expects pointer to 'int' value for stereo flag
810      (boolean is defined as 'char', which will not work here) */
811   unsigned int fragment_spec = 0;
812   int fragment_size_query;
813   int stereo = TRUE;
814   struct
815   {
816     int format_ioctl;
817     int format_result;
818   }
819   formats[] =
820   {
821     /* supported audio format in preferred order */
822     { AFMT_S16_LE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
823     { AFMT_S16_BE,      AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
824     { AFMT_U8,          AUDIO_FORMAT_U8                    },
825     { -1,               -1 }
826   };
827   int i;
828
829   /* determine logarithm (log2) of the fragment size */
830   while ((1 << fragment_spec) < afmt->fragment_size)
831     fragment_spec++;
832
833   /* use two fragments (play one fragment, prepare the other);
834      one fragment would result in interrupted audio output, more
835      than two fragments would raise audio output latency to much */
836   fragment_spec |= 0x00020000;
837
838   /* Example for fragment specification:
839      - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
840      - (with stereo the effective buffer size will shrink to 256)
841      => fragment_size = 0x00020009 */
842
843   if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
844     Error(ERR_EXIT_SOUND_SERVER,
845           "cannot set fragment size of /dev/dsp -- no sounds");
846
847   i = 0;
848   afmt->format = 0;
849   while (formats[i].format_result != -1)
850   {
851     unsigned int audio_format = formats[i].format_ioctl;
852     if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
853     {
854       afmt->format = formats[i].format_result;
855       break;
856     }
857   }
858
859   if (afmt->format == 0)        /* no supported audio format found */
860     Error(ERR_EXIT_SOUND_SERVER,
861           "cannot set audio format of /dev/dsp -- no sounds");
862
863   /* try if we can use stereo sound */
864   afmt->stereo = TRUE;
865   if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
866     afmt->stereo = FALSE;
867
868   if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
869     Error(ERR_EXIT_SOUND_SERVER,
870           "cannot set sample rate of /dev/dsp -- no sounds");
871
872   /* get the real fragmentation size; this should return 512 */
873   if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
874     Error(ERR_EXIT_SOUND_SERVER,
875           "cannot get fragment size of /dev/dsp -- no sounds");
876   if (fragment_size_query != afmt->fragment_size)
877     Error(ERR_EXIT_SOUND_SERVER,
878           "cannot set fragment size of /dev/dsp -- no sounds");
879 }
880 #endif  /* AUDIO_LINUX_IOCTL */
881
882 #if defined(PLATFORM_NETBSD)
883 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
884 {
885   audio_info_t a_info;
886   boolean stereo = TRUE;
887
888   AUDIO_INITINFO(&a_info);
889   a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
890   a_info.play.precision = 8;
891   a_info.play.channels = 2;
892   a_info.play.sample_rate = sample_rate;
893   a_info.blocksize = fragment_size;
894
895   afmt->format = AUDIO_FORMAT_U8;
896   afmt->stereo = TRUE;
897
898   if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
899   {
900     /* try to disable stereo */
901     a_info.play.channels = 1;
902
903     afmt->stereo = FALSE;
904
905     if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
906       Error(ERR_EXIT_SOUND_SERVER,
907             "cannot set sample rate of /dev/audio -- no sounds");
908   }
909 }
910 #endif /* PLATFORM_NETBSD */
911
912 #if defined(PLATFORM_HPUX)
913 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
914 {
915   struct audio_describe ainfo;
916   int audio_ctl;
917
918   audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
919   if (audio_ctl == -1)
920     Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
921
922   if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
923     Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
924
925   if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
926     Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
927
928   ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
929   ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
930
931   afmt->format = AUDIO_FORMAT_U8;
932   afmt->stereo = FALSE;
933   afmt->sample_rate = 8000;
934
935   close(audio_ctl);
936 }
937 #endif /* PLATFORM_HPUX */
938
939 #if defined(PLATFORM_UNIX)
940 static void InitAudioDevice_DSP(struct AudioFormatInfo *afmt)
941 {
942 #if defined(AUDIO_LINUX_IOCTL)
943   InitAudioDevice_Linux(afmt);
944 #elif defined(PLATFORM_NETBSD)
945   InitAudioDevice_NetBSD(afmt);
946 #elif defined(PLATFORM_HPUX)
947   InitAudioDevice_HPUX(afmt);
948 #endif
949 }
950 #endif /* PLATFORM_UNIX */
951
952 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
953
954 /* these two are stolen from "sox"... :) */
955
956 /*
957 ** This routine converts from linear to ulaw.
958 **
959 ** Craig Reese: IDA/Supercomputing Research Center
960 ** Joe Campbell: Department of Defense
961 ** 29 September 1989
962 **
963 ** References:
964 ** 1) CCITT Recommendation G.711  (very difficult to follow)
965 ** 2) "A New Digital Technique for Implementation of Any
966 **     Continuous PCM Companding Law," Villeret, Michel,
967 **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
968 **     1973, pg. 11.12-11.17
969 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
970 **     for Analog-to_Digital Conversion Techniques,"
971 **     17 February 1987
972 **
973 ** Input: Signed 16 bit linear sample
974 ** Output: 8 bit ulaw sample
975 */
976
977 #define ZEROTRAP    /* turn on the trap as per the MIL-STD */
978 #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
979 #define CLIP 32635
980
981 static unsigned char linear_to_ulaw(int sample)
982 {
983   static int exp_lut[256] =
984   {
985     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
986     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
987     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
988     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
989     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
990     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
991     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
992     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
993     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
994     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
995     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
996     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
997     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
998     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
999     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1000     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1001   };
1002
1003   int sign, exponent, mantissa;
1004   unsigned char ulawbyte;
1005
1006   /* Get the sample into sign-magnitude. */
1007   sign = (sample >> 8) & 0x80;          /* set aside the sign */
1008   if (sign != 0)
1009     sample = -sample;                   /* get magnitude */
1010   if (sample > CLIP)
1011     sample = CLIP;                      /* clip the magnitude */
1012
1013   /* Convert from 16 bit linear to ulaw. */
1014   sample = sample + BIAS;
1015   exponent = exp_lut[( sample >> 7 ) & 0xFF];
1016   mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1017   ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1018 #ifdef ZEROTRAP
1019   if (ulawbyte == 0)
1020     ulawbyte = 0x02;                    /* optional CCITT trap */
1021 #endif
1022
1023   return(ulawbyte);
1024 }
1025
1026 /*
1027 ** This routine converts from ulaw to 16 bit linear.
1028 **
1029 ** Craig Reese: IDA/Supercomputing Research Center
1030 ** 29 September 1989
1031 **
1032 ** References:
1033 ** 1) CCITT Recommendation G.711  (very difficult to follow)
1034 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1035 **     for Analog-to_Digital Conversion Techniques,"
1036 **     17 February 1987
1037 **
1038 ** Input: 8 bit ulaw sample
1039 ** Output: signed 16 bit linear sample
1040 */
1041
1042 static int ulaw_to_linear(unsigned char ulawbyte)
1043 {
1044   static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1045   int sign, exponent, mantissa, sample;
1046
1047   ulawbyte = ~ ulawbyte;
1048   sign = ( ulawbyte & 0x80 );
1049   exponent = ( ulawbyte >> 4 ) & 0x07;
1050   mantissa = ulawbyte & 0x0F;
1051   sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1052   if (sign != 0)
1053     sample = -sample;
1054
1055   return(sample);
1056 }
1057 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1058
1059
1060 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS            */
1061 /* ========================================================================= */
1062 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS                          */
1063
1064 #define CHUNK_ID_LEN            4       /* IFF style chunk id length */
1065 #define WAV_HEADER_SIZE         16      /* size of WAV file header */
1066
1067 static SoundInfo *Load_WAV(char *filename)
1068 {
1069   SoundInfo *snd_info;
1070 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1071   byte sound_header_buffer[WAV_HEADER_SIZE];
1072   char chunk_name[CHUNK_ID_LEN + 1];
1073   int chunk_size;
1074   short *data_ptr;
1075   FILE *file;
1076   int i;
1077 #endif
1078
1079   if (!audio.sound_available)
1080     return NULL;
1081
1082   snd_info = checked_calloc(sizeof(SoundInfo));
1083
1084 #if defined(TARGET_SDL)
1085
1086   if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1087   {
1088     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1089     free(snd_info);
1090     return NULL;
1091   }
1092
1093 #elif defined(TARGET_ALLEGRO)
1094
1095   if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1096   {
1097     Error(ERR_WARN, "cannot read sound file '%s'", filename);
1098     free(snd_info);
1099     return NULL;
1100   }
1101
1102 #else   /* PLATFORM_UNIX */
1103
1104   if ((file = fopen(filename, MODE_READ)) == NULL)
1105   {
1106     Error(ERR_WARN, "cannot open sound file '%s'", filename);
1107     free(snd_info);
1108     return NULL;
1109   }
1110
1111   /* read chunk id "RIFF" */
1112   getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1113   if (strcmp(chunk_name, "RIFF") != 0)
1114   {
1115     Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1116     fclose(file);
1117     free(snd_info);
1118     return NULL;
1119   }
1120
1121   /* read "RIFF" type id "WAVE" */
1122   getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1123   if (strcmp(chunk_name, "WAVE") != 0)
1124   {
1125     Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1126     fclose(file);
1127     free(snd_info);
1128     return NULL;
1129   }
1130
1131   while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1132   {
1133     if (strcmp(chunk_name, "fmt ") == 0)
1134     {
1135       /* read header information */
1136       for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1137         sound_header_buffer[i] = fgetc(file);
1138
1139       if (chunk_size > WAV_HEADER_SIZE)
1140         ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1141     }
1142     else if (strcmp(chunk_name, "data") == 0)
1143     {
1144       snd_info->data_len = chunk_size;
1145       snd_info->data_ptr = checked_malloc(snd_info->data_len);
1146
1147       /* read sound data */
1148       if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1149           snd_info->data_len)
1150       {
1151         Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1152         fclose(file);
1153         free(snd_info->data_ptr);
1154         free(snd_info);
1155         return NULL;
1156       }
1157
1158       /* check for odd number of sample bytes (data chunk is word aligned) */
1159       if ((chunk_size % 2) == 1)
1160         ReadUnusedBytesFromFile(file, 1);
1161     }
1162     else        /* unknown chunk -- ignore */
1163       ReadUnusedBytesFromFile(file, chunk_size);
1164   }
1165
1166   fclose(file);
1167
1168   if (snd_info->data_ptr == NULL)
1169   {
1170     Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1171     free(snd_info);
1172     return NULL;
1173   }
1174
1175   /* convert unsigned 8 bit sample data to signed 16 bit sample data */
1176
1177   data_ptr = checked_malloc(snd_info->data_len * sizeof(short));
1178
1179   for (i=0; i<snd_info->data_len; i++)
1180     data_ptr[i] = ((short)(((byte *)snd_info->data_ptr)[i] ^ 0x80)) << 8;
1181
1182   free(snd_info->data_ptr);
1183   snd_info->data_ptr = data_ptr;
1184
1185 #endif  /* PLATFORM_UNIX */
1186
1187   snd_info->type = SND_TYPE_WAV;
1188   snd_info->source_filename = getStringCopy(filename);
1189
1190   return snd_info;
1191 }
1192
1193 SoundInfo *LoadCustomSound(char *basename)
1194 {
1195   char *filename = getCustomSoundFilename(basename);
1196
1197   if (filename == NULL)
1198   {
1199     Error(ERR_WARN, "cannot find sound file '%s'", basename);
1200     return FALSE;
1201   }
1202
1203   return Load_WAV(filename);
1204 }
1205
1206 void InitSoundList(int num_list_entries)
1207 {
1208   Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1209   num_sounds = num_list_entries;
1210 }
1211
1212 void LoadSoundToList(char *basename, int list_pos)
1213 {
1214   if (Sound == NULL || list_pos >= num_sounds)
1215     return;
1216
1217   if (Sound[list_pos])
1218     FreeSound(Sound[list_pos]);
1219
1220   Sound[list_pos] = LoadCustomSound(basename);
1221 }
1222
1223 static MusicInfo *Load_MOD(char *filename)
1224 {
1225 #if defined(TARGET_SDL)
1226   MusicInfo *mod_info;
1227
1228   if (!audio.sound_available)
1229     return NULL;
1230
1231   mod_info = checked_calloc(sizeof(MusicInfo));
1232
1233   if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1234   {
1235     Error(ERR_WARN, "cannot read music file '%s'", filename);
1236     free(mod_info);
1237     return NULL;
1238   }
1239
1240   mod_info->type = MUS_TYPE_MOD;
1241   mod_info->source_filename = getStringCopy(filename);
1242
1243   return mod_info;
1244 #else
1245   return NULL;
1246 #endif
1247 }
1248
1249 void LoadCustomMusic(void)
1250 {
1251   char *music_directory = getCustomMusicDirectory();
1252   DIR *dir;
1253   struct dirent *dir_entry;
1254
1255   if (!audio.sound_available)
1256     return;
1257
1258   if ((dir = opendir(music_directory)) == NULL)
1259   {
1260     Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1261     audio.music_available = FALSE;
1262     return;
1263   }
1264
1265   while ((dir_entry = readdir(dir)) != NULL)    /* loop until last dir entry */
1266   {
1267     char *basename = dir_entry->d_name;
1268     char *filename = getPath2(music_directory, basename);
1269     MusicInfo *mus_info = NULL;
1270
1271     if (FileIsSound(basename))
1272       mus_info = Load_WAV(filename);
1273     else if (FileIsMusic(basename))
1274       mus_info = Load_MOD(filename);
1275
1276     free(filename);
1277
1278     if (mus_info)
1279     {
1280       num_music++;
1281       Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1282       Music[num_music -1] = mus_info;
1283     }
1284   }
1285
1286   closedir(dir);
1287
1288   if (num_music == 0)
1289     Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1290           music_directory);
1291 }
1292
1293 void PlayMusic(int nr)
1294 {
1295   if (!audio.music_available)
1296     return;
1297
1298 #if defined(TARGET_SDL)
1299
1300   nr = nr % num_music;
1301
1302   if (Music[nr]->type == MUS_TYPE_MOD)
1303   {
1304     Mix_PlayMusic(Music[nr]->data_ptr, -1);
1305     Mix_VolumeMusic(SOUND_MAX_VOLUME);  /* must be _after_ Mix_PlayMusic()! */
1306   }
1307   else                          /* play WAV music loop */
1308   {
1309     Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1310     Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1311   }
1312
1313 #else
1314
1315   PlaySoundMusic(nr);
1316
1317 #endif
1318 }
1319
1320 void PlaySound(int nr)
1321 {
1322   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
1323 }
1324
1325 void PlaySoundStereo(int nr, int stereo)
1326 {
1327   PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
1328 }
1329
1330 void PlaySoundLoop(int nr)
1331 {
1332   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
1333 }
1334
1335 void PlaySoundMusic(int nr)
1336 {
1337   PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_MUSIC);
1338 }
1339
1340 void PlaySoundExt(int nr, int volume, int stereo, boolean loop_type)
1341 {
1342   struct SoundControl snd_ctrl = emptySoundControl;
1343
1344   if (!audio.sound_available ||
1345       !audio.sound_enabled ||
1346       audio.sound_deactivated)
1347     return;
1348
1349   if (volume < PSND_MIN_VOLUME)
1350     volume = PSND_MIN_VOLUME;
1351   else if (volume > PSND_MAX_VOLUME)
1352     volume = PSND_MAX_VOLUME;
1353
1354   if (stereo < PSND_MAX_LEFT)
1355     stereo = PSND_MAX_LEFT;
1356   else if (stereo > PSND_MAX_RIGHT)
1357     stereo = PSND_MAX_RIGHT;
1358
1359   snd_ctrl.nr           = nr;
1360   snd_ctrl.volume       = volume;
1361   snd_ctrl.stereo       = stereo;
1362   snd_ctrl.loop         = (loop_type != PSND_NO_LOOP);
1363   snd_ctrl.music        = (loop_type == PSND_MUSIC);
1364   snd_ctrl.active       = TRUE;
1365
1366 #if 0
1367   /* now only used internally in sound server child process */
1368   snd_ctrl.data_ptr     = Sound[nr].data_ptr;
1369   snd_ctrl.data_len     = Sound[nr].data_len;
1370 #endif
1371
1372 #if defined(TARGET_SDL)
1373   Mix_Volume(-1, SOUND_MAX_VOLUME);
1374   Mix_PlayChannel(-1, Sound[nr]->data_ptr, (loop_type ? -1 : 0));
1375 #elif defined(PLATFORM_UNIX)
1376   if (audio.soundserver_pid == 0)       /* we are child process */
1377     return;
1378
1379   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1380   {
1381     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1382     audio.sound_available = audio.sound_enabled = FALSE;
1383     return;
1384   }
1385 #elif defined(PLATFORM_MSDOS)
1386   sound_handler(snd_ctrl);
1387 #endif
1388 }
1389
1390 void FadeMusic(void)
1391 {
1392   if (!audio.sound_available)
1393     return;
1394
1395 #if defined(TARGET_SDL)
1396   Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1397   Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1398 #else
1399   StopSoundExt(-1, SSND_FADE_MUSIC);
1400 #endif
1401 }
1402
1403 void FadeSound(int nr)
1404 {
1405   StopSoundExt(nr, SSND_FADE_SOUND);
1406 }
1407
1408 void FadeSounds()
1409 {
1410   FadeMusic();
1411   StopSoundExt(-1, SSND_FADE_ALL);
1412 }
1413
1414 void StopMusic(void)
1415 {
1416 #if defined(TARGET_SDL)
1417   if (!audio.sound_available)
1418     return;
1419
1420   Mix_HaltMusic();
1421   Mix_HaltChannel(audio.music_channel);
1422 #else
1423   StopSoundExt(-1, SSND_STOP_MUSIC);
1424 #endif
1425 }
1426
1427 void StopSound(int nr)
1428 {
1429   StopSoundExt(nr, SSND_STOP_SOUND);
1430 }
1431
1432 void StopSounds()
1433 {
1434   StopSoundExt(-1, SSND_STOP_ALL);
1435 }
1436
1437 void StopSoundExt(int nr, int method)
1438 {
1439   struct SoundControl snd_ctrl = emptySoundControl;
1440
1441   if (!audio.sound_available)
1442     return;
1443
1444   if (method & SSND_FADING)
1445     snd_ctrl.fade_sound = TRUE;
1446
1447   if (method & SSND_ALL)
1448     snd_ctrl.stop_all_sounds = TRUE;
1449   else
1450   {
1451     snd_ctrl.stop_sound = TRUE;
1452     snd_ctrl.nr = nr;
1453   }
1454
1455   if (method & SSND_MUSIC)
1456     snd_ctrl.music = TRUE;
1457
1458 #if defined(TARGET_SDL)
1459
1460   if (method & SSND_FADING)
1461   {
1462     int i;
1463
1464     for (i=0; i<audio.channels; i++)
1465       if (i != audio.music_channel || snd_ctrl.music)
1466         Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1467     if (snd_ctrl.music)
1468       Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1469   }
1470   else
1471   {
1472     int i;
1473
1474     for (i=0; i<audio.channels; i++)
1475       if (i != audio.music_channel || snd_ctrl.music)
1476         Mix_HaltChannel(i);
1477     if (snd_ctrl.music)
1478       Mix_HaltMusic();
1479   }
1480
1481 #elif !defined(PLATFORM_MSDOS)
1482
1483   if (audio.soundserver_pid == 0)       /* we are child process */
1484     return;
1485
1486   if (write(audio.soundserver_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1487   {
1488     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1489     audio.sound_available = audio.sound_enabled = FALSE;
1490     return;
1491   }
1492 #else
1493   sound_handler(snd_ctrl);
1494 #endif
1495 }
1496
1497 static void InitReloadSoundsOrMusic(char *set_name, int type)
1498 {
1499 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
1500   struct SoundControl snd_ctrl = emptySoundControl;
1501   TreeInfo *ti =
1502     (type == SND_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current);
1503   unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
1504   unsigned long str_size2 = strlen(ti->basepath) + 1;
1505   unsigned long str_size3 = strlen(ti->fullpath) + 1;
1506 #endif
1507
1508   if (!audio.sound_available)
1509     return;
1510
1511 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1512   if (type == SND_RELOAD_SOUNDS)
1513     audio.func_reload_sounds();
1514   else
1515     audio.func_reload_music();
1516 #elif defined(PLATFORM_UNIX)
1517   if (audio.soundserver_pid == 0)       /* we are child process */
1518     return;
1519
1520   if (leveldir_current == NULL)         /* should never happen */
1521     Error(ERR_EXIT, "leveldir_current == NULL");
1522
1523   snd_ctrl.reload_sounds = (type == SND_RELOAD_SOUNDS);
1524   snd_ctrl.reload_music  = (type == SND_RELOAD_MUSIC);
1525   snd_ctrl.data_len = strlen(set_name) + 1;
1526
1527   if (write(audio.soundserver_pipe[1], &snd_ctrl,
1528             sizeof(snd_ctrl)) < 0 ||
1529       write(audio.soundserver_pipe[1], set_name,
1530             snd_ctrl.data_len) < 0 ||
1531       write(audio.soundserver_pipe[1], leveldir_current,
1532             sizeof(TreeInfo)) < 0 ||
1533       write(audio.soundserver_pipe[1], ti,
1534             sizeof(TreeInfo)) < 0 ||
1535       write(audio.soundserver_pipe[1], &str_size1,
1536             sizeof(unsigned long)) < 0 ||
1537       write(audio.soundserver_pipe[1], &str_size2,
1538             sizeof(unsigned long)) < 0 ||
1539       write(audio.soundserver_pipe[1], &str_size3,
1540             sizeof(unsigned long)) < 0 ||
1541       write(audio.soundserver_pipe[1], leveldir_current->fullpath,
1542             str_size1) < 0 ||
1543       write(audio.soundserver_pipe[1], ti->basepath,
1544             str_size2) < 0 ||
1545       write(audio.soundserver_pipe[1], ti->fullpath,
1546             str_size3) < 0)
1547   {
1548     Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1549     audio.sound_available = audio.sound_enabled = FALSE;
1550     return;
1551   }
1552 #endif
1553 }
1554
1555 void InitReloadSounds(char *set_name)
1556 {
1557   InitReloadSoundsOrMusic(set_name, SND_RELOAD_SOUNDS);
1558 }
1559
1560 void InitReloadMusic(char *set_name)
1561 {
1562   InitReloadSoundsOrMusic(set_name, SND_RELOAD_MUSIC);
1563 }
1564
1565 void FreeSound(SoundInfo *sound)
1566 {
1567   if (sound == NULL)
1568     return;
1569
1570   if (sound->data_ptr)
1571   {
1572 #if defined(TARGET_SDL)
1573     Mix_FreeChunk(sound->data_ptr);
1574 #elif defined(TARGET_ALLEGRO)
1575     destroy_sample(sound->data_ptr);
1576 #else   /* PLATFORM_UNIX */
1577     free(sound->data_ptr);
1578 #endif
1579   }
1580
1581   free(sound);
1582 }
1583
1584 void FreeMusic(MusicInfo *music)
1585 {
1586   if (music == NULL)
1587     return;
1588
1589   if (music->data_ptr)
1590   {
1591 #if defined(TARGET_SDL)
1592     if (music->type == MUS_TYPE_MOD)
1593       Mix_FreeMusic(music->data_ptr);
1594     else
1595       Mix_FreeChunk(music->data_ptr);
1596 #elif defined(TARGET_ALLEGRO)
1597     destroy_sample(music->data_ptr);
1598 #else   /* PLATFORM_UNIX */
1599     free(music->data_ptr);
1600 #endif
1601   }
1602
1603   free(music);
1604 }
1605
1606 void FreeAllSounds()
1607 {
1608   int i;
1609
1610   if (Sound == NULL)
1611     return;
1612
1613   for(i=0; i<num_sounds; i++)
1614     FreeSound(Sound[i]);
1615
1616   free(Sound);
1617
1618   Sound = NULL;
1619   num_sounds = 0;
1620 }
1621
1622 void FreeAllMusic()
1623 {
1624   int i;
1625
1626   if (Music == NULL)
1627     return;
1628
1629   for(i=0; i<num_music; i++)
1630     FreeMusic(Music[i]);
1631
1632   free(Music);
1633
1634   Music = NULL;
1635   num_music = 0;
1636 }
1637
1638 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS                          */
1639 /* ========================================================================= */