1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
12 #include <sys/types.h>
30 /* expiration time (in milliseconds) for sound loops */
31 #define SOUND_LOOP_EXPIRATION_TIME 200
33 /* one second fading interval == 1000 ticks (milliseconds) */
34 #define SOUND_FADING_INTERVAL 1000
36 #define SND_TYPE_NONE 0
37 #define SND_TYPE_WAV 1
39 #define MUS_TYPE_NONE 0
40 #define MUS_TYPE_WAV 1
41 #define MUS_TYPE_MOD 2
43 #define DEVICENAME_DSP "/dev/dsp"
44 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
45 #define DEVICENAME_AUDIO "/dev/audio"
46 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
48 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
49 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
51 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
52 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
54 #define SOUND_VOLUME_FROM_PERCENT(v,p) ((p) < 0 ? SOUND_MIN_VOLUME : \
58 #define SOUND_VOLUME_SIMPLE(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_simple)
59 #define SOUND_VOLUME_LOOPS(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_loops)
60 #define SOUND_VOLUME_MUSIC(v) SOUND_VOLUME_FROM_PERCENT(v, setup.volume_music)
62 #define SETUP_SOUND_VOLUME(v,s) ((s) == SND_CTRL_PLAY_MUSIC ? \
63 SOUND_VOLUME_MUSIC(v) : \
64 (s) == SND_CTRL_PLAY_LOOP ? \
65 SOUND_VOLUME_LOOPS(v) : \
66 SOUND_VOLUME_SIMPLE(v))
68 struct AudioFormatInfo
70 boolean stereo; /* availability of stereo sound */
71 int format; /* size and endianess of sample data */
72 int sample_rate; /* sample frequency */
73 int fragment_size; /* audio device fragment size in bytes */
78 char *source_filename;
83 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
84 int data_len; /* number of samples, NOT number of bytes */
85 int num_channels; /* mono: 1 channel, stereo: 2 channels */
87 typedef struct SampleInfo SoundInfo;
88 typedef struct SampleInfo MusicInfo;
100 unsigned int playing_starttime;
101 unsigned int playing_pos;
105 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
106 int data_len; /* number of samples, NOT number of bytes */
107 int num_channels; /* mono: 1 channel, stereo: 2 channels */
109 typedef struct SoundControl SoundControl;
111 static struct ArtworkListInfo *sound_info = NULL;
112 static struct ArtworkListInfo *music_info = NULL;
114 static MusicInfo **Music_NoConf = NULL;
116 static int num_music_noconf = 0;
117 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
120 /* ========================================================================= */
121 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
123 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
124 static int mixer_active_channels = 0;
126 static void ReloadCustomSounds();
127 static void ReloadCustomMusic();
128 static void FreeSound(void *);
129 static void FreeMusic(void *);
130 static void FreeAllMusic_NoConf();
132 static SoundInfo *getSoundInfoEntryFromSoundID(int);
133 static MusicInfo *getMusicInfoEntryFromMusicID(int);
136 /* ------------------------------------------------------------------------- */
137 /* mixer functions */
138 /* ------------------------------------------------------------------------- */
140 void Mixer_InitChannels()
144 for (i = 0; i < audio.num_channels; i++)
145 mixer[i].active = FALSE;
146 mixer_active_channels = 0;
149 static void Mixer_ResetChannelExpiration(int channel)
151 mixer[channel].playing_starttime = Counter();
153 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
154 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
157 static boolean Mixer_ChannelExpired(int channel)
159 if (!mixer[channel].active)
162 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
163 DelayReached(&mixer[channel].playing_starttime,
164 SOUND_LOOP_EXPIRATION_TIME))
167 if (!Mix_Playing(channel))
173 static boolean Mixer_AllocateChannel(int channel)
178 static void Mixer_SetChannelProperties(int channel)
180 Mix_Volume(channel, mixer[channel].volume);
181 Mix_SetPanning(channel,
182 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
183 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
186 static void Mixer_StartChannel(int channel)
188 Mix_PlayChannel(channel, mixer[channel].data_ptr,
189 IS_LOOP(mixer[channel]) ? -1 : 0);
192 static void Mixer_PlayChannel(int channel)
194 /* start with inactive channel in case something goes wrong */
195 mixer[channel].active = FALSE;
197 if (mixer[channel].type != MUS_TYPE_WAV)
200 if (!Mixer_AllocateChannel(channel))
203 Mixer_SetChannelProperties(channel);
204 Mixer_StartChannel(channel);
206 Mixer_ResetChannelExpiration(channel);
208 mixer[channel].playing_pos = 0;
209 mixer[channel].active = TRUE;
210 mixer_active_channels++;
213 static void Mixer_PlayMusicChannel()
215 Mixer_PlayChannel(audio.music_channel);
217 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
219 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
220 this looks like a bug in the SDL_mixer library */
221 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
222 Mix_VolumeMusic(mixer[audio.music_channel].volume);
226 static void Mixer_StopChannel(int channel)
228 if (!mixer[channel].active)
231 Mix_HaltChannel(channel);
233 mixer[channel].active = FALSE;
234 mixer_active_channels--;
237 static void Mixer_StopMusicChannel()
239 Mixer_StopChannel(audio.music_channel);
244 static void Mixer_FadeChannel(int channel)
246 if (!mixer[channel].active)
249 mixer[channel].state |= SND_CTRL_FADE;
251 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
254 static void Mixer_FadeMusicChannel()
256 Mixer_FadeChannel(audio.music_channel);
258 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
261 static void Mixer_UnFadeChannel(int channel)
263 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
266 mixer[channel].state &= ~SND_CTRL_FADE;
267 mixer[channel].volume = SOUND_MAX_VOLUME;
269 Mix_ExpireChannel(channel, -1);
270 Mix_Volume(channel, mixer[channel].volume);
273 static void Mixer_InsertSound(SoundControl snd_ctrl)
277 int num_sounds = getSoundListSize();
278 int num_music = getMusicListSize();
280 if (IS_MUSIC(snd_ctrl))
282 if (snd_ctrl.nr >= num_music) /* invalid music */
285 if (snd_ctrl.nr < 0) /* undefined music */
287 if (num_music_noconf == 0) /* no fallback music available */
290 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
291 snd_info = Music_NoConf[snd_ctrl.nr];
294 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
298 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
301 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
304 if (snd_info == NULL)
307 /* copy sound sample and format information */
308 snd_ctrl.type = snd_info->type;
309 snd_ctrl.format = snd_info->format;
310 snd_ctrl.data_ptr = snd_info->data_ptr;
311 snd_ctrl.data_len = snd_info->data_len;
312 snd_ctrl.num_channels = snd_info->num_channels;
314 /* play music samples on a dedicated music channel */
315 if (IS_MUSIC(snd_ctrl))
317 Mixer_StopMusicChannel();
319 mixer[audio.music_channel] = snd_ctrl;
320 Mixer_PlayMusicChannel();
325 /* check if (and how often) this sound sample is already playing */
326 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
327 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
330 /* reset expiration delay for already playing loop sounds */
331 if (k > 0 && IS_LOOP(snd_ctrl))
333 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
335 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
337 if (IS_FADING(mixer[i]))
338 Mixer_UnFadeChannel(i);
340 /* restore settings like volume and stereo position */
341 mixer[i].volume = snd_ctrl.volume;
342 mixer[i].stereo_position = snd_ctrl.stereo_position;
344 Mixer_SetChannelProperties(i);
345 Mixer_ResetChannelExpiration(i);
352 /* don't play sound more than n times simultaneously (with n == 2 for now) */
355 unsigned int playing_current = Counter();
356 int longest = 0, longest_nr = audio.first_sound_channel;
358 /* look for oldest equal sound */
359 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
361 int playing_time = playing_current - mixer[i].playing_starttime;
364 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
367 actual = 1000 * playing_time / mixer[i].data_len;
369 if (actual >= longest)
376 Mixer_StopChannel(longest_nr);
379 /* If all (non-music) channels are active, stop the channel that has
380 played its sound sample most completely (in percent of the sample
381 length). As we cannot currently get the actual playing position
382 of the channel's sound sample when compiling with the SDL mixer
383 library, we use the current playing time (in milliseconds) instead. */
386 /* channel allocation sanity check -- should not be needed */
387 if (mixer_active_channels ==
388 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
390 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
392 if (!mixer[i].active)
394 Error(ERR_INFO, "Mixer_InsertSound: Channel %d inactive", i);
395 Error(ERR_INFO, "Mixer_InsertSound: This should never happen!");
397 mixer_active_channels--;
403 if (mixer_active_channels ==
404 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
406 unsigned int playing_current = Counter();
407 int longest = 0, longest_nr = audio.first_sound_channel;
409 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
411 int playing_time = playing_current - mixer[i].playing_starttime;
412 int actual = 1000 * playing_time / mixer[i].data_len;
414 if (!IS_LOOP(mixer[i]) && actual > longest)
421 Mixer_StopChannel(longest_nr);
424 /* add the new sound to the mixer */
425 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
427 if (!mixer[i].active)
430 Mixer_PlayChannel(i);
437 static void HandleSoundRequest(SoundControl snd_ctrl)
441 /* deactivate channels that have expired since the last request */
442 for (i = 0; i < audio.num_channels; i++)
443 if (mixer[i].active && Mixer_ChannelExpired(i))
444 Mixer_StopChannel(i);
446 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
448 Mixer_StopMusicChannel();
449 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
450 Mixer_StopChannel(i);
452 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
453 ReloadCustomSounds();
457 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
459 if (IS_MUSIC(snd_ctrl))
461 Mixer_FadeMusicChannel();
465 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
466 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
467 Mixer_FadeChannel(i);
469 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
471 if (IS_MUSIC(snd_ctrl))
473 Mixer_StopMusicChannel();
477 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
478 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
479 Mixer_StopChannel(i);
481 else if (snd_ctrl.active) /* add new sound to mixer */
483 Mixer_InsertSound(snd_ctrl);
487 void StartMixer(void)
491 if (!audio.sound_available)
494 /* initialize stereo position conversion information */
495 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
497 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
501 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
502 /* ========================================================================= */
503 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
505 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
506 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
508 static void *Load_WAV(char *filename)
512 if (!audio.sound_available)
515 snd_info = checked_calloc(sizeof(SoundInfo));
517 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
519 Error(ERR_WARN, "cannot read sound file '%s': %s", filename, Mix_GetError());
524 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
526 snd_info->type = SND_TYPE_WAV;
527 snd_info->source_filename = getStringCopy(filename);
532 static void *Load_MOD(char *filename)
536 if (!audio.sound_available)
539 mod_info = checked_calloc(sizeof(MusicInfo));
541 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
543 Error(ERR_WARN, "cannot read music file '%s': %s", filename, Mix_GetError());
548 mod_info->type = MUS_TYPE_MOD;
549 mod_info->source_filename = getStringCopy(filename);
554 static void *Load_WAV_or_MOD(char *filename)
556 if (FileIsMusic(filename))
557 return Load_MOD(filename);
558 else if (FileIsSound(filename))
559 return Load_WAV(filename);
564 void LoadCustomMusic_NoConf(void)
566 static boolean draw_init_text = TRUE; /* only draw at startup */
567 static char *last_music_directory = NULL;
568 char *music_directory = getCustomMusicDirectory();
570 DirectoryEntry *dir_entry;
571 int num_music = getMusicListSize();
573 if (!audio.sound_available)
576 if (last_music_directory != NULL &&
577 strEqual(last_music_directory, music_directory))
578 return; /* old and new music directory are the same */
580 if (last_music_directory != NULL)
581 free(last_music_directory);
582 last_music_directory = getStringCopy(music_directory);
584 FreeAllMusic_NoConf();
586 if ((dir = openDirectory(music_directory)) == NULL)
588 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
590 audio.music_available = FALSE;
596 DrawInitText("Loading music", 120, FC_GREEN);
598 while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */
600 char *basename = dir_entry->basename;
601 MusicInfo *mus_info = NULL;
602 boolean music_already_used = FALSE;
605 /* skip all music files that are configured in music config file */
606 for (i = 0; i < num_music; i++)
608 struct FileInfo *music = getMusicListEntry(i);
610 if (strEqual(basename, music->filename))
612 music_already_used = TRUE;
617 if (music_already_used)
621 DrawInitText(basename, 150, FC_YELLOW);
623 if (FileIsMusic(dir_entry->filename))
624 mus_info = Load_WAV_or_MOD(dir_entry->filename);
629 Music_NoConf = checked_realloc(Music_NoConf,
630 num_music_noconf * sizeof(MusicInfo *));
631 Music_NoConf[num_music_noconf - 1] = mus_info;
637 draw_init_text = FALSE;
640 int getSoundListSize()
642 return (sound_info->num_file_list_entries +
643 sound_info->num_dynamic_file_list_entries);
646 int getMusicListSize()
648 return (music_info->num_file_list_entries +
649 music_info->num_dynamic_file_list_entries);
652 struct FileInfo *getSoundListEntry(int pos)
654 int num_list_entries = sound_info->num_file_list_entries;
655 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
657 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
658 &sound_info->dynamic_file_list[list_pos]);
661 struct FileInfo *getMusicListEntry(int pos)
663 int num_list_entries = music_info->num_file_list_entries;
664 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
666 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
667 &music_info->dynamic_file_list[list_pos]);
670 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
672 int num_list_entries = sound_info->num_file_list_entries;
673 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
674 SoundInfo **snd_info =
675 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
676 sound_info->dynamic_artwork_list);
678 return snd_info[list_pos];
681 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
683 int num_list_entries = music_info->num_file_list_entries;
684 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
685 MusicInfo **mus_info =
686 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
687 music_info->dynamic_artwork_list);
689 return mus_info[list_pos];
692 int getSoundListPropertyMappingSize()
694 return sound_info->num_property_mapping_entries;
697 int getMusicListPropertyMappingSize()
699 return music_info->num_property_mapping_entries;
702 struct PropertyMapping *getSoundListPropertyMapping()
704 return sound_info->property_mapping;
707 struct PropertyMapping *getMusicListPropertyMapping()
709 return music_info->property_mapping;
712 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
713 struct ConfigTypeInfo *config_suffix_list,
714 char **base_prefixes, char **ext1_suffixes,
715 char **ext2_suffixes, char **ext3_suffixes,
716 char **ignore_tokens)
720 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
721 sound_info->type = ARTWORK_TYPE_SOUNDS;
723 /* ---------- initialize file list and suffix lists ---------- */
725 sound_info->num_file_list_entries = num_file_list_entries;
726 sound_info->num_dynamic_file_list_entries = 0;
728 sound_info->file_list =
729 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
730 num_file_list_entries);
731 sound_info->dynamic_file_list = NULL;
733 sound_info->num_suffix_list_entries = 0;
734 for (i = 0; config_suffix_list[i].token != NULL; i++)
735 sound_info->num_suffix_list_entries++;
737 sound_info->suffix_list = config_suffix_list;
739 /* ---------- initialize base prefix and suffixes lists ---------- */
741 sound_info->num_base_prefixes = 0;
742 for (i = 0; base_prefixes[i] != NULL; i++)
743 sound_info->num_base_prefixes++;
745 sound_info->num_ext1_suffixes = 0;
746 for (i = 0; ext1_suffixes[i] != NULL; i++)
747 sound_info->num_ext1_suffixes++;
749 sound_info->num_ext2_suffixes = 0;
750 for (i = 0; ext2_suffixes[i] != NULL; i++)
751 sound_info->num_ext2_suffixes++;
753 sound_info->num_ext3_suffixes = 0;
754 for (i = 0; ext3_suffixes[i] != NULL; i++)
755 sound_info->num_ext3_suffixes++;
757 sound_info->num_ignore_tokens = 0;
758 for (i = 0; ignore_tokens[i] != NULL; i++)
759 sound_info->num_ignore_tokens++;
761 sound_info->base_prefixes = base_prefixes;
762 sound_info->ext1_suffixes = ext1_suffixes;
763 sound_info->ext2_suffixes = ext2_suffixes;
764 sound_info->ext3_suffixes = ext3_suffixes;
765 sound_info->ignore_tokens = ignore_tokens;
767 sound_info->num_property_mapping_entries = 0;
769 sound_info->property_mapping = NULL;
771 /* ---------- initialize artwork reference and content lists ---------- */
773 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
775 sound_info->artwork_list =
776 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
777 sound_info->dynamic_artwork_list = NULL;
779 sound_info->content_list = NULL;
781 /* ---------- initialize artwork loading/freeing functions ---------- */
783 sound_info->load_artwork = Load_WAV;
784 sound_info->free_artwork = FreeSound;
787 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
788 struct ConfigTypeInfo *config_suffix_list,
789 char **base_prefixes, char **ext1_suffixes,
790 char **ext2_suffixes, char **ext3_suffixes,
791 char **ignore_tokens)
795 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
796 music_info->type = ARTWORK_TYPE_MUSIC;
798 /* ---------- initialize file list and suffix lists ---------- */
800 music_info->num_file_list_entries = num_file_list_entries;
801 music_info->num_dynamic_file_list_entries = 0;
803 music_info->file_list =
804 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
805 num_file_list_entries);
806 music_info->dynamic_file_list = NULL;
808 music_info->num_suffix_list_entries = 0;
809 for (i = 0; config_suffix_list[i].token != NULL; i++)
810 music_info->num_suffix_list_entries++;
812 music_info->suffix_list = config_suffix_list;
814 /* ---------- initialize base prefix and suffixes lists ---------- */
816 music_info->num_base_prefixes = 0;
817 for (i = 0; base_prefixes[i] != NULL; i++)
818 music_info->num_base_prefixes++;
820 music_info->num_ext1_suffixes = 0;
821 for (i = 0; ext1_suffixes[i] != NULL; i++)
822 music_info->num_ext1_suffixes++;
824 music_info->num_ext2_suffixes = 0;
825 for (i = 0; ext2_suffixes[i] != NULL; i++)
826 music_info->num_ext2_suffixes++;
828 music_info->num_ext3_suffixes = 0;
829 for (i = 0; ext3_suffixes[i] != NULL; i++)
830 music_info->num_ext3_suffixes++;
832 music_info->num_ignore_tokens = 0;
833 for (i = 0; ignore_tokens[i] != NULL; i++)
834 music_info->num_ignore_tokens++;
836 music_info->base_prefixes = base_prefixes;
837 music_info->ext1_suffixes = ext1_suffixes;
838 music_info->ext2_suffixes = ext2_suffixes;
839 music_info->ext3_suffixes = ext3_suffixes;
840 music_info->ignore_tokens = ignore_tokens;
842 music_info->num_property_mapping_entries = 0;
844 music_info->property_mapping = NULL;
846 /* ---------- initialize artwork reference and content lists ---------- */
848 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
850 music_info->artwork_list =
851 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
852 music_info->dynamic_artwork_list = NULL;
854 music_info->content_list = NULL;
856 /* ---------- initialize artwork loading/freeing functions ---------- */
858 music_info->load_artwork = Load_WAV_or_MOD;
859 music_info->free_artwork = FreeMusic;
862 void PlayMusic(int nr)
864 if (!audio.music_available)
870 void PlaySound(int nr)
872 if (!setup.sound_simple)
875 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
878 void PlaySoundStereo(int nr, int stereo_position)
880 if (!setup.sound_simple)
883 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
886 void PlaySoundLoop(int nr)
888 if (!setup.sound_loops)
891 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
894 void PlaySoundMusic(int nr)
896 if (!setup.sound_music)
899 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
902 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
904 SoundControl snd_ctrl;
906 if (!audio.sound_available ||
907 !audio.sound_enabled ||
908 audio.sound_deactivated)
911 volume = SETUP_SOUND_VOLUME(volume, state);
913 if (volume < SOUND_MIN_VOLUME)
914 volume = SOUND_MIN_VOLUME;
915 else if (volume > SOUND_MAX_VOLUME)
916 volume = SOUND_MAX_VOLUME;
918 if (stereo_position < SOUND_MAX_LEFT)
919 stereo_position = SOUND_MAX_LEFT;
920 else if (stereo_position > SOUND_MAX_RIGHT)
921 stereo_position = SOUND_MAX_RIGHT;
923 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
925 snd_ctrl.active = TRUE;
927 snd_ctrl.volume = volume;
928 snd_ctrl.stereo_position = stereo_position;
929 snd_ctrl.state = state;
931 HandleSoundRequest(snd_ctrl);
936 if (!audio.music_available)
939 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
942 void FadeSound(int nr)
944 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
949 StopSoundExt(-1, SND_CTRL_FADE_ALL);
952 void FadeSoundsAndMusic()
960 if (!audio.music_available)
963 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
966 void StopSound(int nr)
968 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
974 StopSoundExt(-1, SND_CTRL_STOP_ALL);
977 void StopSoundExt(int nr, int state)
979 SoundControl snd_ctrl;
981 if (!audio.sound_available)
984 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
986 snd_ctrl.active = FALSE;
988 snd_ctrl.state = state;
990 HandleSoundRequest(snd_ctrl);
993 static void ReloadCustomSounds()
995 LoadArtworkConfig(sound_info);
996 ReloadCustomArtworkList(sound_info);
999 static void ReloadCustomMusic()
1001 LoadArtworkConfig(music_info);
1002 ReloadCustomArtworkList(music_info);
1004 /* load all music files from directory not defined in "musicinfo.conf" */
1005 LoadCustomMusic_NoConf();
1008 void InitReloadCustomSounds(char *set_identifier)
1010 if (!audio.sound_available)
1013 ReloadCustomSounds();
1016 void InitReloadCustomMusic(char *set_identifier)
1018 if (!audio.music_available)
1021 ReloadCustomMusic();
1024 void FreeSound(void *ptr)
1026 SoundInfo *sound = (SoundInfo *)ptr;
1031 if (sound->data_ptr)
1033 Mix_FreeChunk(sound->data_ptr);
1036 checked_free(sound->source_filename);
1041 void FreeMusic(void *ptr)
1043 MusicInfo *music = (MusicInfo *)ptr;
1048 if (music->data_ptr)
1050 if (music->type == MUS_TYPE_MOD)
1051 Mix_FreeMusic(music->data_ptr);
1053 Mix_FreeChunk(music->data_ptr);
1059 static void FreeAllMusic_NoConf()
1063 if (Music_NoConf == NULL)
1066 for (i = 0; i < num_music_noconf; i++)
1067 FreeMusic(Music_NoConf[i]);
1071 Music_NoConf = NULL;
1072 num_music_noconf = 0;
1075 void FreeAllSounds()
1077 FreeCustomArtworkLists(sound_info);
1082 FreeCustomArtworkLists(music_info);
1083 FreeAllMusic_NoConf();
1086 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1087 /* ========================================================================= */