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;
125 static boolean expire_loop_sounds = FALSE;
127 static void ReloadCustomSounds();
128 static void ReloadCustomMusic();
129 static void FreeSound(void *);
130 static void FreeMusic(void *);
131 static void FreeAllMusic_NoConf();
133 static SoundInfo *getSoundInfoEntryFromSoundID(int);
134 static MusicInfo *getMusicInfoEntryFromMusicID(int);
137 /* ------------------------------------------------------------------------- */
138 /* mixer functions */
139 /* ------------------------------------------------------------------------- */
141 void Mixer_InitChannels()
145 for (i = 0; i < audio.num_channels; i++)
146 mixer[i].active = FALSE;
147 mixer_active_channels = 0;
150 static void Mixer_ResetChannelExpiration(int channel)
152 mixer[channel].playing_starttime = Counter();
154 if (expire_loop_sounds &&
155 IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
156 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
159 static boolean Mixer_ChannelExpired(int channel)
161 if (!mixer[channel].active)
164 if (expire_loop_sounds &&
165 IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
166 DelayReached(&mixer[channel].playing_starttime,
167 SOUND_LOOP_EXPIRATION_TIME))
170 if (!Mix_Playing(channel))
176 static boolean Mixer_AllocateChannel(int channel)
181 static void Mixer_SetChannelProperties(int channel)
183 Mix_Volume(channel, mixer[channel].volume);
184 Mix_SetPanning(channel,
185 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
186 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
189 static void Mixer_StartChannel(int channel)
191 Mix_PlayChannel(channel, mixer[channel].data_ptr,
192 IS_LOOP(mixer[channel]) ? -1 : 0);
195 static void Mixer_PlayChannel(int channel)
197 /* start with inactive channel in case something goes wrong */
198 mixer[channel].active = FALSE;
200 if (mixer[channel].type != MUS_TYPE_WAV)
203 if (!Mixer_AllocateChannel(channel))
206 Mixer_SetChannelProperties(channel);
207 Mixer_StartChannel(channel);
209 Mixer_ResetChannelExpiration(channel);
211 mixer[channel].playing_pos = 0;
212 mixer[channel].active = TRUE;
213 mixer_active_channels++;
216 static void Mixer_PlayMusicChannel()
218 Mixer_PlayChannel(audio.music_channel);
220 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
222 // use short fade-in to prevent "plop" sound for certain music files
223 // (this may happen when switching on music while playing the game)
224 Mix_VolumeMusic(mixer[audio.music_channel].volume);
225 Mix_FadeInMusic(mixer[audio.music_channel].data_ptr, -1, 100);
229 static void Mixer_StopChannel(int channel)
231 if (!mixer[channel].active)
234 Mix_HaltChannel(channel);
236 mixer[channel].active = FALSE;
237 mixer_active_channels--;
240 static void Mixer_StopMusicChannel()
242 Mixer_StopChannel(audio.music_channel);
247 static void Mixer_FadeChannel(int channel)
249 if (!mixer[channel].active)
252 mixer[channel].state |= SND_CTRL_FADE;
254 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
257 static void Mixer_FadeMusicChannel()
259 Mixer_FadeChannel(audio.music_channel);
261 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
264 static void Mixer_UnFadeChannel(int channel)
266 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
269 mixer[channel].state &= ~SND_CTRL_FADE;
270 mixer[channel].volume = SOUND_MAX_VOLUME;
272 Mix_ExpireChannel(channel, -1);
273 Mix_Volume(channel, mixer[channel].volume);
276 static void Mixer_InsertSound(SoundControl snd_ctrl)
280 int num_sounds = getSoundListSize();
281 int num_music = getMusicListSize();
283 if (IS_MUSIC(snd_ctrl))
285 if (snd_ctrl.nr >= num_music) /* invalid music */
288 if (snd_ctrl.nr < 0) /* undefined music */
290 if (num_music_noconf == 0) /* no fallback music available */
293 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
294 snd_info = Music_NoConf[snd_ctrl.nr];
297 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
301 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
304 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
307 if (snd_info == NULL)
310 /* copy sound sample and format information */
311 snd_ctrl.type = snd_info->type;
312 snd_ctrl.format = snd_info->format;
313 snd_ctrl.data_ptr = snd_info->data_ptr;
314 snd_ctrl.data_len = snd_info->data_len;
315 snd_ctrl.num_channels = snd_info->num_channels;
317 /* play music samples on a dedicated music channel */
318 if (IS_MUSIC(snd_ctrl))
320 Mixer_StopMusicChannel();
322 mixer[audio.music_channel] = snd_ctrl;
323 Mixer_PlayMusicChannel();
328 /* check if (and how often) this sound sample is already playing */
329 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
330 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
333 /* reset expiration delay for already playing loop sounds */
334 if (k > 0 && IS_LOOP(snd_ctrl))
336 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
338 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
340 if (IS_FADING(mixer[i]))
341 Mixer_UnFadeChannel(i);
343 /* restore settings like volume and stereo position */
344 mixer[i].volume = snd_ctrl.volume;
345 mixer[i].stereo_position = snd_ctrl.stereo_position;
347 Mixer_SetChannelProperties(i);
348 Mixer_ResetChannelExpiration(i);
355 /* don't play sound more than n times simultaneously (with n == 2 for now) */
358 unsigned int playing_current = Counter();
359 int longest = 0, longest_nr = audio.first_sound_channel;
361 /* look for oldest equal sound */
362 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
364 int playing_time = playing_current - mixer[i].playing_starttime;
367 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
370 actual = 1000 * playing_time / mixer[i].data_len;
372 if (actual >= longest)
379 Mixer_StopChannel(longest_nr);
382 /* If all (non-music) channels are active, stop the channel that has
383 played its sound sample most completely (in percent of the sample
384 length). As we cannot currently get the actual playing position
385 of the channel's sound sample when compiling with the SDL mixer
386 library, we use the current playing time (in milliseconds) instead. */
389 /* channel allocation sanity check -- should not be needed */
390 if (mixer_active_channels ==
391 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
393 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
395 if (!mixer[i].active)
397 Error(ERR_INFO, "Mixer_InsertSound: Channel %d inactive", i);
398 Error(ERR_INFO, "Mixer_InsertSound: This should never happen!");
400 mixer_active_channels--;
406 if (mixer_active_channels ==
407 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
409 unsigned int playing_current = Counter();
410 int longest = 0, longest_nr = audio.first_sound_channel;
412 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
414 int playing_time = playing_current - mixer[i].playing_starttime;
415 int actual = 1000 * playing_time / mixer[i].data_len;
417 if (!IS_LOOP(mixer[i]) && actual > longest)
424 Mixer_StopChannel(longest_nr);
427 /* add the new sound to the mixer */
428 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
430 if (!mixer[i].active)
433 Mixer_PlayChannel(i);
440 static void HandleSoundRequest(SoundControl snd_ctrl)
444 /* deactivate channels that have expired since the last request */
445 for (i = 0; i < audio.num_channels; i++)
446 if (mixer[i].active && Mixer_ChannelExpired(i))
447 Mixer_StopChannel(i);
449 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
451 Mixer_StopMusicChannel();
452 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
453 Mixer_StopChannel(i);
455 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
456 ReloadCustomSounds();
460 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
462 if (IS_MUSIC(snd_ctrl))
464 Mixer_FadeMusicChannel();
468 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
469 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
470 Mixer_FadeChannel(i);
472 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
474 if (IS_MUSIC(snd_ctrl))
476 Mixer_StopMusicChannel();
480 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
481 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
482 Mixer_StopChannel(i);
484 else if (SET_EXPIRE_LOOPS(snd_ctrl)) /* set loop expiration on or off */
486 expire_loop_sounds = snd_ctrl.active;
488 else if (snd_ctrl.active) /* add new sound to mixer */
490 Mixer_InsertSound(snd_ctrl);
494 void StartMixer(void)
498 if (!audio.sound_available)
501 /* initialize stereo position conversion information */
502 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
504 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
508 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
509 /* ========================================================================= */
510 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
512 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
513 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
515 static void *Load_WAV(char *filename)
519 if (!audio.sound_available)
522 snd_info = checked_calloc(sizeof(SoundInfo));
524 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
526 Error(ERR_WARN, "cannot read sound file '%s': %s", filename, Mix_GetError());
531 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
533 snd_info->type = SND_TYPE_WAV;
534 snd_info->source_filename = getStringCopy(filename);
539 static void *Load_MOD(char *filename)
543 if (!audio.sound_available)
546 mod_info = checked_calloc(sizeof(MusicInfo));
548 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
550 Error(ERR_WARN, "cannot read music file '%s': %s", filename, Mix_GetError());
555 mod_info->type = MUS_TYPE_MOD;
556 mod_info->source_filename = getStringCopy(filename);
561 static void *Load_WAV_or_MOD(char *filename)
563 if (FileIsMusic(filename))
564 return Load_MOD(filename);
565 else if (FileIsSound(filename))
566 return Load_WAV(filename);
571 void LoadCustomMusic_NoConf(void)
573 static boolean draw_init_text = TRUE; /* only draw at startup */
574 static char *last_music_directory = NULL;
575 char *music_directory = getCustomMusicDirectory();
577 DirectoryEntry *dir_entry;
578 int num_music = getMusicListSize();
580 if (!audio.sound_available)
583 if (last_music_directory != NULL &&
584 strEqual(last_music_directory, music_directory))
585 return; /* old and new music directory are the same */
587 if (last_music_directory != NULL)
588 free(last_music_directory);
589 last_music_directory = getStringCopy(music_directory);
591 FreeAllMusic_NoConf();
593 if ((dir = openDirectory(music_directory)) == NULL)
595 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
597 audio.music_available = FALSE;
603 DrawInitText("Loading music", 120, FC_GREEN);
605 while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */
607 char *basename = dir_entry->basename;
608 MusicInfo *mus_info = NULL;
609 boolean music_already_used = FALSE;
612 /* skip all music files that are configured in music config file */
613 for (i = 0; i < num_music; i++)
615 struct FileInfo *music = getMusicListEntry(i);
617 if (strEqual(basename, music->filename))
619 music_already_used = TRUE;
624 if (music_already_used)
628 DrawInitText(basename, 150, FC_YELLOW);
630 if (FileIsMusic(dir_entry->filename))
631 mus_info = Load_WAV_or_MOD(dir_entry->filename);
636 Music_NoConf = checked_realloc(Music_NoConf,
637 num_music_noconf * sizeof(MusicInfo *));
638 Music_NoConf[num_music_noconf - 1] = mus_info;
644 draw_init_text = FALSE;
647 int getSoundListSize()
649 return (sound_info->num_file_list_entries +
650 sound_info->num_dynamic_file_list_entries);
653 int getMusicListSize()
655 return (music_info->num_file_list_entries +
656 music_info->num_dynamic_file_list_entries);
659 struct FileInfo *getSoundListEntry(int pos)
661 int num_list_entries = sound_info->num_file_list_entries;
662 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
664 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
665 &sound_info->dynamic_file_list[list_pos]);
668 struct FileInfo *getMusicListEntry(int pos)
670 int num_list_entries = music_info->num_file_list_entries;
671 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
673 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
674 &music_info->dynamic_file_list[list_pos]);
677 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
679 int num_list_entries = sound_info->num_file_list_entries;
680 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
681 SoundInfo **snd_info =
682 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
683 sound_info->dynamic_artwork_list);
685 return snd_info[list_pos];
688 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
690 int num_list_entries = music_info->num_file_list_entries;
691 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
692 MusicInfo **mus_info =
693 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
694 music_info->dynamic_artwork_list);
696 return mus_info[list_pos];
699 int getSoundListPropertyMappingSize()
701 return sound_info->num_property_mapping_entries;
704 int getMusicListPropertyMappingSize()
706 return music_info->num_property_mapping_entries;
709 struct PropertyMapping *getSoundListPropertyMapping()
711 return sound_info->property_mapping;
714 struct PropertyMapping *getMusicListPropertyMapping()
716 return music_info->property_mapping;
719 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
720 struct ConfigTypeInfo *config_suffix_list,
721 char **base_prefixes, char **ext1_suffixes,
722 char **ext2_suffixes, char **ext3_suffixes,
723 char **ignore_tokens)
727 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
728 sound_info->type = ARTWORK_TYPE_SOUNDS;
730 /* ---------- initialize file list and suffix lists ---------- */
732 sound_info->num_file_list_entries = num_file_list_entries;
733 sound_info->num_dynamic_file_list_entries = 0;
735 sound_info->file_list =
736 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
737 num_file_list_entries);
738 sound_info->dynamic_file_list = NULL;
740 sound_info->num_suffix_list_entries = 0;
741 for (i = 0; config_suffix_list[i].token != NULL; i++)
742 sound_info->num_suffix_list_entries++;
744 sound_info->suffix_list = config_suffix_list;
746 /* ---------- initialize base prefix and suffixes lists ---------- */
748 sound_info->num_base_prefixes = 0;
749 for (i = 0; base_prefixes[i] != NULL; i++)
750 sound_info->num_base_prefixes++;
752 sound_info->num_ext1_suffixes = 0;
753 for (i = 0; ext1_suffixes[i] != NULL; i++)
754 sound_info->num_ext1_suffixes++;
756 sound_info->num_ext2_suffixes = 0;
757 for (i = 0; ext2_suffixes[i] != NULL; i++)
758 sound_info->num_ext2_suffixes++;
760 sound_info->num_ext3_suffixes = 0;
761 for (i = 0; ext3_suffixes[i] != NULL; i++)
762 sound_info->num_ext3_suffixes++;
764 sound_info->num_ignore_tokens = 0;
765 for (i = 0; ignore_tokens[i] != NULL; i++)
766 sound_info->num_ignore_tokens++;
768 sound_info->base_prefixes = base_prefixes;
769 sound_info->ext1_suffixes = ext1_suffixes;
770 sound_info->ext2_suffixes = ext2_suffixes;
771 sound_info->ext3_suffixes = ext3_suffixes;
772 sound_info->ignore_tokens = ignore_tokens;
774 sound_info->num_property_mapping_entries = 0;
776 sound_info->property_mapping = NULL;
778 /* ---------- initialize artwork reference and content lists ---------- */
780 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
782 sound_info->artwork_list =
783 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
784 sound_info->dynamic_artwork_list = NULL;
786 sound_info->content_list = NULL;
788 /* ---------- initialize artwork loading/freeing functions ---------- */
790 sound_info->load_artwork = Load_WAV;
791 sound_info->free_artwork = FreeSound;
794 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
795 struct ConfigTypeInfo *config_suffix_list,
796 char **base_prefixes, char **ext1_suffixes,
797 char **ext2_suffixes, char **ext3_suffixes,
798 char **ignore_tokens)
802 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
803 music_info->type = ARTWORK_TYPE_MUSIC;
805 /* ---------- initialize file list and suffix lists ---------- */
807 music_info->num_file_list_entries = num_file_list_entries;
808 music_info->num_dynamic_file_list_entries = 0;
810 music_info->file_list =
811 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
812 num_file_list_entries);
813 music_info->dynamic_file_list = NULL;
815 music_info->num_suffix_list_entries = 0;
816 for (i = 0; config_suffix_list[i].token != NULL; i++)
817 music_info->num_suffix_list_entries++;
819 music_info->suffix_list = config_suffix_list;
821 /* ---------- initialize base prefix and suffixes lists ---------- */
823 music_info->num_base_prefixes = 0;
824 for (i = 0; base_prefixes[i] != NULL; i++)
825 music_info->num_base_prefixes++;
827 music_info->num_ext1_suffixes = 0;
828 for (i = 0; ext1_suffixes[i] != NULL; i++)
829 music_info->num_ext1_suffixes++;
831 music_info->num_ext2_suffixes = 0;
832 for (i = 0; ext2_suffixes[i] != NULL; i++)
833 music_info->num_ext2_suffixes++;
835 music_info->num_ext3_suffixes = 0;
836 for (i = 0; ext3_suffixes[i] != NULL; i++)
837 music_info->num_ext3_suffixes++;
839 music_info->num_ignore_tokens = 0;
840 for (i = 0; ignore_tokens[i] != NULL; i++)
841 music_info->num_ignore_tokens++;
843 music_info->base_prefixes = base_prefixes;
844 music_info->ext1_suffixes = ext1_suffixes;
845 music_info->ext2_suffixes = ext2_suffixes;
846 music_info->ext3_suffixes = ext3_suffixes;
847 music_info->ignore_tokens = ignore_tokens;
849 music_info->num_property_mapping_entries = 0;
851 music_info->property_mapping = NULL;
853 /* ---------- initialize artwork reference and content lists ---------- */
855 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
857 music_info->artwork_list =
858 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
859 music_info->dynamic_artwork_list = NULL;
861 music_info->content_list = NULL;
863 /* ---------- initialize artwork loading/freeing functions ---------- */
865 music_info->load_artwork = Load_WAV_or_MOD;
866 music_info->free_artwork = FreeMusic;
869 void PlayMusic(int nr)
871 if (!audio.music_available)
877 void PlaySound(int nr)
879 if (!setup.sound_simple)
882 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
885 void PlaySoundStereo(int nr, int stereo_position)
887 if (!setup.sound_simple)
890 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
893 void PlaySoundLoop(int nr)
895 if (!setup.sound_loops)
898 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
901 void PlaySoundMusic(int nr)
903 if (!setup.sound_music)
906 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
909 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
911 SoundControl snd_ctrl;
913 if (!audio.sound_available ||
914 !audio.sound_enabled ||
915 audio.sound_deactivated)
918 volume = SETUP_SOUND_VOLUME(volume, state);
920 if (volume < SOUND_MIN_VOLUME)
921 volume = SOUND_MIN_VOLUME;
922 else if (volume > SOUND_MAX_VOLUME)
923 volume = SOUND_MAX_VOLUME;
925 if (stereo_position < SOUND_MAX_LEFT)
926 stereo_position = SOUND_MAX_LEFT;
927 else if (stereo_position > SOUND_MAX_RIGHT)
928 stereo_position = SOUND_MAX_RIGHT;
930 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
932 snd_ctrl.active = TRUE;
934 snd_ctrl.volume = volume;
935 snd_ctrl.stereo_position = stereo_position;
936 snd_ctrl.state = state;
938 HandleSoundRequest(snd_ctrl);
943 if (!audio.music_available)
946 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
949 void FadeSound(int nr)
951 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
956 StopSoundExt(-1, SND_CTRL_FADE_ALL);
959 void FadeSoundsAndMusic()
967 if (!audio.music_available)
970 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
973 void StopSound(int nr)
975 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
981 StopSoundExt(-1, SND_CTRL_STOP_ALL);
984 void StopSoundExt(int nr, int state)
986 SoundControl snd_ctrl;
988 if (!audio.sound_available)
991 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
993 snd_ctrl.active = FALSE;
995 snd_ctrl.state = state;
997 HandleSoundRequest(snd_ctrl);
1000 void ExpireSoundLoops(boolean active)
1002 SoundControl snd_ctrl;
1004 if (!audio.sound_available)
1007 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
1009 snd_ctrl.active = active;
1010 snd_ctrl.state = SND_CTRL_EXPIRE_LOOPS;
1012 HandleSoundRequest(snd_ctrl);
1015 static void ReloadCustomSounds()
1017 LoadArtworkConfig(sound_info);
1018 ReloadCustomArtworkList(sound_info);
1021 static void ReloadCustomMusic()
1023 LoadArtworkConfig(music_info);
1024 ReloadCustomArtworkList(music_info);
1026 /* load all music files from directory not defined in "musicinfo.conf" */
1027 LoadCustomMusic_NoConf();
1030 void InitReloadCustomSounds(char *set_identifier)
1032 if (!audio.sound_available)
1035 ReloadCustomSounds();
1038 void InitReloadCustomMusic(char *set_identifier)
1040 if (!audio.music_available)
1043 ReloadCustomMusic();
1046 void FreeSound(void *ptr)
1048 SoundInfo *sound = (SoundInfo *)ptr;
1053 if (sound->data_ptr)
1055 Mix_FreeChunk(sound->data_ptr);
1058 checked_free(sound->source_filename);
1063 void FreeMusic(void *ptr)
1065 MusicInfo *music = (MusicInfo *)ptr;
1070 if (music->data_ptr)
1072 if (music->type == MUS_TYPE_MOD)
1073 Mix_FreeMusic(music->data_ptr);
1075 Mix_FreeChunk(music->data_ptr);
1081 static void FreeAllMusic_NoConf()
1085 if (Music_NoConf == NULL)
1088 for (i = 0; i < num_music_noconf; i++)
1089 FreeMusic(Music_NoConf[i]);
1093 Music_NoConf = NULL;
1094 num_music_noconf = 0;
1097 void FreeAllSounds()
1099 FreeCustomArtworkLists(sound_info);
1104 FreeCustomArtworkLists(music_info);
1105 FreeAllMusic_NoConf();
1108 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1109 /* ========================================================================= */