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];
119 static char *currently_playing_music_filename = NULL;
122 /* ========================================================================= */
123 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
125 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
126 static int mixer_active_channels = 0;
127 static boolean expire_loop_sounds = FALSE;
129 static void ReloadCustomSounds();
130 static void ReloadCustomMusic();
131 static void FreeSound(void *);
132 static void FreeMusic(void *);
133 static void FreeAllMusic_NoConf();
135 static SoundInfo *getSoundInfoEntryFromSoundID(int);
136 static MusicInfo *getMusicInfoEntryFromMusicID(int);
139 /* ------------------------------------------------------------------------- */
140 /* mixer functions */
141 /* ------------------------------------------------------------------------- */
143 void Mixer_InitChannels()
147 for (i = 0; i < audio.num_channels; i++)
148 mixer[i].active = FALSE;
149 mixer_active_channels = 0;
152 static void Mixer_ResetChannelExpiration(int channel)
154 mixer[channel].playing_starttime = Counter();
156 if (expire_loop_sounds &&
157 IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
158 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
161 static boolean Mixer_ChannelExpired(int channel)
163 if (!mixer[channel].active)
166 if (expire_loop_sounds &&
167 IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
168 DelayReached(&mixer[channel].playing_starttime,
169 SOUND_LOOP_EXPIRATION_TIME))
172 if (!Mix_Playing(channel))
178 static boolean Mixer_AllocateChannel(int channel)
183 static void Mixer_SetChannelProperties(int channel)
185 Mix_Volume(channel, mixer[channel].volume);
186 Mix_SetPanning(channel,
187 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
188 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
191 static void Mixer_StartChannel(int channel)
193 Mix_PlayChannel(channel, mixer[channel].data_ptr,
194 IS_LOOP(mixer[channel]) ? -1 : 0);
197 static void Mixer_PlayChannel(int channel)
199 /* start with inactive channel in case something goes wrong */
200 mixer[channel].active = FALSE;
202 if (mixer[channel].type != MUS_TYPE_WAV)
205 if (!Mixer_AllocateChannel(channel))
208 Mixer_SetChannelProperties(channel);
209 Mixer_StartChannel(channel);
211 Mixer_ResetChannelExpiration(channel);
213 mixer[channel].playing_pos = 0;
214 mixer[channel].active = TRUE;
215 mixer_active_channels++;
218 static void Mixer_PlayMusicChannel()
220 Mixer_PlayChannel(audio.music_channel);
222 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
224 // use short fade-in to prevent "plop" sound for certain music files
225 // (this may happen when switching on music while playing the game)
226 Mix_VolumeMusic(mixer[audio.music_channel].volume);
227 Mix_FadeInMusic(mixer[audio.music_channel].data_ptr, -1, 100);
231 static void Mixer_StopChannel(int channel)
233 if (!mixer[channel].active)
236 Mix_HaltChannel(channel);
238 mixer[channel].active = FALSE;
239 mixer_active_channels--;
242 static void Mixer_StopMusicChannel()
244 Mixer_StopChannel(audio.music_channel);
248 setString(¤tly_playing_music_filename, NULL);
251 static void Mixer_FadeChannel(int channel)
253 if (!mixer[channel].active)
256 mixer[channel].state |= SND_CTRL_FADE;
258 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
261 static void Mixer_FadeMusicChannel()
263 Mixer_FadeChannel(audio.music_channel);
265 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
267 setString(¤tly_playing_music_filename, NULL);
270 static void Mixer_UnFadeChannel(int channel)
272 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
275 mixer[channel].state &= ~SND_CTRL_FADE;
276 mixer[channel].volume = SOUND_MAX_VOLUME;
278 Mix_ExpireChannel(channel, -1);
279 Mix_Volume(channel, mixer[channel].volume);
282 static void Mixer_InsertSound(SoundControl snd_ctrl)
286 int num_sounds = getSoundListSize();
287 int num_music = getMusicListSize();
289 if (IS_MUSIC(snd_ctrl))
291 if (snd_ctrl.nr >= num_music) /* invalid music */
294 if (snd_ctrl.nr < 0) /* undefined music */
296 if (num_music_noconf == 0) /* no fallback music available */
299 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
300 snd_info = Music_NoConf[snd_ctrl.nr];
303 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
307 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
310 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
313 if (snd_info == NULL)
316 /* copy sound sample and format information */
317 snd_ctrl.type = snd_info->type;
318 snd_ctrl.format = snd_info->format;
319 snd_ctrl.data_ptr = snd_info->data_ptr;
320 snd_ctrl.data_len = snd_info->data_len;
321 snd_ctrl.num_channels = snd_info->num_channels;
323 /* play music samples on a dedicated music channel */
324 if (IS_MUSIC(snd_ctrl))
326 Mixer_StopMusicChannel();
328 mixer[audio.music_channel] = snd_ctrl;
329 Mixer_PlayMusicChannel();
331 setString(¤tly_playing_music_filename,
332 getBaseNamePtr(snd_info->source_filename));
337 /* check if (and how often) this sound sample is already playing */
338 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
339 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
342 /* reset expiration delay for already playing loop sounds */
343 if (k > 0 && IS_LOOP(snd_ctrl))
345 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
347 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
349 if (IS_FADING(mixer[i]))
350 Mixer_UnFadeChannel(i);
352 /* restore settings like volume and stereo position */
353 mixer[i].volume = snd_ctrl.volume;
354 mixer[i].stereo_position = snd_ctrl.stereo_position;
356 Mixer_SetChannelProperties(i);
357 Mixer_ResetChannelExpiration(i);
364 /* don't play sound more than n times simultaneously (with n == 2 for now) */
367 unsigned int playing_current = Counter();
368 int longest = 0, longest_nr = audio.first_sound_channel;
370 /* look for oldest equal sound */
371 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
373 int playing_time = playing_current - mixer[i].playing_starttime;
376 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
379 actual = 1000 * playing_time / mixer[i].data_len;
381 if (actual >= longest)
388 Mixer_StopChannel(longest_nr);
391 /* If all (non-music) channels are active, stop the channel that has
392 played its sound sample most completely (in percent of the sample
393 length). As we cannot currently get the actual playing position
394 of the channel's sound sample when compiling with the SDL mixer
395 library, we use the current playing time (in milliseconds) instead. */
398 /* channel allocation sanity check -- should not be needed */
399 if (mixer_active_channels ==
400 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
402 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
404 if (!mixer[i].active)
406 Error(ERR_INFO, "Mixer_InsertSound: Channel %d inactive", i);
407 Error(ERR_INFO, "Mixer_InsertSound: This should never happen!");
409 mixer_active_channels--;
415 if (mixer_active_channels ==
416 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
418 unsigned int playing_current = Counter();
419 int longest = 0, longest_nr = audio.first_sound_channel;
421 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
423 int playing_time = playing_current - mixer[i].playing_starttime;
424 int actual = 1000 * playing_time / mixer[i].data_len;
426 if (!IS_LOOP(mixer[i]) && actual > longest)
433 Mixer_StopChannel(longest_nr);
436 /* add the new sound to the mixer */
437 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
439 if (!mixer[i].active)
442 Mixer_PlayChannel(i);
449 static void HandleSoundRequest(SoundControl snd_ctrl)
453 /* deactivate channels that have expired since the last request */
454 for (i = 0; i < audio.num_channels; i++)
455 if (mixer[i].active && Mixer_ChannelExpired(i))
456 Mixer_StopChannel(i);
458 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
460 Mixer_StopMusicChannel();
461 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
462 Mixer_StopChannel(i);
464 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
465 ReloadCustomSounds();
469 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
471 if (IS_MUSIC(snd_ctrl))
473 Mixer_FadeMusicChannel();
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_FadeChannel(i);
481 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
483 if (IS_MUSIC(snd_ctrl))
485 Mixer_StopMusicChannel();
489 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
490 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
491 Mixer_StopChannel(i);
493 else if (SET_EXPIRE_LOOPS(snd_ctrl)) /* set loop expiration on or off */
495 expire_loop_sounds = snd_ctrl.active;
497 else if (snd_ctrl.active) /* add new sound to mixer */
499 Mixer_InsertSound(snd_ctrl);
503 void StartMixer(void)
507 if (!audio.sound_available)
510 /* initialize stereo position conversion information */
511 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
513 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
517 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
518 /* ========================================================================= */
519 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
521 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
522 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
524 static void *Load_WAV(char *filename)
528 if (!audio.sound_available)
531 snd_info = checked_calloc(sizeof(SoundInfo));
533 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
535 Error(ERR_WARN, "cannot read sound file '%s': %s", filename, Mix_GetError());
540 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
542 snd_info->type = SND_TYPE_WAV;
543 snd_info->source_filename = getStringCopy(filename);
548 static void *Load_MOD(char *filename)
552 if (!audio.sound_available)
555 mod_info = checked_calloc(sizeof(MusicInfo));
557 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
559 Error(ERR_WARN, "cannot read music file '%s': %s", filename, Mix_GetError());
564 mod_info->type = MUS_TYPE_MOD;
565 mod_info->source_filename = getStringCopy(filename);
570 static void *Load_WAV_or_MOD(char *filename)
572 if (FileIsMusic(filename))
573 return Load_MOD(filename);
574 else if (FileIsSound(filename))
575 return Load_WAV(filename);
580 void LoadCustomMusic_NoConf(void)
582 static boolean draw_init_text = TRUE; /* only draw at startup */
583 static char *last_music_directory = NULL;
584 char *music_directory = getCustomMusicDirectory();
586 DirectoryEntry *dir_entry;
587 int num_music = getMusicListSize();
589 if (!audio.sound_available)
592 if (last_music_directory != NULL &&
593 strEqual(last_music_directory, music_directory))
594 return; /* old and new music directory are the same */
596 if (last_music_directory != NULL)
597 free(last_music_directory);
598 last_music_directory = getStringCopy(music_directory);
600 FreeAllMusic_NoConf();
602 if ((dir = openDirectory(music_directory)) == NULL)
604 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
606 audio.music_available = FALSE;
612 DrawInitText("Loading music", 120, FC_GREEN);
614 while ((dir_entry = readDirectory(dir)) != NULL) /* loop all entries */
616 char *basename = dir_entry->basename;
617 MusicInfo *mus_info = NULL;
618 boolean music_already_used = FALSE;
621 /* skip all music files that are configured in music config file */
622 for (i = 0; i < num_music; i++)
624 struct FileInfo *music = getMusicListEntry(i);
626 if (strEqual(basename, music->filename))
628 music_already_used = TRUE;
633 if (music_already_used)
637 DrawInitText(basename, 150, FC_YELLOW);
639 if (FileIsMusic(dir_entry->filename))
640 mus_info = Load_WAV_or_MOD(dir_entry->filename);
645 Music_NoConf = checked_realloc(Music_NoConf,
646 num_music_noconf * sizeof(MusicInfo *));
647 Music_NoConf[num_music_noconf - 1] = mus_info;
653 draw_init_text = FALSE;
656 int getSoundListSize()
658 return (sound_info->num_file_list_entries +
659 sound_info->num_dynamic_file_list_entries);
662 int getMusicListSize()
664 return (music_info->num_file_list_entries +
665 music_info->num_dynamic_file_list_entries);
668 struct FileInfo *getSoundListEntry(int pos)
670 int num_list_entries = sound_info->num_file_list_entries;
671 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
673 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
674 &sound_info->dynamic_file_list[list_pos]);
677 struct FileInfo *getMusicListEntry(int pos)
679 int num_list_entries = music_info->num_file_list_entries;
680 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
682 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
683 &music_info->dynamic_file_list[list_pos]);
686 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
688 int num_list_entries = sound_info->num_file_list_entries;
689 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
690 SoundInfo **snd_info =
691 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
692 sound_info->dynamic_artwork_list);
694 return snd_info[list_pos];
697 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
699 int num_list_entries = music_info->num_file_list_entries;
700 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
701 MusicInfo **mus_info =
702 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
703 music_info->dynamic_artwork_list);
705 return mus_info[list_pos];
708 char *getCurrentlyPlayingMusicFilename()
710 return currently_playing_music_filename;
713 int getSoundListPropertyMappingSize()
715 return sound_info->num_property_mapping_entries;
718 int getMusicListPropertyMappingSize()
720 return music_info->num_property_mapping_entries;
723 struct PropertyMapping *getSoundListPropertyMapping()
725 return sound_info->property_mapping;
728 struct PropertyMapping *getMusicListPropertyMapping()
730 return music_info->property_mapping;
733 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
734 struct ConfigTypeInfo *config_suffix_list,
735 char **base_prefixes, char **ext1_suffixes,
736 char **ext2_suffixes, char **ext3_suffixes,
737 char **ignore_tokens)
741 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
742 sound_info->type = ARTWORK_TYPE_SOUNDS;
744 /* ---------- initialize file list and suffix lists ---------- */
746 sound_info->num_file_list_entries = num_file_list_entries;
747 sound_info->num_dynamic_file_list_entries = 0;
749 sound_info->file_list =
750 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
751 num_file_list_entries);
752 sound_info->dynamic_file_list = NULL;
754 sound_info->num_suffix_list_entries = 0;
755 for (i = 0; config_suffix_list[i].token != NULL; i++)
756 sound_info->num_suffix_list_entries++;
758 sound_info->suffix_list = config_suffix_list;
760 /* ---------- initialize base prefix and suffixes lists ---------- */
762 sound_info->num_base_prefixes = 0;
763 for (i = 0; base_prefixes[i] != NULL; i++)
764 sound_info->num_base_prefixes++;
766 sound_info->num_ext1_suffixes = 0;
767 for (i = 0; ext1_suffixes[i] != NULL; i++)
768 sound_info->num_ext1_suffixes++;
770 sound_info->num_ext2_suffixes = 0;
771 for (i = 0; ext2_suffixes[i] != NULL; i++)
772 sound_info->num_ext2_suffixes++;
774 sound_info->num_ext3_suffixes = 0;
775 for (i = 0; ext3_suffixes[i] != NULL; i++)
776 sound_info->num_ext3_suffixes++;
778 sound_info->num_ignore_tokens = 0;
779 for (i = 0; ignore_tokens[i] != NULL; i++)
780 sound_info->num_ignore_tokens++;
782 sound_info->base_prefixes = base_prefixes;
783 sound_info->ext1_suffixes = ext1_suffixes;
784 sound_info->ext2_suffixes = ext2_suffixes;
785 sound_info->ext3_suffixes = ext3_suffixes;
786 sound_info->ignore_tokens = ignore_tokens;
788 sound_info->num_property_mapping_entries = 0;
790 sound_info->property_mapping = NULL;
792 /* ---------- initialize artwork reference and content lists ---------- */
794 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
796 sound_info->artwork_list =
797 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
798 sound_info->dynamic_artwork_list = NULL;
800 sound_info->content_list = NULL;
802 /* ---------- initialize artwork loading/freeing functions ---------- */
804 sound_info->load_artwork = Load_WAV;
805 sound_info->free_artwork = FreeSound;
808 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
809 struct ConfigTypeInfo *config_suffix_list,
810 char **base_prefixes, char **ext1_suffixes,
811 char **ext2_suffixes, char **ext3_suffixes,
812 char **ignore_tokens)
816 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
817 music_info->type = ARTWORK_TYPE_MUSIC;
819 /* ---------- initialize file list and suffix lists ---------- */
821 music_info->num_file_list_entries = num_file_list_entries;
822 music_info->num_dynamic_file_list_entries = 0;
824 music_info->file_list =
825 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
826 num_file_list_entries);
827 music_info->dynamic_file_list = NULL;
829 music_info->num_suffix_list_entries = 0;
830 for (i = 0; config_suffix_list[i].token != NULL; i++)
831 music_info->num_suffix_list_entries++;
833 music_info->suffix_list = config_suffix_list;
835 /* ---------- initialize base prefix and suffixes lists ---------- */
837 music_info->num_base_prefixes = 0;
838 for (i = 0; base_prefixes[i] != NULL; i++)
839 music_info->num_base_prefixes++;
841 music_info->num_ext1_suffixes = 0;
842 for (i = 0; ext1_suffixes[i] != NULL; i++)
843 music_info->num_ext1_suffixes++;
845 music_info->num_ext2_suffixes = 0;
846 for (i = 0; ext2_suffixes[i] != NULL; i++)
847 music_info->num_ext2_suffixes++;
849 music_info->num_ext3_suffixes = 0;
850 for (i = 0; ext3_suffixes[i] != NULL; i++)
851 music_info->num_ext3_suffixes++;
853 music_info->num_ignore_tokens = 0;
854 for (i = 0; ignore_tokens[i] != NULL; i++)
855 music_info->num_ignore_tokens++;
857 music_info->base_prefixes = base_prefixes;
858 music_info->ext1_suffixes = ext1_suffixes;
859 music_info->ext2_suffixes = ext2_suffixes;
860 music_info->ext3_suffixes = ext3_suffixes;
861 music_info->ignore_tokens = ignore_tokens;
863 music_info->num_property_mapping_entries = 0;
865 music_info->property_mapping = NULL;
867 /* ---------- initialize artwork reference and content lists ---------- */
869 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
871 music_info->artwork_list =
872 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
873 music_info->dynamic_artwork_list = NULL;
875 music_info->content_list = NULL;
877 /* ---------- initialize artwork loading/freeing functions ---------- */
879 music_info->load_artwork = Load_WAV_or_MOD;
880 music_info->free_artwork = FreeMusic;
883 void PlayMusic(int nr)
885 if (!audio.music_available)
891 void PlaySound(int nr)
893 if (!setup.sound_simple)
896 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
899 void PlaySoundStereo(int nr, int stereo_position)
901 if (!setup.sound_simple)
904 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
907 void PlaySoundLoop(int nr)
909 if (!setup.sound_loops)
912 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
915 void PlaySoundMusic(int nr)
917 if (!setup.sound_music)
920 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
923 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
925 SoundControl snd_ctrl;
927 if (!audio.sound_available ||
928 !audio.sound_enabled ||
929 audio.sound_deactivated)
932 volume = SETUP_SOUND_VOLUME(volume, state);
934 if (volume < SOUND_MIN_VOLUME)
935 volume = SOUND_MIN_VOLUME;
936 else if (volume > SOUND_MAX_VOLUME)
937 volume = SOUND_MAX_VOLUME;
939 if (stereo_position < SOUND_MAX_LEFT)
940 stereo_position = SOUND_MAX_LEFT;
941 else if (stereo_position > SOUND_MAX_RIGHT)
942 stereo_position = SOUND_MAX_RIGHT;
944 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
946 snd_ctrl.active = TRUE;
948 snd_ctrl.volume = volume;
949 snd_ctrl.stereo_position = stereo_position;
950 snd_ctrl.state = state;
952 HandleSoundRequest(snd_ctrl);
957 if (!audio.music_available)
960 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
963 void FadeSound(int nr)
965 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
970 StopSoundExt(-1, SND_CTRL_FADE_ALL);
973 void FadeSoundsAndMusic()
981 if (!audio.music_available)
984 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
987 void StopSound(int nr)
989 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
995 StopSoundExt(-1, SND_CTRL_STOP_ALL);
998 void StopSoundExt(int nr, int state)
1000 SoundControl snd_ctrl;
1002 if (!audio.sound_available)
1005 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
1007 snd_ctrl.active = FALSE;
1009 snd_ctrl.state = state;
1011 HandleSoundRequest(snd_ctrl);
1014 void ExpireSoundLoops(boolean active)
1016 SoundControl snd_ctrl;
1018 if (!audio.sound_available)
1021 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
1023 snd_ctrl.active = active;
1024 snd_ctrl.state = SND_CTRL_EXPIRE_LOOPS;
1026 HandleSoundRequest(snd_ctrl);
1029 static void ReloadCustomSounds()
1031 LoadArtworkConfig(sound_info);
1032 ReloadCustomArtworkList(sound_info);
1035 static void ReloadCustomMusic()
1037 LoadArtworkConfig(music_info);
1038 ReloadCustomArtworkList(music_info);
1040 /* load all music files from directory not defined in "musicinfo.conf" */
1041 LoadCustomMusic_NoConf();
1044 void InitReloadCustomSounds(char *set_identifier)
1046 if (!audio.sound_available)
1049 ReloadCustomSounds();
1052 void InitReloadCustomMusic(char *set_identifier)
1054 if (!audio.music_available)
1057 ReloadCustomMusic();
1060 void FreeSound(void *ptr)
1062 SoundInfo *sound = (SoundInfo *)ptr;
1067 if (sound->data_ptr)
1069 Mix_FreeChunk(sound->data_ptr);
1072 checked_free(sound->source_filename);
1077 void FreeMusic(void *ptr)
1079 MusicInfo *music = (MusicInfo *)ptr;
1084 if (music->data_ptr)
1086 if (music->type == MUS_TYPE_MOD)
1087 Mix_FreeMusic(music->data_ptr);
1089 Mix_FreeChunk(music->data_ptr);
1095 static void FreeAllMusic_NoConf()
1099 if (Music_NoConf == NULL)
1102 for (i = 0; i < num_music_noconf; i++)
1103 FreeMusic(Music_NoConf[i]);
1107 Music_NoConf = NULL;
1108 num_music_noconf = 0;
1111 void FreeAllSounds()
1113 FreeCustomArtworkLists(sound_info);
1118 FreeCustomArtworkLists(music_info);
1119 FreeAllMusic_NoConf();
1122 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
1123 /* ========================================================================= */