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'", filename);
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'", filename);
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 char *filename = NULL;
602 MusicInfo *mus_info = NULL;
603 boolean music_already_used = FALSE;
606 /* skip all music files that are configured in music config file */
607 for (i = 0; i < num_music; i++)
609 struct FileInfo *music = getMusicListEntry(i);
611 if (strEqual(basename, music->filename))
613 music_already_used = TRUE;
618 if (music_already_used)
622 DrawInitText(basename, 150, FC_YELLOW);
624 filename = getPath2(music_directory, basename);
626 if (FileIsMusic(basename))
627 mus_info = Load_WAV_or_MOD(filename);
634 Music_NoConf = checked_realloc(Music_NoConf,
635 num_music_noconf * sizeof(MusicInfo *));
636 Music_NoConf[num_music_noconf - 1] = mus_info;
642 draw_init_text = FALSE;
645 int getSoundListSize()
647 return (sound_info->num_file_list_entries +
648 sound_info->num_dynamic_file_list_entries);
651 int getMusicListSize()
653 return (music_info->num_file_list_entries +
654 music_info->num_dynamic_file_list_entries);
657 struct FileInfo *getSoundListEntry(int pos)
659 int num_list_entries = sound_info->num_file_list_entries;
660 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
662 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
663 &sound_info->dynamic_file_list[list_pos]);
666 struct FileInfo *getMusicListEntry(int pos)
668 int num_list_entries = music_info->num_file_list_entries;
669 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
671 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
672 &music_info->dynamic_file_list[list_pos]);
675 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
677 int num_list_entries = sound_info->num_file_list_entries;
678 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
679 SoundInfo **snd_info =
680 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
681 sound_info->dynamic_artwork_list);
683 return snd_info[list_pos];
686 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
688 int num_list_entries = music_info->num_file_list_entries;
689 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
690 MusicInfo **mus_info =
691 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
692 music_info->dynamic_artwork_list);
694 return mus_info[list_pos];
697 int getSoundListPropertyMappingSize()
699 return sound_info->num_property_mapping_entries;
702 int getMusicListPropertyMappingSize()
704 return music_info->num_property_mapping_entries;
707 struct PropertyMapping *getSoundListPropertyMapping()
709 return sound_info->property_mapping;
712 struct PropertyMapping *getMusicListPropertyMapping()
714 return music_info->property_mapping;
717 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
718 struct ConfigTypeInfo *config_suffix_list,
719 char **base_prefixes, char **ext1_suffixes,
720 char **ext2_suffixes, char **ext3_suffixes,
721 char **ignore_tokens)
725 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
726 sound_info->type = ARTWORK_TYPE_SOUNDS;
728 /* ---------- initialize file list and suffix lists ---------- */
730 sound_info->num_file_list_entries = num_file_list_entries;
731 sound_info->num_dynamic_file_list_entries = 0;
733 sound_info->file_list =
734 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
735 num_file_list_entries);
736 sound_info->dynamic_file_list = NULL;
738 sound_info->num_suffix_list_entries = 0;
739 for (i = 0; config_suffix_list[i].token != NULL; i++)
740 sound_info->num_suffix_list_entries++;
742 sound_info->suffix_list = config_suffix_list;
744 /* ---------- initialize base prefix and suffixes lists ---------- */
746 sound_info->num_base_prefixes = 0;
747 for (i = 0; base_prefixes[i] != NULL; i++)
748 sound_info->num_base_prefixes++;
750 sound_info->num_ext1_suffixes = 0;
751 for (i = 0; ext1_suffixes[i] != NULL; i++)
752 sound_info->num_ext1_suffixes++;
754 sound_info->num_ext2_suffixes = 0;
755 for (i = 0; ext2_suffixes[i] != NULL; i++)
756 sound_info->num_ext2_suffixes++;
758 sound_info->num_ext3_suffixes = 0;
759 for (i = 0; ext3_suffixes[i] != NULL; i++)
760 sound_info->num_ext3_suffixes++;
762 sound_info->num_ignore_tokens = 0;
763 for (i = 0; ignore_tokens[i] != NULL; i++)
764 sound_info->num_ignore_tokens++;
766 sound_info->base_prefixes = base_prefixes;
767 sound_info->ext1_suffixes = ext1_suffixes;
768 sound_info->ext2_suffixes = ext2_suffixes;
769 sound_info->ext3_suffixes = ext3_suffixes;
770 sound_info->ignore_tokens = ignore_tokens;
772 sound_info->num_property_mapping_entries = 0;
774 sound_info->property_mapping = NULL;
776 /* ---------- initialize artwork reference and content lists ---------- */
778 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
780 sound_info->artwork_list =
781 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
782 sound_info->dynamic_artwork_list = NULL;
784 sound_info->content_list = NULL;
786 /* ---------- initialize artwork loading/freeing functions ---------- */
788 sound_info->load_artwork = Load_WAV;
789 sound_info->free_artwork = FreeSound;
792 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
793 struct ConfigTypeInfo *config_suffix_list,
794 char **base_prefixes, char **ext1_suffixes,
795 char **ext2_suffixes, char **ext3_suffixes,
796 char **ignore_tokens)
800 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
801 music_info->type = ARTWORK_TYPE_MUSIC;
803 /* ---------- initialize file list and suffix lists ---------- */
805 music_info->num_file_list_entries = num_file_list_entries;
806 music_info->num_dynamic_file_list_entries = 0;
808 music_info->file_list =
809 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
810 num_file_list_entries);
811 music_info->dynamic_file_list = NULL;
813 music_info->num_suffix_list_entries = 0;
814 for (i = 0; config_suffix_list[i].token != NULL; i++)
815 music_info->num_suffix_list_entries++;
817 music_info->suffix_list = config_suffix_list;
819 /* ---------- initialize base prefix and suffixes lists ---------- */
821 music_info->num_base_prefixes = 0;
822 for (i = 0; base_prefixes[i] != NULL; i++)
823 music_info->num_base_prefixes++;
825 music_info->num_ext1_suffixes = 0;
826 for (i = 0; ext1_suffixes[i] != NULL; i++)
827 music_info->num_ext1_suffixes++;
829 music_info->num_ext2_suffixes = 0;
830 for (i = 0; ext2_suffixes[i] != NULL; i++)
831 music_info->num_ext2_suffixes++;
833 music_info->num_ext3_suffixes = 0;
834 for (i = 0; ext3_suffixes[i] != NULL; i++)
835 music_info->num_ext3_suffixes++;
837 music_info->num_ignore_tokens = 0;
838 for (i = 0; ignore_tokens[i] != NULL; i++)
839 music_info->num_ignore_tokens++;
841 music_info->base_prefixes = base_prefixes;
842 music_info->ext1_suffixes = ext1_suffixes;
843 music_info->ext2_suffixes = ext2_suffixes;
844 music_info->ext3_suffixes = ext3_suffixes;
845 music_info->ignore_tokens = ignore_tokens;
847 music_info->num_property_mapping_entries = 0;
849 music_info->property_mapping = NULL;
851 /* ---------- initialize artwork reference and content lists ---------- */
853 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
855 music_info->artwork_list =
856 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
857 music_info->dynamic_artwork_list = NULL;
859 music_info->content_list = NULL;
861 /* ---------- initialize artwork loading/freeing functions ---------- */
863 music_info->load_artwork = Load_WAV_or_MOD;
864 music_info->free_artwork = FreeMusic;
867 void PlayMusic(int nr)
869 if (!audio.music_available)
875 void PlaySound(int nr)
877 if (!setup.sound_simple)
880 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
883 void PlaySoundStereo(int nr, int stereo_position)
885 if (!setup.sound_simple)
888 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
891 void PlaySoundLoop(int nr)
893 if (!setup.sound_loops)
896 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
899 void PlaySoundMusic(int nr)
901 if (!setup.sound_music)
904 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
907 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
909 SoundControl snd_ctrl;
911 if (!audio.sound_available ||
912 !audio.sound_enabled ||
913 audio.sound_deactivated)
916 volume = SETUP_SOUND_VOLUME(volume, state);
918 if (volume < SOUND_MIN_VOLUME)
919 volume = SOUND_MIN_VOLUME;
920 else if (volume > SOUND_MAX_VOLUME)
921 volume = SOUND_MAX_VOLUME;
923 if (stereo_position < SOUND_MAX_LEFT)
924 stereo_position = SOUND_MAX_LEFT;
925 else if (stereo_position > SOUND_MAX_RIGHT)
926 stereo_position = SOUND_MAX_RIGHT;
928 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
930 snd_ctrl.active = TRUE;
932 snd_ctrl.volume = volume;
933 snd_ctrl.stereo_position = stereo_position;
934 snd_ctrl.state = state;
936 HandleSoundRequest(snd_ctrl);
941 if (!audio.music_available)
944 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
947 void FadeSound(int nr)
949 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
954 StopSoundExt(-1, SND_CTRL_FADE_ALL);
957 void FadeSoundsAndMusic()
965 if (!audio.music_available)
968 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
971 void StopSound(int nr)
973 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
979 StopSoundExt(-1, SND_CTRL_STOP_ALL);
982 void StopSoundExt(int nr, int state)
984 SoundControl snd_ctrl;
986 if (!audio.sound_available)
989 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
991 snd_ctrl.active = FALSE;
993 snd_ctrl.state = state;
995 HandleSoundRequest(snd_ctrl);
998 static void ReloadCustomSounds()
1000 LoadArtworkConfig(sound_info);
1001 ReloadCustomArtworkList(sound_info);
1004 static void ReloadCustomMusic()
1006 LoadArtworkConfig(music_info);
1007 ReloadCustomArtworkList(music_info);
1009 /* load all music files from directory not defined in "musicinfo.conf" */
1010 LoadCustomMusic_NoConf();
1013 void InitReloadCustomSounds(char *set_identifier)
1015 if (!audio.sound_available)
1018 ReloadCustomSounds();
1021 void InitReloadCustomMusic(char *set_identifier)
1023 if (!audio.music_available)
1026 ReloadCustomMusic();
1029 void FreeSound(void *ptr)
1031 SoundInfo *sound = (SoundInfo *)ptr;
1036 if (sound->data_ptr)
1038 Mix_FreeChunk(sound->data_ptr);
1041 checked_free(sound->source_filename);
1046 void FreeMusic(void *ptr)
1048 MusicInfo *music = (MusicInfo *)ptr;
1053 if (music->data_ptr)
1055 if (music->type == MUS_TYPE_MOD)
1056 Mix_FreeMusic(music->data_ptr);
1058 Mix_FreeChunk(music->data_ptr);
1064 static void FreeAllMusic_NoConf()
1068 if (Music_NoConf == NULL)
1071 for (i = 0; i < num_music_noconf; i++)
1072 FreeMusic(Music_NoConf[i]);
1076 Music_NoConf = NULL;
1077 num_music_noconf = 0;
1080 void FreeAllSounds()
1082 FreeCustomArtworkLists(sound_info);
1087 FreeCustomArtworkLists(music_info);
1088 FreeAllMusic_NoConf();
1091 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1092 /* ========================================================================= */