forked from pool/SDL2_mixer
469 lines
14 KiB
Diff
469 lines
14 KiB
Diff
|
|
||
|
# HG changeset patch
|
||
|
# User Sam Lantinga <slouken@libsdl.org>
|
||
|
# Date 1508906510 25200
|
||
|
# Node ID 7fa15b556953502e11c911d104450ae02c807c84
|
||
|
# Parent 7d6df0a13bd02a3eb7fbdf64eca628913d46c291
|
||
|
Only load music interfaces that are explicitly initialized or needed for audio content
|
||
|
|
||
|
diff -r 7d6df0a13bd0 -r 7fa15b556953 mixer.c
|
||
|
--- a/mixer.c Mon Oct 23 12:40:10 2017 -0700
|
||
|
+++ b/mixer.c Tue Oct 24 21:41:50 2017 -0700
|
||
|
@@ -118,9 +118,19 @@
|
||
|
return SDL_FALSE;
|
||
|
}
|
||
|
|
||
|
-static void add_chunk_decoder(const char *decoder)
|
||
|
+void add_chunk_decoder(const char *decoder)
|
||
|
{
|
||
|
- void *ptr = SDL_realloc((void *)chunk_decoders, (num_decoders + 1) * sizeof (const char *));
|
||
|
+ int i;
|
||
|
+ void *ptr;
|
||
|
+
|
||
|
+ /* Check to see if we already have this decoder */
|
||
|
+ for (i = 0; i < num_decoders; ++i) {
|
||
|
+ if (SDL_strcmp(chunk_decoders[i], decoder) == 0) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ ptr = SDL_realloc((void *)chunk_decoders, (num_decoders + 1) * sizeof (const char *));
|
||
|
if (ptr == NULL) {
|
||
|
return; /* oh well, go on without it. */
|
||
|
}
|
||
|
@@ -140,44 +150,47 @@
|
||
|
{
|
||
|
int result = 0;
|
||
|
|
||
|
- load_music();
|
||
|
-
|
||
|
if (flags & MIX_INIT_FLAC) {
|
||
|
- if (has_music(MUS_FLAC)) {
|
||
|
+ if (load_music_type(MUS_FLAC)) {
|
||
|
+ open_music_type(MUS_FLAC);
|
||
|
result |= MIX_INIT_FLAC;
|
||
|
} else {
|
||
|
Mix_SetError("FLAC support not available");
|
||
|
}
|
||
|
}
|
||
|
if (flags & MIX_INIT_MOD) {
|
||
|
- if (has_music(MUS_MOD)) {
|
||
|
+ if (load_music_type(MUS_MOD)) {
|
||
|
+ open_music_type(MUS_MOD);
|
||
|
result |= MIX_INIT_MOD;
|
||
|
} else {
|
||
|
Mix_SetError("MOD support not available");
|
||
|
}
|
||
|
}
|
||
|
if (flags & MIX_INIT_MP3) {
|
||
|
- if (has_music(MUS_MP3)) {
|
||
|
+ if (load_music_type(MUS_MP3)) {
|
||
|
+ open_music_type(MUS_MP3);
|
||
|
result |= MIX_INIT_MP3;
|
||
|
} else {
|
||
|
Mix_SetError("MP3 support not available");
|
||
|
}
|
||
|
}
|
||
|
if (flags & MIX_INIT_OGG) {
|
||
|
- if (has_music(MUS_OGG)) {
|
||
|
+ if (load_music_type(MUS_OGG)) {
|
||
|
+ open_music_type(MUS_OGG);
|
||
|
result |= MIX_INIT_OGG;
|
||
|
} else {
|
||
|
Mix_SetError("OGG support not available");
|
||
|
}
|
||
|
}
|
||
|
if (flags & MIX_INIT_MID) {
|
||
|
- if (has_music(MUS_MID)) {
|
||
|
+ if (load_music_type(MUS_MID)) {
|
||
|
+ open_music_type(MUS_MID);
|
||
|
result |= MIX_INIT_MID;
|
||
|
} else {
|
||
|
Mix_SetError("MIDI support not available");
|
||
|
}
|
||
|
}
|
||
|
- return (result);
|
||
|
+ return result;
|
||
|
}
|
||
|
|
||
|
void Mix_Quit()
|
||
|
@@ -400,13 +413,6 @@
|
||
|
PrintFormat("Audio device", &mixer);
|
||
|
#endif
|
||
|
|
||
|
- /* Initialize the music players */
|
||
|
- load_music();
|
||
|
- if (open_music(&mixer) < 0) {
|
||
|
- SDL_CloseAudioDevice(audio_device);
|
||
|
- return(-1);
|
||
|
- }
|
||
|
-
|
||
|
num_channels = MIX_CHANNELS;
|
||
|
mix_channel = (struct _Mix_Channel *) SDL_malloc(num_channels * sizeof(struct _Mix_Channel));
|
||
|
|
||
|
@@ -431,21 +437,9 @@
|
||
|
add_chunk_decoder("WAVE");
|
||
|
add_chunk_decoder("AIFF");
|
||
|
add_chunk_decoder("VOC");
|
||
|
- if (has_music(MUS_MOD)) {
|
||
|
- add_chunk_decoder("MOD");
|
||
|
- }
|
||
|
- if (has_music(MUS_MID)) {
|
||
|
- add_chunk_decoder("MID");
|
||
|
- }
|
||
|
- if (has_music(MUS_OGG)) {
|
||
|
- add_chunk_decoder("OGG");
|
||
|
- }
|
||
|
- if (has_music(MUS_MP3)) {
|
||
|
- add_chunk_decoder("MP3");
|
||
|
- }
|
||
|
- if (has_music(MUS_FLAC)) {
|
||
|
- add_chunk_decoder("FLAC");
|
||
|
- }
|
||
|
+
|
||
|
+ /* Initialize the music players */
|
||
|
+ open_music(&mixer);
|
||
|
|
||
|
audio_opened = 1;
|
||
|
SDL_PauseAudioDevice(audio_device, 0);
|
||
|
@@ -536,6 +530,10 @@
|
||
|
int count = 0;
|
||
|
int fragment_size;
|
||
|
|
||
|
+ if (!load_music_type(music_type) || !open_music_type(music_type)) {
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+
|
||
|
*spec = mixer;
|
||
|
|
||
|
/* Use fragments sized on full audio frame boundaries - this'll do */
|
||
|
@@ -544,6 +542,9 @@
|
||
|
start = SDL_RWtell(src);
|
||
|
for (i = 0; i < get_num_music_interfaces(); ++i) {
|
||
|
interface = get_music_interface(i);
|
||
|
+ if (!interface->opened) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
if (interface->type != music_type) {
|
||
|
continue;
|
||
|
}
|
||
|
diff -r 7d6df0a13bd0 -r 7fa15b556953 mixer.h
|
||
|
--- a/mixer.h Mon Oct 23 12:40:10 2017 -0700
|
||
|
+++ b/mixer.h Tue Oct 24 21:41:50 2017 -0700
|
||
|
@@ -23,4 +23,6 @@
|
||
|
extern void Mix_LockAudio(void);
|
||
|
extern void Mix_UnlockAudio(void);
|
||
|
|
||
|
+extern void add_chunk_decoder(const char *decoder);
|
||
|
+
|
||
|
/* vi: set ts=4 sw=4 expandtab: */
|
||
|
diff -r 7d6df0a13bd0 -r 7fa15b556953 music.c
|
||
|
--- a/music.c Mon Oct 23 12:40:10 2017 -0700
|
||
|
+++ b/music.c Tue Oct 24 21:41:50 2017 -0700
|
||
|
@@ -42,6 +42,9 @@
|
||
|
#include "music_flac.h"
|
||
|
#include "native_midi/native_midi.h"
|
||
|
|
||
|
+/* Set this hint to true if you want verbose logging of music interfaces */
|
||
|
+#define SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES \
|
||
|
+ "SDL_MIXER_DEBUG_MUSIC_INTERFACES"
|
||
|
|
||
|
char *music_cmd = NULL;
|
||
|
static SDL_bool music_active = SDL_TRUE;
|
||
|
@@ -135,7 +138,17 @@
|
||
|
|
||
|
static void add_music_decoder(const char *decoder)
|
||
|
{
|
||
|
- void *ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
|
||
|
+ void *ptr;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ /* Check to see if we already have this decoder */
|
||
|
+ for (i = 0; i < num_decoders; ++i) {
|
||
|
+ if (SDL_strcmp(music_decoders[i], decoder) == 0) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
|
||
|
if (ptr == NULL) {
|
||
|
return; /* oh well, go on without it. */
|
||
|
}
|
||
|
@@ -252,28 +265,123 @@
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-/* Load the music interface libraries */
|
||
|
-int load_music(void)
|
||
|
+/* Load the music interface libraries for a given music type */
|
||
|
+SDL_bool load_music_type(Mix_MusicType type)
|
||
|
{
|
||
|
- char hint[128];
|
||
|
-
|
||
|
- int i;
|
||
|
+ int i, loaded = 0;
|
||
|
for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
|
||
|
Mix_MusicInterface *interface = s_music_interfaces[i];
|
||
|
- if (interface->loaded) {
|
||
|
+ if (interface->type != type) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ if (!interface->loaded) {
|
||
|
+ char hint[64];
|
||
|
+ SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
|
||
|
+ if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (interface->Load && interface->Load() < 0) {
|
||
|
+ if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
|
||
|
+ SDL_Log("Couldn't load %s: %s\n", interface->tag, Mix_GetError());
|
||
|
+ }
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ interface->loaded = SDL_TRUE;
|
||
|
+ }
|
||
|
+ ++loaded;
|
||
|
+ }
|
||
|
+ return (loaded > 0) ? SDL_TRUE : SDL_FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/* Open the music interfaces for a given music type */
|
||
|
+SDL_bool open_music_type(Mix_MusicType type)
|
||
|
+{
|
||
|
+ int i, opened = 0;
|
||
|
+ SDL_bool use_native_midi = SDL_FALSE;
|
||
|
+
|
||
|
+ if (!music_spec.format) {
|
||
|
+ /* Music isn't opened yet */
|
||
|
+ return SDL_FALSE;
|
||
|
+ }
|
||
|
+
|
||
|
+#ifdef MUSIC_MID_NATIVE
|
||
|
+ if (type == MUS_MID && SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
|
||
|
+ use_native_midi = SDL_TRUE;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
+ for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
|
||
|
+ Mix_MusicInterface *interface = s_music_interfaces[i];
|
||
|
+ if (!interface->loaded) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ if (type != MUS_NONE && interface->type != type) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
|
||
|
- if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
|
||
|
+ if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- if (!interface->Load || interface->Load() == 0) {
|
||
|
- interface->loaded = SDL_TRUE;
|
||
|
+ if (!interface->opened) {
|
||
|
+ if (interface->Open && interface->Open(&music_spec) < 0) {
|
||
|
+ if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
|
||
|
+ SDL_Log("Couldn't open %s: %s\n", interface->tag, Mix_GetError());
|
||
|
+ }
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ interface->opened = SDL_TRUE;
|
||
|
+ add_music_decoder(interface->tag);
|
||
|
}
|
||
|
+ ++opened;
|
||
|
}
|
||
|
- return 0;
|
||
|
+
|
||
|
+ if (has_music(MUS_MOD)) {
|
||
|
+ add_music_decoder("MOD");
|
||
|
+ add_chunk_decoder("MOD");
|
||
|
+ }
|
||
|
+ if (has_music(MUS_MID)) {
|
||
|
+ add_music_decoder("MIDI");
|
||
|
+ add_chunk_decoder("MID");
|
||
|
+ }
|
||
|
+ if (has_music(MUS_OGG)) {
|
||
|
+ add_music_decoder("OGG");
|
||
|
+ add_chunk_decoder("OGG");
|
||
|
+ }
|
||
|
+ if (has_music(MUS_MP3)) {
|
||
|
+ add_music_decoder("MP3");
|
||
|
+ add_chunk_decoder("MP3");
|
||
|
+ }
|
||
|
+ if (has_music(MUS_FLAC)) {
|
||
|
+ add_music_decoder("FLAC");
|
||
|
+ add_chunk_decoder("FLAC");
|
||
|
+ }
|
||
|
+
|
||
|
+ return (opened > 0) ? SDL_TRUE : SDL_FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/* Initialize the music interfaces with a certain desired audio format */
|
||
|
+void open_music(const SDL_AudioSpec *spec)
|
||
|
+{
|
||
|
+#ifdef MIX_INIT_SOUNDFONT_PATHS
|
||
|
+ if (!soundfont_paths) {
|
||
|
+ soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
+ /* Load the music interfaces that don't have explicit initialization */
|
||
|
+ load_music_type(MUS_CMD);
|
||
|
+ load_music_type(MUS_WAV);
|
||
|
+
|
||
|
+ /* Open all the interfaces that are loaded */
|
||
|
+ music_spec = *spec;
|
||
|
+ open_music_type(MUS_NONE);
|
||
|
+
|
||
|
+ Mix_VolumeMusic(MIX_MAX_VOLUME);
|
||
|
+
|
||
|
+ /* Calculate the number of ms for each callback */
|
||
|
+ ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
|
||
|
}
|
||
|
|
||
|
/* Return SDL_TRUE if the music type is available */
|
||
|
@@ -292,60 +400,6 @@
|
||
|
return SDL_FALSE;
|
||
|
}
|
||
|
|
||
|
-/* Initialize the music interfaces with a certain desired audio format */
|
||
|
-int open_music(const SDL_AudioSpec *spec)
|
||
|
-{
|
||
|
- int i;
|
||
|
- SDL_bool use_native_midi = SDL_FALSE;
|
||
|
-
|
||
|
-#ifdef MIX_INIT_SOUNDFONT_PATHS
|
||
|
- if (!soundfont_paths) {
|
||
|
- soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
|
||
|
- }
|
||
|
-#endif
|
||
|
-
|
||
|
-
|
||
|
-#ifdef MUSIC_MID_NATIVE
|
||
|
- if (SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
|
||
|
- use_native_midi = SDL_TRUE;
|
||
|
- }
|
||
|
-#endif
|
||
|
-
|
||
|
- music_spec = *spec;
|
||
|
- for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
|
||
|
- Mix_MusicInterface *interface = s_music_interfaces[i];
|
||
|
- if (!interface->loaded) {
|
||
|
- continue;
|
||
|
- }
|
||
|
-
|
||
|
- if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
|
||
|
- continue;
|
||
|
- }
|
||
|
-
|
||
|
- if (!interface->Open || interface->Open(spec) == 0) {
|
||
|
- interface->opened = SDL_TRUE;
|
||
|
- add_music_decoder(interface->tag);
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- if (has_music(MUS_MOD)) {
|
||
|
- add_music_decoder("MOD");
|
||
|
- }
|
||
|
- if (has_music(MUS_MID)) {
|
||
|
- add_music_decoder("MIDI");
|
||
|
- }
|
||
|
- if (has_music(MUS_MP3)) {
|
||
|
- add_music_decoder("MP3");
|
||
|
- }
|
||
|
-
|
||
|
- Mix_VolumeMusic(MIX_MAX_VOLUME);
|
||
|
-
|
||
|
- /* Calculate the number of ms for each callback */
|
||
|
- ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
Mix_MusicType detect_music_type_from_magic(const Uint8 *magic)
|
||
|
{
|
||
|
/* Ogg Vorbis files have the magic four bytes "OggS" */
|
||
|
@@ -509,32 +563,34 @@
|
||
|
|
||
|
Mix_ClearError();
|
||
|
|
||
|
- for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
|
||
|
- Mix_MusicInterface *interface = s_music_interfaces[i];
|
||
|
- if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
|
||
|
- continue;
|
||
|
+ if (load_music_type(type) && open_music_type(type)) {
|
||
|
+ for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
|
||
|
+ Mix_MusicInterface *interface = s_music_interfaces[i];
|
||
|
+ if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ context = interface->CreateFromRW(src, freesrc);
|
||
|
+ if (context) {
|
||
|
+ /* Allocate memory for the music structure */
|
||
|
+ Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
|
||
|
+ if (music == NULL) {
|
||
|
+ interface->Delete(context);
|
||
|
+ Mix_SetError("Out of memory");
|
||
|
+ return NULL;
|
||
|
+ }
|
||
|
+ music->interface = interface;
|
||
|
+ music->context = context;
|
||
|
+
|
||
|
+ if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
|
||
|
+ SDL_Log("Loaded music with %s\n", interface->tag);
|
||
|
+ }
|
||
|
+ return music;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Reset the stream for the next decoder */
|
||
|
+ SDL_RWseek(src, start, RW_SEEK_SET);
|
||
|
}
|
||
|
-
|
||
|
- context = interface->CreateFromRW(src, freesrc);
|
||
|
- if (context) {
|
||
|
- /* Allocate memory for the music structure */
|
||
|
- Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
|
||
|
- if (music == NULL) {
|
||
|
- interface->Delete(context);
|
||
|
- Mix_SetError("Out of memory");
|
||
|
- return NULL;
|
||
|
- }
|
||
|
- music->interface = interface;
|
||
|
- music->context = context;
|
||
|
-#ifdef DEBUG_MUSIC
|
||
|
- /* This would be useful to expose via an API */
|
||
|
- SDL_Log("Music playing with %s\n", interface->tag);
|
||
|
-#endif
|
||
|
- return music;
|
||
|
- }
|
||
|
-
|
||
|
- /* Reset the stream for the next decoder */
|
||
|
- SDL_RWseek(src, start, RW_SEEK_SET);
|
||
|
}
|
||
|
|
||
|
if (!*Mix_GetError()) {
|
||
|
diff -r 7d6df0a13bd0 -r 7fa15b556953 music.h
|
||
|
--- a/music.h Mon Oct 23 12:40:10 2017 -0700
|
||
|
+++ b/music.h Tue Oct 24 21:41:50 2017 -0700
|
||
|
@@ -103,12 +103,13 @@
|
||
|
} Mix_MusicInterface;
|
||
|
|
||
|
|
||
|
-extern int load_music(void);
|
||
|
-extern Mix_MusicType detect_music_type_from_magic(const Uint8 *magic);
|
||
|
extern int get_num_music_interfaces(void);
|
||
|
extern Mix_MusicInterface *get_music_interface(int index);
|
||
|
+extern Mix_MusicType detect_music_type_from_magic(const Uint8 *magic);
|
||
|
+extern SDL_bool load_music_type(Mix_MusicType type);
|
||
|
+extern SDL_bool open_music_type(Mix_MusicType type);
|
||
|
extern SDL_bool has_music(Mix_MusicType type);
|
||
|
-extern int open_music(const SDL_AudioSpec *spec);
|
||
|
+extern void open_music(const SDL_AudioSpec *spec);
|
||
|
extern int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
|
||
|
int (*GetSome)(void *context, void *data, int bytes, SDL_bool *done));
|
||
|
extern void SDLCALL music_mixer(void *udata, Uint8 *stream, int len);
|
||
|
|