From 7bc32b5bc267e1a9c197e9800ec20ed1d51006b7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 5 Jun 2009 16:07:08 +0000 Subject: [PATCH] SDL_mixer: Added decoder enumeration API. --- SDL_mixer.h | 26 +++++++++++++++++++++++++- mixer.c | 42 ++++++++++++++++++++++++++++++++++++++++++ music.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ playwave.c | 23 +++++++++++++++++++++++ 4 files changed, 134 insertions(+), 1 deletion(-) diff --git a/SDL_mixer.h b/SDL_mixer.h index 7f086d42..d355bff8 100644 --- a/SDL_mixer.h +++ b/SDL_mixer.h @@ -41,7 +41,7 @@ extern "C" { */ #define SDL_MIXER_MAJOR_VERSION 1 #define SDL_MIXER_MINOR_VERSION 2 -#define SDL_MIXER_PATCHLEVEL 8 +#define SDL_MIXER_PATCHLEVEL 9 /* This macro can be used to fill a version structure with the compile-time * version of the SDL_mixer library. @@ -146,6 +146,30 @@ extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len); extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk); extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music); +/* Get a list of chunk/music decoders that this build of SDL_mixer provides. + This list can change between builds AND runs of the program, if external + libraries that add functionality become available. + You must successfully call Mix_OpenAudio() before calling these functions. + This API is only available in SDL_mixer 1.2.9 and later. + + // usage... + int i; + const int total = Mix_GetNumChunkDecoders(); + for (i = 0; i < total; i++) + printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); + + Appearing in this list doesn't promise your specific audio file will + decode...but it's handy to know if you have, say, a functioning Timidity + install. + + These return values are static, read-only data; do not modify or free it. + The pointers remain valid until you call Mix_CloseAudio(). +*/ +extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index); +extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index); + /* Find out the music format of a mixer music, or the currently playing music, if 'music' is NULL. */ diff --git a/mixer.c b/mixer.c index ce99abb2..a06450dc 100644 --- a/mixer.c +++ b/mixer.c @@ -98,6 +98,32 @@ extern void music_mixer(void *udata, Uint8 *stream, int len); static void (*mix_music)(void *udata, Uint8 *stream, int len) = music_mixer; static void *music_data = NULL; +/* rcg06042009 report available decoders at runtime. */ +static const char **chunk_decoders = NULL; +static int num_decoders = 0; + +int Mix_NumChunkDecoders(void) +{ + return(num_decoders); +} + +const char *Mix_GetChunkDecoder(int index) +{ + if ((index < 0) || (index >= num_decoders)) { + return NULL; + } + return(chunk_decoders[index]); +} + +static void add_chunk_decoder(const char *decoder) +{ + void *ptr = realloc(chunk_decoders, num_decoders * sizeof (const char **)); + if (ptr == NULL) { + return; /* oh well, go on without it. */ + } + chunk_decoders = (const char **) ptr; + chunk_decoders[num_decoders++] = decoder; +} /* rcg06192001 get linked library's version. */ const SDL_version *Mix_Linked_Version(void) @@ -334,6 +360,17 @@ int Mix_OpenAudio(int frequency, Uint16 format, int nchannels, int chunksize) _Mix_InitEffects(); + /* This list is (currently) decided at build time. */ + add_chunk_decoder("WAVE"); + add_chunk_decoder("AIFF"); + add_chunk_decoder("VOC"); +#ifdef OGG_MUSIC + add_chunk_decoder("OGG"); +#endif +#ifdef FLAC_MUSIC + add_chunk_decoder("FLAC"); +#endif + audio_opened = 1; SDL_PauseAudio(0); return(0); @@ -978,6 +1015,11 @@ void Mix_CloseAudio(void) SDL_CloseAudio(); free(mix_channel); mix_channel = NULL; + + /* rcg06042009 report available decoders at runtime. */ + free(chunk_decoders); + chunk_decoders = NULL; + num_decoders = 0; } --audio_opened; } diff --git a/music.c b/music.c index 14b3fd8c..9dd7fb40 100644 --- a/music.c +++ b/music.c @@ -162,6 +162,33 @@ static Uint16 current_output_format; /* Used to calculate fading steps */ static int ms_per_step; +/* rcg06042009 report available decoders at runtime. */ +static const char **music_decoders = NULL; +static int num_decoders = 0; + +int Mix_NumMusicDecoders(void) +{ + return(num_decoders); +} + +const char *Mix_GetMusicDecoder(int index) +{ + if ((index < 0) || (index >= num_decoders)) { + return NULL; + } + return(music_decoders[index]); +} + +static void add_music_decoder(const char *decoder) +{ + void *ptr = realloc(music_decoders, num_decoders * sizeof (const char **)); + if (ptr == NULL) { + return; /* oh well, go on without it. */ + } + music_decoders = (const char **) ptr; + music_decoders[num_decoders++] = decoder; +} + /* Local low-level functions prototypes */ static void music_internal_initialize_volume(void); static void music_internal_volume(int volume); @@ -387,6 +414,8 @@ int open_music(SDL_AudioSpec *mixer) #ifdef WAV_MUSIC if ( WAVStream_Init(mixer) < 0 ) { ++music_error; + } else { + add_music_decoder("WAVE"); } #endif #if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC) @@ -458,6 +487,7 @@ int open_music(SDL_AudioSpec *mixer) Mix_SetError("%s", MikMod_strerror(MikMod_errno)); ++music_error; } + add_music_decoder("MIKMOD"); #endif #ifdef MID_MUSIC #ifdef USE_TIMIDITY_MIDI @@ -465,6 +495,7 @@ int open_music(SDL_AudioSpec *mixer) if ( Timidity_Init(mixer->freq, mixer->format, mixer->channels, mixer->samples) == 0 ) { timidity_ok = 1; + add_music_decoder("TIMIDITY"); } else { timidity_ok = 0; } @@ -475,22 +506,30 @@ int open_music(SDL_AudioSpec *mixer) if ( native_midi_ok ) #endif native_midi_ok = native_midi_detect(); + if ( native_midi_ok ) + add_music_decoder("NATIVEMIDI"); #endif #endif #ifdef OGG_MUSIC if ( OGG_init(mixer) < 0 ) { ++music_error; + } else { + add_music_decoder("OGG"); } #endif #ifdef FLAC_MUSIC if ( FLAC_init(mixer) < 0 ) { ++music_error; + } else { + add_music_decoder("FLAC"); } #endif #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC) /* Keep a copy of the mixer */ used_mixer = *mixer; + add_music_decoder("MP3"); #endif + music_playing = NULL; music_stopped = 0; if ( music_error ) { @@ -1406,6 +1445,11 @@ void close_music(void) Timidity_Close(); # endif #endif + + /* rcg06042009 report available decoders at runtime. */ + free(music_decoders); + music_decoders = NULL; + num_decoders = 0; } # ifdef LIBMIKMOD_MUSIC diff --git a/playwave.c b/playwave.c index deaa778d..796ba729 100644 --- a/playwave.c +++ b/playwave.c @@ -37,6 +37,7 @@ /* * rcg06132001 various mixer tests. Define the ones you want. */ +#define TEST_MIX_DECODERS /*#define TEST_MIX_VERSIONS*/ /*#define TEST_MIX_CHANNELFINISHED*/ /*#define TEST_MIX_PANNING*/ @@ -81,6 +82,24 @@ static void output_test_warnings(void) static int audio_open = 0; static Mix_Chunk *wave = NULL; +/* rcg06042009 Report available decoders. */ +#if (defined TEST_MIX_DECODERS) +static void report_decoders(void) +{ + int i, total; + + printf("Supported decoders...\n"); + total = Mix_NumChunkDecoders(); + for (i = 0; i < total; i++) { + fprintf(stderr, " - chunk decoder: %s\n", Mix_GetChunkDecoder(i)); + } + + total = Mix_NumMusicDecoders(); + for (i = 0; i < total; i++) { + fprintf(stderr, " - music decoder: %s\n", Mix_GetMusicDecoder(i)); + } +} +#endif /* rcg06192001 Check new Mixer version API. */ #if (defined TEST_MIX_VERSIONS) @@ -417,6 +436,10 @@ int main(int argc, char *argv[]) test_versions(); #endif +#if (defined TEST_MIX_DECODERS) + report_decoders(); +#endif + /* Load the requested wave file */ wave = Mix_LoadWAV(argv[i]); if ( wave == NULL ) {