Skip to content
Permalink
Browse files

SDL_mixer: Added decoder enumeration API.

  • Loading branch information
icculus committed Jun 5, 2009
1 parent 9a064ae commit 7bc32b5bc267e1a9c197e9800ec20ed1d51006b7
Showing with 134 additions and 1 deletion.
  1. +25 −1 SDL_mixer.h
  2. +42 −0 mixer.c
  3. +44 −0 music.c
  4. +23 −0 playwave.c
@@ -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.
*/
42 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;
}
44 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,13 +487,15 @@ 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
samplesize = mixer->size / mixer->samples;
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
@@ -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 ) {

0 comments on commit 7bc32b5

Please sign in to comment.