From b540241cf5c24e3b20c1ae5f1043285070941c7e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 8 Nov 2009 16:35:36 +0000 Subject: [PATCH] Sam Lantinga - Sun Nov 8 08:34:48 PST 2009 * Added Mix_Init()/Mix_Quit() to prevent constantly loading and unloading DLLs --- CHANGES | 2 ++ SDL_mixer.h | 17 +++++++++++++++++ dynamic_flac.c | 29 +++++++++++++++++++++------- dynamic_flac.h | 4 ++-- dynamic_mod.c | 12 ++++++++++++ dynamic_mod.h | 4 ++-- dynamic_mp3.c | 12 ++++++++++++ dynamic_mp3.h | 4 ++-- dynamic_ogg.c | 12 ++++++++++++ dynamic_ogg.h | 4 ++-- load_flac.c | 39 +++++++++++++++++++------------------ load_ogg.c | 4 +--- mixer.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ music.c | 5 ++--- music_flac.c | 15 +++++++-------- music_mod.c | 3 +-- music_ogg.c | 4 +--- 17 files changed, 169 insertions(+), 53 deletions(-) diff --git a/CHANGES b/CHANGES index 04046e99..f9c474d4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ 1.2.10: +Sam Lantinga - Sun Nov 8 08:34:48 PST 2009 + * Added Mix_Init()/Mix_Quit() to prevent constantly loading and unloading DLLs Mike Frysinger - 2009-11-05 09:11:43 PST * Check for fork/vfork on any platform, don't just assume it on UNIX Jon Atkins - Thu Nov 5 00:02:50 2009 UTC diff --git a/SDL_mixer.h b/SDL_mixer.h index 320ec8fd..7880f8b8 100644 --- a/SDL_mixer.h +++ b/SDL_mixer.h @@ -65,6 +65,23 @@ extern "C" { */ extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void); +typedef enum +{ + MIX_INIT_FLAC = 0x00000001, + MIX_INIT_MOD = 0x00000002, + MIX_INIT_MP3 = 0x00000004, + MIX_INIT_OGG = 0x00000008 +} MIX_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from MIX_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL Mix_Init(int flags); + +/* Unloads libraries loaded with Mix_Init */ +extern DECLSPEC void SDLCALL Mix_Quit(); + /* The default mixer has 8 simultaneous mixing channels */ #ifndef MIX_CHANNELS diff --git a/dynamic_flac.c b/dynamic_flac.c index d823757b..85c9a7d2 100644 --- a/dynamic_flac.c +++ b/dynamic_flac.c @@ -35,8 +35,8 @@ flac_loader flac = { }; #ifdef FLAC_DYNAMIC - -int Mix_InitFLAC() { +int Mix_InitFLAC() +{ if ( flac.loaded == 0 ) { flac.handle = SDL_LoadObject(FLAC_DYNAMIC); if ( flac.handle == NULL ) { @@ -130,7 +130,8 @@ int Mix_InitFLAC() { return 0; } -void Mix_QuitFLAC() { +void Mix_QuitFLAC() +{ if ( flac.loaded == 0 ) { return; } @@ -140,7 +141,8 @@ void Mix_QuitFLAC() { --flac.loaded; } #else -int Mix_InitFLAC() { +int Mix_InitFLAC() +{ if ( flac.loaded == 0 ) { flac.FLAC__stream_decoder_new = FLAC__stream_decoder_new; flac.FLAC__stream_decoder_delete = FLAC__stream_decoder_delete; @@ -163,7 +165,8 @@ int Mix_InitFLAC() { return 0; } -void Mix_QuitFLAC() { +void Mix_QuitFLAC() +{ if ( flac.loaded == 0 ) { return; } @@ -171,6 +174,18 @@ void Mix_QuitFLAC() { } --flac.loaded; } -#endif // FLAC_DYNAMIC +#endif /* FLAC_DYNAMIC */ + +#else + +int Mix_InitFLAC() +{ + Mix_SetError("FLAC audio is not supported"); + return -1; +} + +void Mix_QuitFLAC() +{ +} -#endif // FLAC_MUSIC +#endif /* FLAC_MUSIC */ diff --git a/dynamic_flac.h b/dynamic_flac.h index 0d8a764d..ae857e3d 100644 --- a/dynamic_flac.h +++ b/dynamic_flac.h @@ -62,7 +62,7 @@ typedef struct { extern flac_loader flac; +#endif /* FLAC_MUSIC */ + extern int Mix_InitFLAC(); extern void Mix_QuitFLAC(); - -#endif // FLAC_MUSIC diff --git a/dynamic_mod.c b/dynamic_mod.c index 0703036a..654bd813 100644 --- a/dynamic_mod.c +++ b/dynamic_mod.c @@ -273,4 +273,16 @@ void Mix_QuitMOD() } #endif /* MOD_DYNAMIC */ +#else + +int Mix_InitMOD() +{ + Mix_SetError("MOD audio is not supported"); + return -1; +} + +void Mix_QuitMOD() +{ +} + #endif /* MOD_MUSIC */ diff --git a/dynamic_mod.h b/dynamic_mod.h index 7294013d..f834c86c 100644 --- a/dynamic_mod.h +++ b/dynamic_mod.h @@ -57,7 +57,7 @@ typedef struct { extern mikmod_loader mikmod; +#endif /* MOD_MUSIC */ + extern int Mix_InitMOD(); extern void Mix_QuitMOD(); - -#endif diff --git a/dynamic_mp3.c b/dynamic_mp3.c index 345a9c17..f5287d89 100644 --- a/dynamic_mp3.c +++ b/dynamic_mp3.c @@ -177,4 +177,16 @@ void Mix_QuitMP3() } #endif /* MP3_DYNAMIC */ +#else + +int Mix_InitMP3() +{ + Mix_SetError("MP3 audio is not supported"); + return -1; +} + +void Mix_QuitMP3() +{ +} + #endif /* MP3_MUSIC */ diff --git a/dynamic_mp3.h b/dynamic_mp3.h index 926f2a2a..9015e86f 100644 --- a/dynamic_mp3.h +++ b/dynamic_mp3.h @@ -43,7 +43,7 @@ typedef struct { extern smpeg_loader smpeg; +#endif /* MUSIC_MP3 */ + extern int Mix_InitMP3(); extern void Mix_QuitMP3(); - -#endif diff --git a/dynamic_ogg.c b/dynamic_ogg.c index f764c878..92664027 100644 --- a/dynamic_ogg.c +++ b/dynamic_ogg.c @@ -125,4 +125,16 @@ void Mix_QuitOgg() } #endif /* OGG_DYNAMIC */ +#else + +int Mix_InitOgg() +{ + Mix_SetError("Ogg Vorbis audio is not supported"); + return -1; +} + +void Mix_QuitOgg() +{ +} + #endif /* OGG_MUSIC */ diff --git a/dynamic_ogg.h b/dynamic_ogg.h index 841995b3..49d35626 100644 --- a/dynamic_ogg.h +++ b/dynamic_ogg.h @@ -44,7 +44,7 @@ typedef struct { extern vorbis_loader vorbis; +#endif /* OGG_MUSIC */ + extern int Mix_InitOgg(); extern void Mix_QuitOgg(); - -#endif diff --git a/load_flac.c b/load_flac.c index 4544192c..26b02606 100644 --- a/load_flac.c +++ b/load_flac.c @@ -208,7 +208,8 @@ static FLAC__StreamDecoderWriteStatus flac_write_load_cb( static void flac_metadata_load_cb( const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, - void *client_data) { + void *client_data) +{ FLAC_SDL_Data *data = (FLAC_SDL_Data *)client_data; FLAC__uint64 total_samples; unsigned bps; @@ -237,7 +238,8 @@ static void flac_metadata_load_cb( static void flac_error_load_cb( const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, - void *client_data) { + void *client_data) +{ // print an SDL error based on the error status switch (status) { case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC: @@ -260,7 +262,8 @@ static void flac_error_load_cb( /* don't call this directly; use Mix_LoadWAV_RW() for now. */ SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc, - SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { + SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +{ FLAC__StreamDecoder *decoder = 0; FLAC__StreamDecoderInitStatus init_status; int was_error = 1; @@ -271,11 +274,11 @@ SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc, FLAC_SDL_Data* client_data; client_data = (FLAC_SDL_Data *)malloc (sizeof (FLAC_SDL_Data)); - if ((!src) || (!audio_buf) || (!audio_len)) /* sanity checks. */ - goto done; + if ((!src) || (!audio_buf) || (!audio_len)) /* sanity checks. */ + goto done; - if (Mix_InitFLAC() < 0) - goto done; + if (!Mix_Init(MIX_INIT_FLAC)) + goto done; if ((decoder = flac.FLAC__stream_decoder_new ()) == NULL) { SDL_SetError ("Unable to allocate FLAC decoder."); @@ -313,25 +316,23 @@ SDL_AudioSpec *Mix_LoadFLAC_RW (SDL_RWops *src, int freesrc, *audio_len &= ~(samplesize - 1); done: - if(was_init && decoder) { + if (was_init && decoder) { flac.FLAC__stream_decoder_finish (decoder); } - if(decoder) { + if (decoder) { flac.FLAC__stream_decoder_delete (decoder); } - if (src) { - if (freesrc) - SDL_RWclose (src); - else - SDL_RWseek (src, 0, SEEK_SET); - } - - if (was_error) - spec = NULL; + if (src) { + if (freesrc) + SDL_RWclose (src); + else + SDL_RWseek (src, 0, SEEK_SET); + } - Mix_QuitFLAC (); + if (was_error) + spec = NULL; return spec; } diff --git a/load_ogg.c b/load_ogg.c index ee07ecbf..9ac072f0 100644 --- a/load_ogg.c +++ b/load_ogg.c @@ -80,7 +80,7 @@ SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc, if ( (!src) || (!audio_buf) || (!audio_len) ) /* sanity checks. */ goto done; - if ( Mix_InitOgg() < 0 ) + if ( !Mix_Init(MIX_INIT_OGG) ) goto done; callbacks.read_func = sdl_read_func; @@ -153,8 +153,6 @@ SDL_AudioSpec *Mix_LoadOGG_RW (SDL_RWops *src, int freesrc, if ( was_error ) spec = NULL; - Mix_QuitOgg(); - return(spec); } /* Mix_LoadOGG_RW */ diff --git a/mixer.c b/mixer.c index 8f84de81..4c0f500a 100644 --- a/mixer.c +++ b/mixer.c @@ -35,6 +35,10 @@ #include "load_voc.h" #include "load_ogg.h" #include "load_flac.h" +#include "dynamic_flac.h" +#include "dynamic_mod.h" +#include "dynamic_mp3.h" +#include "dynamic_ogg.h" #define __MIX_INTERNAL_EFFECT__ #include "effects_internal.h" @@ -134,6 +138,54 @@ const SDL_version *Mix_Linked_Version(void) return(&linked_version); } +static int initialized = 0; + +int Mix_Init(int flags) +{ + int result = 0; + + if ((flags & MIX_INIT_FLAC) && !(initialized & MIX_INIT_FLAC)) { + if (Mix_InitFLAC() == 0) { + result |= MIX_INIT_FLAC; + } + } + if ((flags & MIX_INIT_MOD) && !(initialized & MIX_INIT_MOD)) { + if (Mix_InitMOD() == 0) { + result |= MIX_INIT_MOD; + } + } + if ((flags & MIX_INIT_MP3) && !(initialized & MIX_INIT_MP3)) { + if (Mix_InitMP3() == 0) { + result |= MIX_INIT_MP3; + } + } + if ((flags & MIX_INIT_OGG) && !(initialized & MIX_INIT_OGG)) { + if (Mix_InitOgg() == 0) { + result |= MIX_INIT_OGG; + } + } + initialized |= result; + + return (result); +} + +void Mix_Quit() +{ + if (initialized & MIX_INIT_FLAC) { + Mix_QuitFLAC(); + } + if (initialized & MIX_INIT_MOD) { + Mix_QuitMOD(); + } + if (initialized & MIX_INIT_MP3) { + Mix_QuitMP3(); + } + if (initialized & MIX_INIT_OGG) { + Mix_QuitOgg(); + } + initialized = 0; +} + static int _Mix_remove_all_effects(int channel, effect_info **e); /* diff --git a/music.c b/music.c index 03d55817..00dbd8b1 100644 --- a/music.c +++ b/music.c @@ -510,7 +510,7 @@ Mix_Music *Mix_LoadMUS(const char *file) (ext && MIX_string_equals(ext, "MPEG")) || (magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) || (strncmp((char *)magic, "ID3", 3) == 0) ) { - if ( Mix_InitMP3() == 0 ) { + if ( Mix_Init(MIX_INIT_MP3) ) { SMPEG_Info info; music->type = MUS_MP3; music->data.mp3 = smpeg.SMPEG_new(file, &info, 0); @@ -621,7 +621,6 @@ void Mix_FreeMusic(Mix_Music *music) #ifdef MP3_MUSIC case MUS_MP3: smpeg.SMPEG_delete(music->data.mp3); - Mix_QuitMP3(); break; #endif #ifdef MP3_MAD_MUSIC @@ -1297,7 +1296,7 @@ Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw) #endif #ifdef MP3_MUSIC if ( ( magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) || ( strncmp((char *)magic, "ID3", 3) == 0 ) ) { - if ( Mix_InitMP3() == 0 ) { + if ( Mix_Init(MIX_INIT_MP3) ) { SMPEG_Info info; music->type = MUS_MP3; music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0); diff --git a/music_flac.c b/music_flac.c index 296be51a..1ca0059f 100644 --- a/music_flac.c +++ b/music_flac.c @@ -337,7 +337,7 @@ FLAC_music *FLAC_new_RW(SDL_RWops *rw) music->flac_data.data_len = 0; music->flac_data.data_read = 0; - if (Mix_InitFLAC () >= 0) { + if (Mix_Init(MIX_INIT_FLAC)) { init_stage++; // stage 1! music->flac_decoder = flac.FLAC__stream_decoder_new (); @@ -357,8 +357,14 @@ FLAC_music *FLAC_new_RW(SDL_RWops *rw) if (flac.FLAC__stream_decoder_process_until_end_of_metadata (music->flac_decoder)) { was_error = 0; + } else { + SDL_SetError("FLAC__stream_decoder_process_until_end_of_metadata() failed"); } + } else { + SDL_SetError("FLAC__stream_decoder_init_stream() failed"); } + } else { + SDL_SetError("FLAC__stream_decoder_new() failed"); } } @@ -369,16 +375,11 @@ FLAC_music *FLAC_new_RW(SDL_RWops *rw) case 2: flac.FLAC__stream_decoder_delete( music->flac_decoder ); case 1: - Mix_QuitFLAC(); case 0: free(music); SDL_RWclose(rw); break; } - - SDL_SetError ("There was an error in stage [%d] of FLAC init.", - init_stage); - return NULL; } } @@ -559,8 +560,6 @@ void FLAC_delete(FLAC_music *music) } free (music); - - Mix_QuitFLAC (); } } diff --git a/music_mod.c b/music_mod.c index 7682ae33..cffada8b 100644 --- a/music_mod.c +++ b/music_mod.c @@ -53,7 +53,7 @@ int MOD_init(SDL_AudioSpec *mixerfmt) { CHAR *list; - if ( Mix_InitMOD() < 0 ) { + if ( !Mix_Init(MIX_INIT_MOD) ) { return -1; } @@ -132,7 +132,6 @@ int MOD_init(SDL_AudioSpec *mixerfmt) void MOD_exit(void) { mikmod.MikMod_Exit(); - Mix_QuitMOD(); } /* Set the volume for a MOD stream */ diff --git a/music_ogg.c b/music_ogg.c index e6ab2614..203352f9 100644 --- a/music_ogg.c +++ b/music_ogg.c @@ -105,13 +105,12 @@ OGG_music *OGG_new_RW(SDL_RWops *rw) OGG_setvolume(music, MIX_MAX_VOLUME); music->section = -1; - if ( Mix_InitOgg() < 0 ) { + if ( !Mix_Init(MIX_INIT_OGG) ) { return(NULL); } if ( vorbis.ov_open_callbacks(rw, &music->vf, NULL, 0, callbacks) < 0 ) { free(music); SDL_RWclose(rw); - Mix_QuitOgg(); SDL_SetError("Not an Ogg Vorbis audio stream"); return(NULL); } @@ -224,7 +223,6 @@ void OGG_delete(OGG_music *music) } vorbis.ov_clear(&music->vf); free(music); - Mix_QuitOgg(); } }