1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
31 struct ListNode *next;
33 typedef struct ListNode ListNode;
35 static ListNode *newListNode(void);
36 static void addNodeToList(ListNode **, char *, void *);
37 static void deleteNodeFromList(ListNode **, char *, void (*function)(void *));
38 static ListNode *getNodeFromKey(ListNode *, char *);
39 static int getNumNodes(ListNode *);
42 static struct SoundEffectInfo *sound_effect;
43 static ListNode *SoundFileList = NULL;
44 static SoundInfo **Sound = NULL;
45 static MusicInfo **Music = NULL;
46 static int num_sounds = 0, num_music = 0;
49 /* ========================================================================= */
50 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
52 static struct AudioFormatInfo afmt;
53 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
54 static int mixer_active_channels = 0;
56 /* forward declaration of internal functions */
57 static void InitAudioDevice(struct AudioFormatInfo *);
58 static void Mixer_Main(void);
60 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
61 static unsigned char linear_to_ulaw(int);
62 static int ulaw_to_linear(unsigned char);
65 static void ReloadCustomSounds();
66 static void ReloadCustomMusic();
67 static void FreeSound(void *);
69 #if defined(PLATFORM_UNIX)
70 static int OpenAudioDevice(char *audio_device_name)
74 /* check if desired audio device is accessible */
75 if (access(audio_device_name, W_OK) != 0)
78 /* try to open audio device in non-blocking mode */
79 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
80 return audio_device_fd;
82 /* re-open audio device in blocking mode */
83 close(audio_device_fd);
84 audio_device_fd = open(audio_device_name, O_WRONLY);
86 return audio_device_fd;
89 static void CloseAudioDevice(int *audio_device_fd)
91 if (*audio_device_fd == 0)
94 close(*audio_device_fd);
95 *audio_device_fd = -1;
98 static boolean TestAudioDevices(void)
100 static char *audio_device_name[] =
105 int audio_device_fd = -1;
108 /* look for available audio devices, starting with preferred ones */
109 for (i=0; i<sizeof(audio_device_name)/sizeof(char *); i++)
110 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
113 if (audio_device_fd < 0)
115 Error(ERR_WARN, "cannot open audio device -- no sound");
119 close(audio_device_fd);
121 audio.device_name = audio_device_name[i];
126 #if !defined(TARGET_SDL)
127 static boolean ForkAudioProcess(void)
129 if (pipe(audio.mixer_pipe) < 0)
131 Error(ERR_WARN, "cannot create pipe -- no sounds");
135 if ((audio.mixer_pid = fork()) < 0)
137 Error(ERR_WARN, "cannot create sound server process -- no sounds");
141 if (audio.mixer_pid == 0) /* we are child process */
148 else /* we are parent */
149 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
155 void UnixOpenAudio(void)
157 if (!TestAudioDevices())
160 audio.sound_available = TRUE;
161 audio.sound_enabled = TRUE;
163 #if defined(AUDIO_STREAMING_DSP)
164 audio.music_available = TRUE;
165 audio.loops_available = TRUE;
168 audio.num_channels = NUM_MIXER_CHANNELS;
169 audio.music_channel = MUSIC_CHANNEL;
170 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
173 void UnixCloseAudio(void)
176 close(audio.device_fd);
178 if (audio.mixer_pid > 0) /* we are parent process */
179 kill(audio.mixer_pid, SIGTERM);
182 static void WriteReloadInfoToPipe(char *set_name, int type)
184 struct SoundControl snd_ctrl;
185 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
186 artwork.mus_current);
187 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
188 unsigned long str_size2 = strlen(ti->basepath) + 1;
189 unsigned long str_size3 = strlen(ti->fullpath) + 1;
191 if (audio.mixer_pid == 0) /* we are child process */
194 if (leveldir_current == NULL) /* should never happen */
195 Error(ERR_EXIT, "leveldir_current == NULL");
197 snd_ctrl.active = FALSE;
198 snd_ctrl.state = type;
199 snd_ctrl.data_len = strlen(set_name) + 1;
201 if (write(audio.mixer_pipe[1], &snd_ctrl,
202 sizeof(snd_ctrl)) < 0 ||
203 write(audio.mixer_pipe[1], set_name,
204 snd_ctrl.data_len) < 0 ||
205 write(audio.mixer_pipe[1], leveldir_current,
206 sizeof(TreeInfo)) < 0 ||
207 write(audio.mixer_pipe[1], ti,
208 sizeof(TreeInfo)) < 0 ||
209 write(audio.mixer_pipe[1], &str_size1,
210 sizeof(unsigned long)) < 0 ||
211 write(audio.mixer_pipe[1], &str_size2,
212 sizeof(unsigned long)) < 0 ||
213 write(audio.mixer_pipe[1], &str_size3,
214 sizeof(unsigned long)) < 0 ||
215 write(audio.mixer_pipe[1], leveldir_current->fullpath,
217 write(audio.mixer_pipe[1], ti->basepath,
219 write(audio.mixer_pipe[1], ti->fullpath,
222 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
223 audio.sound_available = audio.sound_enabled = FALSE;
228 static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl)
230 TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ?
231 &artwork.snd_current : &artwork.mus_current);
232 TreeInfo *ti = *ti_ptr;
233 unsigned long str_size1, str_size2, str_size3;
234 static char *set_name = NULL;
239 set_name = checked_malloc(snd_ctrl.data_len);
241 if (leveldir_current == NULL)
242 leveldir_current = checked_calloc(sizeof(TreeInfo));
244 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
245 if (leveldir_current->fullpath != NULL)
246 free(leveldir_current->fullpath);
247 if (ti->basepath != NULL)
249 if (ti->fullpath != NULL)
252 if (read(audio.mixer_pipe[0], set_name,
253 snd_ctrl.data_len) != snd_ctrl.data_len ||
254 read(audio.mixer_pipe[0], leveldir_current,
255 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
256 read(audio.mixer_pipe[0], ti,
257 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
258 read(audio.mixer_pipe[0], &str_size1,
259 sizeof(unsigned long)) != sizeof(unsigned long) ||
260 read(audio.mixer_pipe[0], &str_size2,
261 sizeof(unsigned long)) != sizeof(unsigned long) ||
262 read(audio.mixer_pipe[0], &str_size3,
263 sizeof(unsigned long)) != sizeof(unsigned long))
264 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
266 leveldir_current->fullpath = checked_calloc(str_size1);
267 ti->basepath = checked_calloc(str_size2);
268 ti->fullpath = checked_calloc(str_size3);
270 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
271 str_size1) != str_size1 ||
272 read(audio.mixer_pipe[0], ti->basepath,
273 str_size2) != str_size2 ||
274 read(audio.mixer_pipe[0], ti->fullpath,
275 str_size3) != str_size3)
276 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
278 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
279 artwork.sounds_set_current = set_name;
281 artwork.music_set_current = set_name;
283 #endif /* PLATFORM_UNIX */
285 void Mixer_InitChannels()
289 for(i=0; i<audio.num_channels; i++)
290 mixer[i].active = FALSE;
291 mixer_active_channels = 0;
294 static void Mixer_PlayChannel(int channel)
296 #if defined(PLATFORM_MSDOS)
297 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
299 if (mixer[channel].voice < 0)
302 if (IS_LOOP(mixer[channel]))
303 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
305 voice_set_volume(mixer[channel].voice, snd_ctrl.volume);
306 voice_set_pan(mixer[channel].voice, snd_ctrl.stereo);
307 voice_start(mixer[channel].voice);
311 static void Mixer_StopChannel(int channel)
313 #if defined(PLATFORM_MSDOS)
314 voice_set_volume(mixer[channel].voice, 0);
315 deallocate_voice(mixer[channel].voice);
319 static void Mixer_FadeChannel(int channel)
321 mixer[channel].state |= SND_CTRL_FADE;
323 #if defined(PLATFORM_MSDOS)
324 if (voice_check(mixer[channel].voice))
325 voice_ramp_volume(mixer[channel].voice, 1000, 0);
326 mixer[channel].state &= ~SND_CTRL_IS_LOOP;
330 static void Mixer_RemoveSound(int channel)
332 if (!mixer_active_channels || !mixer[channel].active)
336 printf("REMOVING MIXER SOUND %d\n", channel);
339 Mixer_StopChannel(channel);
341 mixer[channel].active = FALSE;
342 mixer_active_channels--;
345 static void Mixer_InsertSound(struct SoundControl snd_ctrl)
351 printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
354 if (IS_MUSIC(snd_ctrl))
355 snd_ctrl.nr = snd_ctrl.nr % num_music;
356 else if (snd_ctrl.nr >= num_sounds)
359 snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
360 if (snd_info == NULL)
363 printf("sound/music %d undefined\n", snd_ctrl.nr);
369 printf("-> %d\n", mixer_active_channels);
372 if (mixer_active_channels == audio.num_channels)
374 for (i=0; i<audio.num_channels; i++)
376 if (mixer[i].data_ptr == NULL)
379 printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
382 Mixer_RemoveSound(i);
387 /* if mixer is full, remove oldest sound */
388 if (mixer_active_channels == audio.num_channels)
390 int longest = 0, longest_nr = audio.first_sound_channel;
392 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
394 #if !defined(PLATFORM_MSDOS)
395 int actual = 100 * mixer[i].playingpos / mixer[i].data_len;
397 int actual = mixer[i].playingpos;
400 if (!IS_LOOP(mixer[i]) && actual > longest)
407 Mixer_RemoveSound(longest_nr);
410 /* check if sound is already being played (and how often) */
411 for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
412 if (mixer[i].nr == snd_ctrl.nr)
415 /* restart loop sounds only if they are just fading out */
416 if (k >= 1 && IS_LOOP(snd_ctrl))
418 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
420 if (mixer[i].nr == snd_ctrl.nr && IS_FADING(mixer[i]))
422 mixer[i].state &= ~SND_CTRL_FADE;
423 mixer[i].volume = PSND_MAX_VOLUME;
424 #if defined(PLATFORM_MSDOS)
425 mixer[i].state |= SND_CTRL_LOOP;
426 voice_stop_volumeramp(mixer[i].voice);
427 voice_ramp_volume(mixer[i].voice, mixer[i].volume, 1000);
435 /* don't play sound more than n times simultaneously (with n == 2 for now) */
438 int longest = 0, longest_nr = audio.first_sound_channel;
440 /* look for oldest equal sound */
441 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
445 if (!mixer[i].active || mixer[i].nr != snd_ctrl.nr)
448 #if !defined(PLATFORM_MSDOS)
449 actual = 100 * mixer[i].playingpos / mixer[i].data_len;
451 actual = mixer[i].playingpos;
453 if (actual >= longest)
460 Mixer_RemoveSound(longest_nr);
463 /* add new sound to mixer */
464 for(i=0; i<audio.num_channels; i++)
467 printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
471 if (!mixer[i].active ||
472 (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
474 if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
475 (i != audio.music_channel && !mixer[i].active))
477 snd_ctrl.data_ptr = snd_info->data_ptr;
478 snd_ctrl.data_len = snd_info->data_len;
479 snd_ctrl.format = snd_info->format;
481 snd_ctrl.playingpos = 0;
482 snd_ctrl.playingtime = 0;
485 if (snd_info->data_len == 0)
487 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
492 if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && mixer[i].active)
494 printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
497 Mixer_RemoveSound(i);
503 mixer_active_channels++;
506 printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr);
509 Mixer_PlayChannel(i);
516 static void HandleSoundRequest(struct SoundControl snd_ctrl)
520 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
522 ReadReloadInfoFromPipe(snd_ctrl);
523 Mixer_InitChannels();
524 CloseAudioDevice(&audio.device_fd);
526 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
527 ReloadCustomSounds();
531 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
533 if (!mixer_active_channels)
536 if (IS_MUSIC(snd_ctrl))
538 Mixer_FadeChannel(audio.music_channel);
542 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
543 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
544 Mixer_FadeChannel(i);
546 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
548 if (!mixer_active_channels)
551 if (IS_MUSIC(snd_ctrl))
553 Mixer_RemoveSound(audio.music_channel);
557 for(i=audio.first_sound_channel; i<audio.num_channels; i++)
558 if (mixer[i].nr == snd_ctrl.nr || ALL_SOUNDS(snd_ctrl))
559 Mixer_RemoveSound(i);
561 if (!mixer_active_channels)
562 CloseAudioDevice(&audio.device_fd);
564 else if (snd_ctrl.active) /* add new sound to mixer */
566 Mixer_InsertSound(snd_ctrl);
570 void StartMixer(void)
572 if (!audio.sound_available)
575 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
576 if (!ForkAudioProcess())
577 audio.sound_available = FALSE;
581 #if defined(PLATFORM_UNIX) && !defined(TARGET_SDL)
583 static void CopySampleToMixingBuffer(struct SoundControl *snd_ctrl,
584 int sample_pos, int sample_size,
587 void *sample_ptr = snd_ctrl->data_ptr;
590 if (snd_ctrl->format == AUDIO_FORMAT_U8)
591 for (i=0; i<sample_size; i++)
593 ((short)(((byte *)sample_ptr)[sample_pos + i] ^ 0x80)) << 8;
594 else /* AUDIO_FORMAT_S16 */
595 for (i=0; i<sample_size; i++)
597 ((short *)sample_ptr)[sample_pos + i];
600 #if defined(AUDIO_STREAMING_DSP)
601 static void Mixer_Main_DSP()
603 static int stereo_volume[PSND_MAX_LEFT2RIGHT + 1];
604 static boolean stereo_volume_calculated = FALSE;
605 static short premix_first_buffer[SND_BLOCKSIZE];
606 static short premix_left_buffer[SND_BLOCKSIZE];
607 static short premix_right_buffer[SND_BLOCKSIZE];
608 static long premix_last_buffer[SND_BLOCKSIZE];
609 static byte playing_buffer[SND_BLOCKSIZE];
616 if (!stereo_volume_calculated)
618 for(i=0; i<=PSND_MAX_LEFT2RIGHT; i++)
620 (int)sqrt((float)(PSND_MAX_LEFT2RIGHT * PSND_MAX_LEFT2RIGHT - i * i));
622 stereo_volume_calculated = TRUE;
625 if (!mixer_active_channels)
628 if (audio.device_fd < 0)
630 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
633 InitAudioDevice(&afmt);
636 stereo = afmt.stereo;
637 fragment_size = afmt.fragment_size;
638 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
639 max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
641 /* first clear the last premixing buffer */
642 memset(premix_last_buffer, 0,
643 max_sample_size * (stereo ? 2 : 1) * sizeof(long));
645 for(i=0; i<audio.num_channels; i++)
652 if (!mixer[i].active)
655 /* pointer, lenght and actual playing position of sound sample */
656 sample_ptr = mixer[i].data_ptr;
657 sample_len = mixer[i].data_len;
658 sample_pos = mixer[i].playingpos;
659 sample_size = MIN(max_sample_size, sample_len - sample_pos);
660 mixer[i].playingpos += sample_size;
662 /* copy original sample to first mixing buffer */
663 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
664 premix_first_buffer);
666 /* are we about to restart a looping sound? */
667 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
669 while (sample_size < max_sample_size)
671 int restarted_sample_size =
672 MIN(max_sample_size - sample_size, sample_len);
674 if (mixer[i].format == AUDIO_FORMAT_U8)
675 for (j=0; j<restarted_sample_size; j++)
676 premix_first_buffer[sample_size + j] =
677 ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
679 for (j=0; j<restarted_sample_size; j++)
680 premix_first_buffer[sample_size + j] =
681 ((short *)sample_ptr)[j];
683 mixer[i].playingpos = restarted_sample_size;
684 sample_size += restarted_sample_size;
688 /* decrease volume if sound is fading out */
689 if (IS_FADING(mixer[i]) &&
690 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
691 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
693 /* adjust volume of actual sound sample */
694 if (mixer[i].volume != PSND_MAX_VOLUME)
695 for(j=0; j<sample_size; j++)
696 premix_first_buffer[j] =
697 (mixer[i].volume * (long)premix_first_buffer[j])
698 >> PSND_MAX_VOLUME_BITS;
700 /* fill the last mixing buffer with stereo or mono sound */
703 int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
704 int left_volume = stereo_volume[middle_pos + mixer[i].stereo];
705 int right_volume= stereo_volume[middle_pos - mixer[i].stereo];
707 for(j=0; j<sample_size; j++)
709 premix_left_buffer[j] =
710 (left_volume * premix_first_buffer[j])
711 >> PSND_MAX_LEFT2RIGHT_BITS;
712 premix_right_buffer[j] =
713 (right_volume * premix_first_buffer[j])
714 >> PSND_MAX_LEFT2RIGHT_BITS;
716 premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
717 premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
722 for(j=0; j<sample_size; j++)
723 premix_last_buffer[j] += premix_first_buffer[j];
726 /* delete completed sound entries from the mixer */
727 if (mixer[i].playingpos >= mixer[i].data_len)
729 if (IS_LOOP(mixer[i]))
730 mixer[i].playingpos = 0;
732 Mixer_RemoveSound(i);
734 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
735 Mixer_RemoveSound(i);
738 /* prepare final playing buffer according to system audio format */
739 for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
741 /* cut off at 17 bit value */
742 if (premix_last_buffer[i] < -65535)
743 premix_last_buffer[i] = -65535;
744 else if (premix_last_buffer[i] > 65535)
745 premix_last_buffer[i] = 65535;
747 /* shift to 16 bit value */
748 premix_last_buffer[i] >>= 1;
750 if (afmt.format & AUDIO_FORMAT_U8)
752 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
754 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
756 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
757 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
759 else /* big endian */
761 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
762 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
766 /* finally play the sound fragment */
767 write(audio.device_fd, playing_buffer, fragment_size);
769 if (!mixer_active_channels)
770 CloseAudioDevice(&audio.device_fd);
773 #else /* !AUDIO_STREAMING_DSP */
775 static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl)
777 static short premix_first_buffer[SND_BLOCKSIZE];
778 static byte playing_buffer[SND_BLOCKSIZE];
779 int max_sample_size = SND_BLOCKSIZE;
788 /* pointer, lenght and actual playing position of sound sample */
789 sample_ptr = mixer[i].data_ptr;
790 sample_len = mixer[i].data_len;
791 sample_pos = mixer[i].playingpos;
792 sample_size = MIN(max_sample_size, sample_len - sample_pos);
793 mixer[i].playingpos += sample_size;
795 /* copy original sample to first mixing buffer */
796 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
797 premix_first_buffer);
799 /* adjust volume of actual sound sample */
800 if (mixer[i].volume != PSND_MAX_VOLUME)
801 for(j=0; j<sample_size; j++)
802 premix_first_buffer[j] =
803 (mixer[i].volume * (long)premix_first_buffer[j])
804 >> PSND_MAX_VOLUME_BITS;
806 /* might be needed for u-law /dev/audio */
808 for(j=0; j<sample_size; j++)
810 linear_to_ulaw(premix_first_buffer[j]);
813 /* delete completed sound entries from the mixer */
814 if (mixer[i].playingpos >= mixer[i].data_len)
815 Mixer_RemoveSound(i);
817 for(i=0; i<sample_size; i++)
818 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
820 /* finally play the sound fragment */
821 write(audio.device_fd, playing_buffer, sample_size);
825 #endif /* !AUDIO_STREAMING_DSP */
829 struct SoundControl snd_ctrl;
832 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
834 Mixer_InitChannels();
836 #if defined(PLATFORM_HPUX)
837 InitAudioDevice(&afmt);
840 FD_ZERO(&mixer_fdset);
841 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
843 while(1) /* wait for sound playing commands from client */
845 struct timeval delay = { 0, 0 };
847 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
848 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
849 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
851 if (read(audio.mixer_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
853 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
855 HandleSoundRequest(snd_ctrl);
857 #if defined(AUDIO_STREAMING_DSP)
859 while (mixer_active_channels &&
860 select(audio.mixer_pipe[0] + 1,
861 &mixer_fdset, NULL, NULL, &delay) < 1)
863 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
868 #else /* !AUDIO_STREAMING_DSP */
870 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
871 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
874 InitAudioDevice(&afmt);
879 while (mixer_active_channels &&
880 select(audio.mixer_pipe[0] + 1,
881 &mixer_fdset, NULL, NULL, &delay) < 1)
883 int wait_percent = 90; /* wait 90% of the real playing time */
886 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
888 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
892 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
895 CloseAudioDevice(&audio.device_fd);
897 Mixer_InitChannels(); /* remove all sounds from mixer */
899 #endif /* !AUDIO_STREAMING_DSP */
902 #endif /* PLATFORM_UNIX */
904 #if defined(PLATFORM_MSDOS)
905 static void sound_handler(struct SoundControl snd_ctrl)
907 for (i=0; i<audio.num_channels; i++)
909 if (!mixer[i].active || mixer[i].loop)
912 mixer[i].playingpos = voice_get_position(mixer[i].voice);
913 mixer[i].volume = voice_get_volume(mixer[i].voice);
914 if (mixer[i].playingpos == -1 || !mixer[i].volume)
916 deallocate_voice(mixer[i].voice);
917 Mixer_RemoveSound(i);
921 HandleSoundRequest(snd_ctrl);
923 #endif /* PLATFORM_MSDOS */
926 /* ------------------------------------------------------------------------- */
927 /* platform dependant audio initialization code */
928 /* ------------------------------------------------------------------------- */
930 #if defined(AUDIO_LINUX_IOCTL)
931 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
933 /* "ioctl()" expects pointer to 'int' value for stereo flag
934 (boolean is defined as 'char', which will not work here) */
935 unsigned int fragment_spec = 0;
936 int fragment_size_query;
945 /* supported audio format in preferred order */
946 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
947 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
948 { AFMT_U8, AUDIO_FORMAT_U8 },
953 /* determine logarithm (log2) of the fragment size */
954 while ((1 << fragment_spec) < afmt->fragment_size)
957 /* use two fragments (play one fragment, prepare the other);
958 one fragment would result in interrupted audio output, more
959 than two fragments would raise audio output latency to much */
960 fragment_spec |= 0x00020000;
962 /* Example for fragment specification:
963 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
964 - (with stereo the effective buffer size will shrink to 256)
965 => fragment_size = 0x00020009 */
967 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
968 Error(ERR_EXIT_SOUND_SERVER,
969 "cannot set fragment size of /dev/dsp -- no sounds");
973 while (formats[i].format_result != -1)
975 unsigned int audio_format = formats[i].format_ioctl;
976 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
978 afmt->format = formats[i].format_result;
983 if (afmt->format == 0) /* no supported audio format found */
984 Error(ERR_EXIT_SOUND_SERVER,
985 "cannot set audio format of /dev/dsp -- no sounds");
987 /* try if we can use stereo sound */
989 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
990 afmt->stereo = FALSE;
992 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
993 Error(ERR_EXIT_SOUND_SERVER,
994 "cannot set sample rate of /dev/dsp -- no sounds");
996 /* get the real fragmentation size; this should return 512 */
997 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
998 Error(ERR_EXIT_SOUND_SERVER,
999 "cannot get fragment size of /dev/dsp -- no sounds");
1000 if (fragment_size_query != afmt->fragment_size)
1001 Error(ERR_EXIT_SOUND_SERVER,
1002 "cannot set fragment size of /dev/dsp -- no sounds");
1004 #endif /* AUDIO_LINUX_IOCTL */
1006 #if defined(PLATFORM_NETBSD)
1007 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
1009 audio_info_t a_info;
1010 boolean stereo = TRUE;
1012 AUDIO_INITINFO(&a_info);
1013 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
1014 a_info.play.precision = 8;
1015 a_info.play.channels = 2;
1016 a_info.play.sample_rate = sample_rate;
1017 a_info.blocksize = fragment_size;
1019 afmt->format = AUDIO_FORMAT_U8;
1020 afmt->stereo = TRUE;
1022 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1024 /* try to disable stereo */
1025 a_info.play.channels = 1;
1027 afmt->stereo = FALSE;
1029 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
1030 Error(ERR_EXIT_SOUND_SERVER,
1031 "cannot set sample rate of /dev/audio -- no sounds");
1034 #endif /* PLATFORM_NETBSD */
1036 #if defined(PLATFORM_HPUX)
1037 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
1039 struct audio_describe ainfo;
1042 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
1043 if (audio_ctl == -1)
1044 Error(ERR_EXIT_SOUND_SERVER, "cannot open /dev/audioCtl -- no sounds");
1046 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
1047 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
1049 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
1050 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
1052 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
1053 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
1055 afmt->format = AUDIO_FORMAT_U8;
1056 afmt->stereo = FALSE;
1057 afmt->sample_rate = 8000;
1061 #endif /* PLATFORM_HPUX */
1063 #if defined(PLATFORM_UNIX)
1064 static void InitAudioDevice(struct AudioFormatInfo *afmt)
1066 afmt->stereo = TRUE;
1067 afmt->format = AUDIO_FORMAT_UNKNOWN;
1068 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
1069 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1071 #if defined(AUDIO_LINUX_IOCTL)
1072 InitAudioDevice_Linux(afmt);
1073 #elif defined(PLATFORM_NETBSD)
1074 InitAudioDevice_NetBSD(afmt);
1075 #elif defined(PLATFORM_HPUX)
1076 InitAudioDevice_HPUX(afmt);
1078 /* generic /dev/audio stuff might be placed here */
1081 #endif /* PLATFORM_UNIX */
1083 #if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP)
1085 /* these two are stolen from "sox"... :) */
1088 ** This routine converts from linear to ulaw.
1090 ** Craig Reese: IDA/Supercomputing Research Center
1091 ** Joe Campbell: Department of Defense
1092 ** 29 September 1989
1095 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1096 ** 2) "A New Digital Technique for Implementation of Any
1097 ** Continuous PCM Companding Law," Villeret, Michel,
1098 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1099 ** 1973, pg. 11.12-11.17
1100 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1101 ** for Analog-to_Digital Conversion Techniques,"
1104 ** Input: Signed 16 bit linear sample
1105 ** Output: 8 bit ulaw sample
1108 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1109 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1112 static unsigned char linear_to_ulaw(int sample)
1114 static int exp_lut[256] =
1116 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1117 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1118 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1119 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1120 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1121 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1122 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1123 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1124 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1125 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1126 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1127 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1128 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1129 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1130 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1131 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1134 int sign, exponent, mantissa;
1135 unsigned char ulawbyte;
1137 /* Get the sample into sign-magnitude. */
1138 sign = (sample >> 8) & 0x80; /* set aside the sign */
1140 sample = -sample; /* get magnitude */
1142 sample = CLIP; /* clip the magnitude */
1144 /* Convert from 16 bit linear to ulaw. */
1145 sample = sample + BIAS;
1146 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1147 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1148 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1151 ulawbyte = 0x02; /* optional CCITT trap */
1158 ** This routine converts from ulaw to 16 bit linear.
1160 ** Craig Reese: IDA/Supercomputing Research Center
1161 ** 29 September 1989
1164 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1165 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1166 ** for Analog-to_Digital Conversion Techniques,"
1169 ** Input: 8 bit ulaw sample
1170 ** Output: signed 16 bit linear sample
1173 static int ulaw_to_linear(unsigned char ulawbyte)
1175 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1176 int sign, exponent, mantissa, sample;
1178 ulawbyte = ~ ulawbyte;
1179 sign = ( ulawbyte & 0x80 );
1180 exponent = ( ulawbyte >> 4 ) & 0x07;
1181 mantissa = ulawbyte & 0x0F;
1182 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1188 #endif /* PLATFORM_UNIX && !AUDIO_STREAMING_DSP */
1191 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1192 /* ========================================================================= */
1193 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1195 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1196 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1198 static SoundInfo *Load_WAV(char *filename)
1200 SoundInfo *snd_info;
1201 #if !defined(TARGET_SDL) && !defined(PLATFORM_MSDOS)
1202 byte sound_header_buffer[WAV_HEADER_SIZE];
1203 char chunk_name[CHUNK_ID_LEN + 1];
1209 if (!audio.sound_available)
1213 printf("loading WAV file '%s'\n", filename);
1216 snd_info = checked_calloc(sizeof(SoundInfo));
1218 #if defined(TARGET_SDL)
1220 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1222 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1227 #elif defined(TARGET_ALLEGRO)
1229 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1231 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1236 #else /* PLATFORM_UNIX */
1238 if ((file = fopen(filename, MODE_READ)) == NULL)
1240 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1245 /* read chunk id "RIFF" */
1246 getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN);
1247 if (strcmp(chunk_name, "RIFF") != 0)
1249 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1255 /* read "RIFF" type id "WAVE" */
1256 getFileChunk(file, chunk_name, NULL, BYTE_ORDER_LITTLE_ENDIAN);
1257 if (strcmp(chunk_name, "WAVE") != 0)
1259 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1265 while (getFileChunk(file, chunk_name, &chunk_size, BYTE_ORDER_LITTLE_ENDIAN))
1267 if (strcmp(chunk_name, "fmt ") == 0)
1269 /* read header information */
1270 for (i=0; i < MIN(chunk_size, WAV_HEADER_SIZE); i++)
1271 sound_header_buffer[i] = fgetc(file);
1273 if (chunk_size > WAV_HEADER_SIZE)
1274 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1276 else if (strcmp(chunk_name, "data") == 0)
1278 snd_info->data_len = chunk_size;
1279 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1281 /* read sound data */
1282 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1285 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1287 free(snd_info->data_ptr);
1292 /* check for odd number of sample bytes (data chunk is word aligned) */
1293 if ((chunk_size % 2) == 1)
1294 ReadUnusedBytesFromFile(file, 1);
1296 else /* unknown chunk -- ignore */
1297 ReadUnusedBytesFromFile(file, chunk_size);
1302 if (snd_info->data_ptr == NULL)
1304 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1309 snd_info->format = AUDIO_FORMAT_U8;
1311 #endif /* PLATFORM_UNIX */
1313 snd_info->type = SND_TYPE_WAV;
1314 snd_info->source_filename = getStringCopy(filename);
1319 static void deleteSoundEntry(SoundInfo **snd_info)
1323 char *filename = (*snd_info)->source_filename;
1326 printf("[decrementing reference counter of sound '%s']\n", filename);
1329 if (--(*snd_info)->num_references <= 0)
1332 printf("[deleting sound '%s']\n", filename);
1336 FreeSound(*snd_info);
1338 deleteNodeFromList(&SoundFileList, filename, FreeSound);
1345 static void replaceSoundEntry(SoundInfo **snd_info, char *filename)
1349 /* check if the old and the new sound file are the same */
1350 if (*snd_info && strcmp((*snd_info)->source_filename, filename) == 0)
1352 /* The old and new sound are the same (have the same filename and path).
1353 This usually means that this sound does not exist in this sound set
1354 and a fallback to the existing sound is done. */
1357 printf("[sound '%s' already exists (same list entry)]\n", filename);
1363 /* delete existing sound file entry */
1364 deleteSoundEntry(snd_info);
1366 /* check if the new sound file already exists in the list of sounds */
1367 if ((node = getNodeFromKey(SoundFileList, filename)) != NULL)
1370 printf("[sound '%s' already exists (other list entry)]\n", filename);
1373 *snd_info = (SoundInfo *)node->content;
1374 (*snd_info)->num_references++;
1376 else if ((*snd_info = Load_WAV(filename)) != NULL) /* load new sound */
1378 (*snd_info)->num_references = 1;
1379 addNodeToList(&SoundFileList, (*snd_info)->source_filename, *snd_info);
1383 static void LoadCustomSound(SoundInfo **snd_info, char *basename)
1385 char *filename = getCustomSoundFilename(basename);
1387 if (strcmp(basename, SND_FILE_UNDEFINED) == 0)
1389 deleteSoundEntry(snd_info);
1393 if (filename == NULL)
1395 Error(ERR_WARN, "cannot find sound file '%s'", basename);
1399 replaceSoundEntry(snd_info, filename);
1402 void InitSoundList(struct SoundEffectInfo *sounds_list, int num_list_entries)
1405 Sound = checked_calloc(num_list_entries * sizeof(SoundInfo *));
1407 sound_effect = sounds_list;
1408 num_sounds = num_list_entries;
1411 void LoadSoundToList(char *basename, int list_pos)
1413 if (Sound == NULL || list_pos >= num_sounds)
1417 printf("loading sound '%s' ... [%d]\n",
1418 basename, getNumNodes(SoundFileList));
1421 LoadCustomSound(&Sound[list_pos], basename);
1424 printf("loading sound '%s' done [%d]\n",
1425 basename, getNumNodes(SoundFileList));
1429 static MusicInfo *Load_MOD(char *filename)
1431 #if defined(TARGET_SDL)
1432 MusicInfo *mod_info;
1434 if (!audio.sound_available)
1437 mod_info = checked_calloc(sizeof(MusicInfo));
1439 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1441 Error(ERR_WARN, "cannot read music file '%s'", filename);
1446 mod_info->type = MUS_TYPE_MOD;
1447 mod_info->source_filename = getStringCopy(filename);
1455 void LoadCustomMusic(void)
1457 char *music_directory = getCustomMusicDirectory();
1459 struct dirent *dir_entry;
1461 if (!audio.sound_available)
1464 if ((dir = opendir(music_directory)) == NULL)
1466 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1467 audio.music_available = FALSE;
1471 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1473 char *basename = dir_entry->d_name;
1474 char *filename = getPath2(music_directory, basename);
1475 MusicInfo *mus_info = NULL;
1477 if (FileIsSound(basename))
1478 mus_info = Load_WAV(filename);
1479 else if (FileIsMusic(basename))
1480 mus_info = Load_MOD(filename);
1487 Music = checked_realloc(Music, num_music * sizeof(MusicInfo *));
1488 Music[num_music -1] = mus_info;
1495 Error(ERR_WARN, "cannot find any valid music files in directory '%s'",
1499 void PlayMusic(int nr)
1501 if (!audio.music_available)
1504 #if defined(TARGET_SDL)
1506 nr = nr % num_music;
1508 if (Music[nr]->type == MUS_TYPE_MOD)
1510 Mix_PlayMusic(Music[nr]->data_ptr, -1);
1511 Mix_VolumeMusic(SOUND_MAX_VOLUME); /* must be _after_ Mix_PlayMusic()! */
1513 else /* play WAV music loop */
1515 Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME);
1516 Mix_PlayChannel(audio.music_channel, Music[nr]->data_ptr, -1);
1526 void PlaySound(int nr)
1528 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_SOUND);
1531 void PlaySoundStereo(int nr, int stereo)
1533 PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, SND_CTRL_PLAY_SOUND);
1536 void PlaySoundLoop(int nr)
1538 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_LOOP);
1541 void PlaySoundMusic(int nr)
1543 PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, SND_CTRL_PLAY_MUSIC);
1546 void PlaySoundExt(int nr, int volume, int stereo, int state)
1548 struct SoundControl snd_ctrl;
1550 if (!audio.sound_available ||
1551 !audio.sound_enabled ||
1552 audio.sound_deactivated)
1555 if (volume < PSND_MIN_VOLUME)
1556 volume = PSND_MIN_VOLUME;
1557 else if (volume > PSND_MAX_VOLUME)
1558 volume = PSND_MAX_VOLUME;
1560 if (stereo < PSND_MAX_LEFT)
1561 stereo = PSND_MAX_LEFT;
1562 else if (stereo > PSND_MAX_RIGHT)
1563 stereo = PSND_MAX_RIGHT;
1565 snd_ctrl.active = TRUE;
1567 snd_ctrl.volume = volume;
1568 snd_ctrl.stereo = stereo;
1569 snd_ctrl.state = state;
1571 #if defined(TARGET_SDL)
1574 Mix_Volume(-1, SOUND_MAX_VOLUME);
1575 Mix_PlayChannel(-1, Sound[nr]->data_ptr, (state & SND_CTRL_LOOP ? -1 : 0));
1577 #elif defined(PLATFORM_UNIX)
1578 if (audio.mixer_pid == 0) /* we are child process */
1581 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1583 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1584 audio.sound_available = audio.sound_enabled = FALSE;
1587 #elif defined(PLATFORM_MSDOS)
1588 sound_handler(snd_ctrl);
1592 void FadeMusic(void)
1594 if (!audio.sound_available)
1597 #if defined(TARGET_SDL)
1598 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1599 Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL);
1601 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
1605 void FadeSound(int nr)
1607 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
1613 StopSoundExt(-1, SND_CTRL_FADE_ALL);
1616 void StopMusic(void)
1618 #if defined(TARGET_SDL)
1619 if (!audio.sound_available)
1623 Mix_HaltChannel(audio.music_channel);
1625 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
1629 void StopSound(int nr)
1631 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
1637 StopSoundExt(-1, SND_CTRL_STOP_ALL);
1640 void StopSoundExt(int nr, int state)
1642 struct SoundControl snd_ctrl;
1644 if (!audio.sound_available)
1647 snd_ctrl.active = FALSE;
1649 snd_ctrl.state = state;
1651 #if defined(TARGET_SDL)
1653 if (state & SND_CTRL_FADE)
1658 for (i=audio.first_sound_channel; i<audio.num_channels; i++)
1661 for (i=0; i<audio.channels; i++)
1662 if (i != audio.music_channel || snd_ctrl.music)
1663 Mix_FadeOutChannel(i, SOUND_FADING_INTERVAL);
1664 if (state & SND_CTRL_MUSIC)
1665 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
1671 for (i=0; i<audio.channels; i++)
1672 if (i != audio.music_channel || snd_ctrl.music)
1674 if (state & SND_CTRL_MUSIC)
1678 #elif !defined(PLATFORM_MSDOS)
1680 if (audio.mixer_pid == 0) /* we are child process */
1683 if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0)
1685 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
1686 audio.sound_available = audio.sound_enabled = FALSE;
1689 #else /* PLATFORM_MSDOS */
1690 sound_handler(snd_ctrl);
1694 ListNode *newListNode()
1696 return checked_calloc(sizeof(ListNode));
1699 void addNodeToList(ListNode **node_first, char *key, void *content)
1701 ListNode *node_new = newListNode();
1704 printf("LIST: adding node with key '%s'\n", key);
1707 node_new->key = getStringCopy(key);
1708 node_new->content = content;
1709 node_new->next = *node_first;
1710 *node_first = node_new;
1713 void deleteNodeFromList(ListNode **node_first, char *key,
1714 void (*destructor_function)(void *))
1716 if (node_first == NULL || *node_first == NULL)
1720 printf("[CHECKING LIST KEY '%s' == '%s']\n",
1721 (*node_first)->key, key);
1724 if (strcmp((*node_first)->key, key) == 0)
1727 printf("[DELETING LIST ENTRY]\n");
1730 free((*node_first)->key);
1731 if (destructor_function)
1732 destructor_function((*node_first)->content);
1733 *node_first = (*node_first)->next;
1736 deleteNodeFromList(&(*node_first)->next, key, destructor_function);
1739 ListNode *getNodeFromKey(ListNode *node_first, char *key)
1741 if (node_first == NULL)
1744 if (strcmp(node_first->key, key) == 0)
1747 return getNodeFromKey(node_first->next, key);
1750 int getNumNodes(ListNode *node_first)
1752 return (node_first ? 1 + getNumNodes(node_first->next) : 0);
1755 void dumpList(ListNode *node_first)
1757 ListNode *node = node_first;
1761 printf("['%s' (%d)]\n", node->key,
1762 ((SoundInfo *)node->content)->num_references);
1766 printf("[%d nodes]\n", getNumNodes(node_first));
1769 static void LoadSoundsInfo()
1771 char *filename = getCustomSoundConfigFilename();
1772 struct SetupFileList *setup_file_list;
1775 /* always start with reliable default values */
1776 for (i=0; i<num_sounds; i++)
1777 sound_effect[i].filename = NULL;
1779 if (filename == NULL)
1782 if ((setup_file_list = loadSetupFileList(filename)))
1784 for (i=0; i<num_sounds; i++)
1785 sound_effect[i].filename =
1786 getStringCopy(getTokenValue(setup_file_list, sound_effect[i].text));
1788 freeSetupFileList(setup_file_list);
1791 for (i=0; i<num_sounds; i++)
1793 printf("'%s' ", sound_effect[i].text);
1794 if (sound_effect[i].filename)
1795 printf("-> '%s'\n", sound_effect[i].filename);
1797 printf("-> UNDEFINED [-> '%s']\n", sound_effect[i].default_filename);
1803 static void ReloadCustomSounds()
1808 printf("DEBUG: reloading sounds '%s' ...\n", artwork.sounds_set_current);
1814 printf("DEBUG: reloading %d sounds ...\n", num_sounds);
1817 for(i=0; i<num_sounds; i++)
1819 if (sound_effect[i].filename)
1820 LoadSoundToList(sound_effect[i].filename, i);
1822 LoadSoundToList(sound_effect[i].default_filename, i);
1826 printf("list size == %d\n", getNumNodes(SoundFileList));
1830 dumpList(SoundFileList);
1834 static void ReloadCustomMusic()
1837 printf("DEBUG: reloading music '%s' ...\n", artwork.music_set_current);
1845 void InitReloadSounds(char *set_name)
1847 if (!audio.sound_available)
1850 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1851 ReloadCustomSounds();
1852 #elif defined(PLATFORM_UNIX)
1853 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_SOUNDS);
1857 void InitReloadMusic(char *set_name)
1859 if (!audio.music_available)
1862 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1863 ReloadCustomMusic();
1864 #elif defined(PLATFORM_UNIX)
1865 WriteReloadInfoToPipe(set_name, SND_CTRL_RELOAD_MUSIC);
1869 void FreeSound(void *ptr)
1871 SoundInfo *sound = (SoundInfo *)ptr;
1876 if (sound->data_ptr)
1878 #if defined(TARGET_SDL)
1879 Mix_FreeChunk(sound->data_ptr);
1880 #elif defined(TARGET_ALLEGRO)
1881 destroy_sample(sound->data_ptr);
1882 #else /* PLATFORM_UNIX */
1883 free(sound->data_ptr);
1887 if (sound->source_filename)
1888 free(sound->source_filename);
1893 void FreeMusic(MusicInfo *music)
1898 if (music->data_ptr)
1900 #if defined(TARGET_SDL)
1901 if (music->type == MUS_TYPE_MOD)
1902 Mix_FreeMusic(music->data_ptr);
1904 Mix_FreeChunk(music->data_ptr);
1905 #elif defined(TARGET_ALLEGRO)
1906 destroy_sample(music->data_ptr);
1907 #else /* PLATFORM_UNIX */
1908 free(music->data_ptr);
1915 void FreeAllSounds()
1922 printf("%s: FREEING SOUNDS ...\n",
1923 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
1925 for(i=0; i<num_sounds; i++)
1926 deleteSoundEntry(&Sound[i]);
1928 FreeSound(Sound[i]);
1931 printf("%s: FREEING SOUNDS -- DONE\n",
1932 audio.mixer_pid == 0 ? "CHILD" : "PARENT");
1947 for(i=0; i<num_music; i++)
1948 FreeMusic(Music[i]);
1956 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1957 /* ========================================================================= */