SDL_mixer: Added decoder enumeration API.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 05 Jun 2009 16:07:08 +0000
changeset 390246b88b9b1f1
parent 389 acb65eaa3f95
child 391 b4bc5ee8b0d6
SDL_mixer: Added decoder enumeration API.
SDL_mixer.h
mixer.c
music.c
playwave.c
     1.1 --- a/SDL_mixer.h	Thu Jun 04 19:12:01 2009 +0000
     1.2 +++ b/SDL_mixer.h	Fri Jun 05 16:07:08 2009 +0000
     1.3 @@ -41,7 +41,7 @@
     1.4  */
     1.5  #define SDL_MIXER_MAJOR_VERSION	1
     1.6  #define SDL_MIXER_MINOR_VERSION	2
     1.7 -#define SDL_MIXER_PATCHLEVEL	8
     1.8 +#define SDL_MIXER_PATCHLEVEL    9
     1.9  
    1.10  /* This macro can be used to fill a version structure with the compile-time
    1.11   * version of the SDL_mixer library.
    1.12 @@ -146,6 +146,30 @@
    1.13  extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk);
    1.14  extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music);
    1.15  
    1.16 +/* Get a list of chunk/music decoders that this build of SDL_mixer provides.
    1.17 +   This list can change between builds AND runs of the program, if external
    1.18 +   libraries that add functionality become available.
    1.19 +   You must successfully call Mix_OpenAudio() before calling these functions.
    1.20 +   This API is only available in SDL_mixer 1.2.9 and later.
    1.21 +
    1.22 +   // usage...
    1.23 +   int i;
    1.24 +   const int total = Mix_GetNumChunkDecoders();
    1.25 +   for (i = 0; i < total; i++)
    1.26 +       printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i));
    1.27 +
    1.28 +   Appearing in this list doesn't promise your specific audio file will
    1.29 +   decode...but it's handy to know if you have, say, a functioning Timidity
    1.30 +   install.
    1.31 +
    1.32 +   These return values are static, read-only data; do not modify or free it.
    1.33 +   The pointers remain valid until you call Mix_CloseAudio().
    1.34 +*/
    1.35 +extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void);
    1.36 +extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index);
    1.37 +extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void);
    1.38 +extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index);
    1.39 +
    1.40  /* Find out the music format of a mixer music, or the currently playing
    1.41     music, if 'music' is NULL.
    1.42  */
     2.1 --- a/mixer.c	Thu Jun 04 19:12:01 2009 +0000
     2.2 +++ b/mixer.c	Fri Jun 05 16:07:08 2009 +0000
     2.3 @@ -98,6 +98,32 @@
     2.4  static void (*mix_music)(void *udata, Uint8 *stream, int len) = music_mixer;
     2.5  static void *music_data = NULL;
     2.6  
     2.7 +/* rcg06042009 report available decoders at runtime. */
     2.8 +static const char **chunk_decoders = NULL;
     2.9 +static int num_decoders = 0;
    2.10 +
    2.11 +int Mix_NumChunkDecoders(void)
    2.12 +{
    2.13 +	return(num_decoders);
    2.14 +}
    2.15 +
    2.16 +const char *Mix_GetChunkDecoder(int index)
    2.17 +{
    2.18 +	if ((index < 0) || (index >= num_decoders)) {
    2.19 +		return NULL;
    2.20 +	}
    2.21 +	return(chunk_decoders[index]);
    2.22 +}
    2.23 +
    2.24 +static void add_chunk_decoder(const char *decoder)
    2.25 +{
    2.26 +	void *ptr = realloc(chunk_decoders, num_decoders * sizeof (const char **));
    2.27 +	if (ptr == NULL) {
    2.28 +		return;  /* oh well, go on without it. */
    2.29 +	}
    2.30 +	chunk_decoders = (const char **) ptr;
    2.31 +	chunk_decoders[num_decoders++] = decoder;
    2.32 +}
    2.33  
    2.34  /* rcg06192001 get linked library's version. */
    2.35  const SDL_version *Mix_Linked_Version(void)
    2.36 @@ -334,6 +360,17 @@
    2.37  
    2.38  	_Mix_InitEffects();
    2.39  
    2.40 +	/* This list is (currently) decided at build time. */
    2.41 +	add_chunk_decoder("WAVE");
    2.42 +	add_chunk_decoder("AIFF");
    2.43 +	add_chunk_decoder("VOC");
    2.44 +#ifdef OGG_MUSIC
    2.45 +	add_chunk_decoder("OGG");
    2.46 +#endif
    2.47 +#ifdef FLAC_MUSIC
    2.48 +	add_chunk_decoder("FLAC");
    2.49 +#endif
    2.50 +
    2.51  	audio_opened = 1;
    2.52  	SDL_PauseAudio(0);
    2.53  	return(0);
    2.54 @@ -978,6 +1015,11 @@
    2.55  			SDL_CloseAudio();
    2.56  			free(mix_channel);
    2.57  			mix_channel = NULL;
    2.58 +
    2.59 +			/* rcg06042009 report available decoders at runtime. */
    2.60 +			free(chunk_decoders);
    2.61 +			chunk_decoders = NULL;
    2.62 +			num_decoders = 0;
    2.63  		}
    2.64  		--audio_opened;
    2.65  	}
     3.1 --- a/music.c	Thu Jun 04 19:12:01 2009 +0000
     3.2 +++ b/music.c	Fri Jun 05 16:07:08 2009 +0000
     3.3 @@ -162,6 +162,33 @@
     3.4  /* Used to calculate fading steps */
     3.5  static int ms_per_step;
     3.6  
     3.7 +/* rcg06042009 report available decoders at runtime. */
     3.8 +static const char **music_decoders = NULL;
     3.9 +static int num_decoders = 0;
    3.10 +
    3.11 +int Mix_NumMusicDecoders(void)
    3.12 +{
    3.13 +	return(num_decoders);
    3.14 +}
    3.15 +
    3.16 +const char *Mix_GetMusicDecoder(int index)
    3.17 +{
    3.18 +	if ((index < 0) || (index >= num_decoders)) {
    3.19 +		return NULL;
    3.20 +	}
    3.21 +	return(music_decoders[index]);
    3.22 +}
    3.23 +
    3.24 +static void add_music_decoder(const char *decoder)
    3.25 +{
    3.26 +	void *ptr = realloc(music_decoders, num_decoders * sizeof (const char **));
    3.27 +	if (ptr == NULL) {
    3.28 +		return;  /* oh well, go on without it. */
    3.29 +	}
    3.30 +    music_decoders = (const char **) ptr;
    3.31 +	music_decoders[num_decoders++] = decoder;
    3.32 +}
    3.33 +
    3.34  /* Local low-level functions prototypes */
    3.35  static void music_internal_initialize_volume(void);
    3.36  static void music_internal_volume(int volume);
    3.37 @@ -387,6 +414,8 @@
    3.38  #ifdef WAV_MUSIC
    3.39  	if ( WAVStream_Init(mixer) < 0 ) {
    3.40  		++music_error;
    3.41 +	} else {
    3.42 +		add_music_decoder("WAVE");
    3.43  	}
    3.44  #endif
    3.45  #if defined(MOD_MUSIC) || defined(LIBMIKMOD_MUSIC)
    3.46 @@ -458,6 +487,7 @@
    3.47  		Mix_SetError("%s", MikMod_strerror(MikMod_errno));
    3.48  		++music_error;
    3.49  	}
    3.50 +	add_music_decoder("MIKMOD");
    3.51  #endif
    3.52  #ifdef MID_MUSIC
    3.53  #ifdef USE_TIMIDITY_MIDI
    3.54 @@ -465,6 +495,7 @@
    3.55  	if ( Timidity_Init(mixer->freq, mixer->format,
    3.56  	                    mixer->channels, mixer->samples) == 0 ) {
    3.57  		timidity_ok = 1;
    3.58 +		add_music_decoder("TIMIDITY");
    3.59  	} else {
    3.60  		timidity_ok = 0;
    3.61  	}
    3.62 @@ -475,22 +506,30 @@
    3.63  	if ( native_midi_ok )
    3.64  #endif
    3.65  		native_midi_ok = native_midi_detect();
    3.66 +	if ( native_midi_ok )
    3.67 +		add_music_decoder("NATIVEMIDI");
    3.68  #endif
    3.69  #endif
    3.70  #ifdef OGG_MUSIC
    3.71  	if ( OGG_init(mixer) < 0 ) {
    3.72  		++music_error;
    3.73 +	} else {
    3.74 +		add_music_decoder("OGG");
    3.75  	}
    3.76  #endif
    3.77  #ifdef FLAC_MUSIC
    3.78  	if ( FLAC_init(mixer) < 0 ) {
    3.79  		++music_error;
    3.80 +	} else {
    3.81 +		add_music_decoder("FLAC");
    3.82  	}
    3.83  #endif
    3.84  #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    3.85  	/* Keep a copy of the mixer */
    3.86  	used_mixer = *mixer;
    3.87 +	add_music_decoder("MP3");
    3.88  #endif
    3.89 +
    3.90  	music_playing = NULL;
    3.91  	music_stopped = 0;
    3.92  	if ( music_error ) {
    3.93 @@ -1406,6 +1445,11 @@
    3.94  	Timidity_Close();
    3.95  # endif
    3.96  #endif
    3.97 +
    3.98 +	/* rcg06042009 report available decoders at runtime. */
    3.99 +	free(music_decoders);
   3.100 +	music_decoders = NULL;
   3.101 +	num_decoders = 0;
   3.102  }
   3.103  
   3.104  # ifdef LIBMIKMOD_MUSIC
     4.1 --- a/playwave.c	Thu Jun 04 19:12:01 2009 +0000
     4.2 +++ b/playwave.c	Fri Jun 05 16:07:08 2009 +0000
     4.3 @@ -37,6 +37,7 @@
     4.4  /*
     4.5   * rcg06132001 various mixer tests. Define the ones you want.
     4.6   */
     4.7 +#define TEST_MIX_DECODERS
     4.8  /*#define TEST_MIX_VERSIONS*/
     4.9  /*#define TEST_MIX_CHANNELFINISHED*/
    4.10  /*#define TEST_MIX_PANNING*/
    4.11 @@ -81,6 +82,24 @@
    4.12  static int audio_open = 0;
    4.13  static Mix_Chunk *wave = NULL;
    4.14  
    4.15 +/* rcg06042009 Report available decoders. */
    4.16 +#if (defined TEST_MIX_DECODERS)
    4.17 +static void report_decoders(void)
    4.18 +{
    4.19 +	int i, total;
    4.20 +
    4.21 +    printf("Supported decoders...\n");
    4.22 +	total = Mix_NumChunkDecoders();
    4.23 +	for (i = 0; i < total; i++) {
    4.24 +		fprintf(stderr, " - chunk decoder: %s\n", Mix_GetChunkDecoder(i));
    4.25 +	}
    4.26 +
    4.27 +	total = Mix_NumMusicDecoders();
    4.28 +	for (i = 0; i < total; i++) {
    4.29 +		fprintf(stderr, " - music decoder: %s\n", Mix_GetMusicDecoder(i));
    4.30 +	}
    4.31 +}
    4.32 +#endif
    4.33  
    4.34  /* rcg06192001 Check new Mixer version API. */
    4.35  #if (defined TEST_MIX_VERSIONS)
    4.36 @@ -417,6 +436,10 @@
    4.37  	test_versions();
    4.38  #endif
    4.39  
    4.40 +#if (defined TEST_MIX_DECODERS)
    4.41 +	report_decoders();
    4.42 +#endif
    4.43 +
    4.44  	/* Load the requested wave file */
    4.45  	wave = Mix_LoadWAV(argv[i]);
    4.46  	if ( wave == NULL ) {