music.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 23:28:23 -0500
changeset 528 bc0dfe8ae026
parent 527 1eddea51f162
child 529 9ca74f21d466
permissions -rw-r--r--
Backed out changeset 1eddea51f162
     1 /*
     2   SDL_mixer:  An audio mixer library based on the SDL library
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* $Id$ */
    23 
    24 #include <stdlib.h>
    25 #include <string.h>
    26 #include <ctype.h>
    27 #include <assert.h>
    28 #include "SDL_endian.h"
    29 #include "SDL_audio.h"
    30 #include "SDL_timer.h"
    31 
    32 #include "SDL_mixer.h"
    33 
    34 #ifdef CMD_MUSIC
    35 #include "music_cmd.h"
    36 #endif
    37 #ifdef WAV_MUSIC
    38 #include "wavestream.h"
    39 #endif
    40 #ifdef MODPLUG_MUSIC
    41 #include "music_modplug.h"
    42 #endif
    43 #ifdef MOD_MUSIC
    44 #include "music_mod.h"
    45 #endif
    46 #ifdef MID_MUSIC
    47 #  ifdef USE_TIMIDITY_MIDI
    48 #    include "timidity.h"
    49 #  endif
    50 #  ifdef USE_FLUIDSYNTH_MIDI
    51 #    include "fluidsynth.h"
    52 #  endif
    53 #  ifdef USE_NATIVE_MIDI
    54 #    include "native_midi.h"
    55 #  endif
    56 #endif
    57 #ifdef OGG_MUSIC
    58 #include "music_ogg.h"
    59 #endif
    60 #ifdef MP3_MUSIC
    61 #include "dynamic_mp3.h"
    62 #endif
    63 #ifdef MP3_MAD_MUSIC
    64 #include "music_mad.h"
    65 #endif
    66 #ifdef FLAC_MUSIC
    67 #include "music_flac.h"
    68 #endif
    69 
    70 #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
    71 static SDL_AudioSpec used_mixer;
    72 #endif
    73 
    74 
    75 int volatile music_active = 1;
    76 static int volatile music_stopped = 0;
    77 static int music_loops = 0;
    78 static char *music_cmd = NULL;
    79 static Mix_Music * volatile music_playing = NULL;
    80 static int music_volume = MIX_MAX_VOLUME;
    81 
    82 struct _Mix_Music {
    83 	Mix_MusicType type;
    84 	union {
    85 #ifdef CMD_MUSIC
    86 		MusicCMD *cmd;
    87 #endif
    88 #ifdef WAV_MUSIC
    89 		WAVStream *wave;
    90 #endif
    91 #ifdef MODPLUG_MUSIC
    92 		modplug_data *modplug;
    93 #endif
    94 #ifdef MOD_MUSIC
    95 		struct MODULE *module;
    96 #endif
    97 #ifdef MID_MUSIC
    98 #ifdef USE_TIMIDITY_MIDI
    99 		MidiSong *midi;
   100 #endif
   101 #ifdef USE_FLUIDSYNTH_MIDI
   102 		FluidSynthMidiSong *fluidsynthmidi;
   103 #endif
   104 #ifdef USE_NATIVE_MIDI
   105 		NativeMidiSong *nativemidi;
   106 #endif
   107 #endif
   108 #ifdef OGG_MUSIC
   109 		OGG_music *ogg;
   110 #endif
   111 #ifdef MP3_MUSIC
   112 		SMPEG *mp3;
   113 #endif
   114 #ifdef MP3_MAD_MUSIC
   115 		mad_data *mp3_mad;
   116 #endif
   117 #ifdef FLAC_MUSIC
   118 		FLAC_music *flac;
   119 #endif
   120 	} data;
   121 	Mix_Fading fading;
   122 	int fade_step;
   123 	int fade_steps;
   124 	int error;
   125 };
   126 #ifdef MID_MUSIC
   127 #ifdef USE_TIMIDITY_MIDI
   128 static int timidity_ok;
   129 static int samplesize;
   130 #endif
   131 #ifdef USE_FLUIDSYNTH_MIDI
   132 static int fluidsynth_ok;
   133 #endif
   134 #ifdef USE_NATIVE_MIDI
   135 static int native_midi_ok;
   136 #endif
   137 #endif
   138 
   139 /* Used to calculate fading steps */
   140 static int ms_per_step;
   141 
   142 /* rcg06042009 report available decoders at runtime. */
   143 static const char **music_decoders = NULL;
   144 static int num_decoders = 0;
   145 
   146 /* Semicolon-separated SoundFont paths */
   147 #ifdef MID_MUSIC
   148 char* soundfont_paths = NULL;
   149 #endif
   150 
   151 int Mix_GetNumMusicDecoders(void)
   152 {
   153 	return(num_decoders);
   154 }
   155 
   156 const char *Mix_GetMusicDecoder(int index)
   157 {
   158 	if ((index < 0) || (index >= num_decoders)) {
   159 		return NULL;
   160 	}
   161 	return(music_decoders[index]);
   162 }
   163 
   164 static void add_music_decoder(const char *decoder)
   165 {
   166 	void *ptr = realloc(music_decoders, (num_decoders + 1) * sizeof (const char **));
   167 	if (ptr == NULL) {
   168 		return;  /* oh well, go on without it. */
   169 	}
   170 	music_decoders = (const char **) ptr;
   171 	music_decoders[num_decoders++] = decoder;
   172 }
   173 
   174 /* Local low-level functions prototypes */
   175 static void music_internal_initialize_volume(void);
   176 static void music_internal_volume(int volume);
   177 static int  music_internal_play(Mix_Music *music, double position);
   178 static int  music_internal_position(double position);
   179 static int  music_internal_playing();
   180 static void music_internal_halt(void);
   181 
   182 
   183 /* Support for hooking when the music has finished */
   184 static void (*music_finished_hook)(void) = NULL;
   185 
   186 void Mix_HookMusicFinished(void (*music_finished)(void))
   187 {
   188 	SDL_LockAudio();
   189 	music_finished_hook = music_finished;
   190 	SDL_UnlockAudio();
   191 }
   192 
   193 
   194 /* If music isn't playing, halt it if no looping is required, restart it */
   195 /* otherwhise. NOP if the music is playing */
   196 static int music_halt_or_loop (void)
   197 {
   198 	/* Restart music if it has to loop */
   199 	
   200 	if (!music_internal_playing()) 
   201 	{
   202 		/* Restart music if it has to loop at a high level */
   203 		if (music_loops && --music_loops)
   204 		{
   205 			Mix_Fading current_fade = music_playing->fading;
   206 			music_internal_play(music_playing, 0.0);
   207 			music_playing->fading = current_fade;
   208 		} 
   209 		else 
   210 		{
   211 			music_internal_halt();
   212 			if (music_finished_hook)
   213 				music_finished_hook();
   214 			
   215 			return 0;
   216 		}
   217 	}
   218 	
   219 	return 1;
   220 }
   221 
   222 
   223 
   224 /* Mixing function */
   225 void music_mixer(void *udata, Uint8 *stream, int len)
   226 {
   227 	int left = 0;
   228 
   229 	if ( music_playing && music_active ) {
   230 		/* Handle fading */
   231 		if ( music_playing->fading != MIX_NO_FADING ) {
   232 			if ( music_playing->fade_step++ < music_playing->fade_steps ) {
   233 				int volume;
   234 				int fade_step = music_playing->fade_step;
   235 				int fade_steps = music_playing->fade_steps;
   236 
   237 				if ( music_playing->fading == MIX_FADING_OUT ) {
   238 					volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
   239 				} else { /* Fading in */
   240 					volume = (music_volume * fade_step) / fade_steps;
   241 				}
   242 				music_internal_volume(volume);
   243 			} else {
   244 				if ( music_playing->fading == MIX_FADING_OUT ) {
   245 					music_internal_halt();
   246 					if ( music_finished_hook ) {
   247 						music_finished_hook();
   248 					}
   249 					return;
   250 				}
   251 				music_playing->fading = MIX_NO_FADING;
   252 			}
   253 		}
   254 		
   255 		music_halt_or_loop();
   256 		if (!music_internal_playing())
   257 			return;
   258 
   259 		switch (music_playing->type) {
   260 #ifdef CMD_MUSIC
   261 			case MUS_CMD:
   262 				/* The playing is done externally */
   263 				break;
   264 #endif
   265 #ifdef WAV_MUSIC
   266 			case MUS_WAV:
   267 				left = WAVStream_PlaySome(stream, len);
   268 				break;
   269 #endif
   270 #ifdef MODPLUG_MUSIC
   271 			case MUS_MODPLUG:
   272 				left = modplug_playAudio(music_playing->data.modplug, stream, len);
   273 				break;
   274 #endif
   275 #ifdef MOD_MUSIC
   276 			case MUS_MOD:
   277 				left = MOD_playAudio(music_playing->data.module, stream, len);
   278 				break;
   279 #endif
   280 #ifdef MID_MUSIC
   281 			case MUS_MID:
   282 #ifdef USE_FLUIDSYNTH_MIDI
   283 				if ( fluidsynth_ok ) {
   284 					fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
   285 					goto skip;
   286 				}
   287 #endif
   288 #ifdef USE_TIMIDITY_MIDI
   289 				if ( timidity_ok ) {
   290 					int samples = len / samplesize;
   291   					Timidity_PlaySome(stream, samples);
   292 					goto skip;
   293 				}
   294 #endif
   295 				break;
   296 #endif
   297 #ifdef OGG_MUSIC
   298 			case MUS_OGG:
   299 				
   300 				left = OGG_playAudio(music_playing->data.ogg, stream, len);
   301 				break;
   302 #endif
   303 #ifdef FLAC_MUSIC
   304 			case MUS_FLAC:
   305 				left = FLAC_playAudio(music_playing->data.flac, stream, len);
   306 				break;
   307 #endif
   308 #ifdef MP3_MUSIC
   309 			case MUS_MP3:
   310 				left = (len - smpeg.SMPEG_playAudio(music_playing->data.mp3, stream, len));
   311 				break;
   312 #endif
   313 #ifdef MP3_MAD_MUSIC
   314 			case MUS_MP3_MAD:
   315 				left = mad_getSamples(music_playing->data.mp3_mad, stream, len);
   316 				break;
   317 #endif
   318 			default:
   319 				/* Unknown music type?? */
   320 				break;
   321 		}
   322 	}
   323 
   324 skip:
   325 	/* Handle seamless music looping */
   326 	if (left > 0 && left < len) {
   327 		music_halt_or_loop();
   328 		if (music_internal_playing())
   329 			music_mixer(udata, stream+(len-left), left);
   330 	}
   331 }
   332 
   333 /* Initialize the music players with a certain desired audio format */
   334 int open_music(SDL_AudioSpec *mixer)
   335 {
   336 #ifdef WAV_MUSIC
   337 	if ( WAVStream_Init(mixer) == 0 ) {
   338 		add_music_decoder("WAVE");
   339 	}
   340 #endif
   341 #ifdef MODPLUG_MUSIC
   342 	if ( modplug_init(mixer) == 0 ) {
   343 		add_music_decoder("MODPLUG");
   344 	}
   345 #endif
   346 #ifdef MOD_MUSIC
   347 	if ( MOD_init(mixer) == 0 ) {
   348 		add_music_decoder("MIKMOD");
   349 	}
   350 #endif
   351 #ifdef MID_MUSIC
   352 #ifdef USE_TIMIDITY_MIDI
   353 	samplesize = mixer->size / mixer->samples;
   354 	if ( Timidity_Init(mixer->freq, mixer->format,
   355 	                    mixer->channels, mixer->samples) == 0 ) {
   356 		timidity_ok = 1;
   357 		add_music_decoder("TIMIDITY");
   358 	} else {
   359 		timidity_ok = 0;
   360 	}
   361 #endif
   362 #ifdef USE_FLUIDSYNTH_MIDI
   363 	if ( fluidsynth_init(mixer) == 0 ) {
   364 		fluidsynth_ok = 1;
   365 		add_music_decoder("FLUIDSYNTH");
   366 	} else {
   367 		fluidsynth_ok = 0;
   368 	}
   369 #endif
   370 #ifdef USE_NATIVE_MIDI
   371 #ifdef USE_FLUIDSYNTH_MIDI
   372 	native_midi_ok = !fluidsynth_ok;
   373 	if ( native_midi_ok )
   374 #endif
   375 #ifdef USE_TIMIDITY_MIDI
   376 		native_midi_ok = !timidity_ok;
   377 	if ( !native_midi_ok ) {
   378 		native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
   379 	}
   380 	if ( native_midi_ok )
   381 #endif
   382 		native_midi_ok = native_midi_detect();
   383 	if ( native_midi_ok )
   384 		add_music_decoder("NATIVEMIDI");
   385 #endif
   386 #endif
   387 #ifdef OGG_MUSIC
   388 	if ( OGG_init(mixer) == 0 ) {
   389 		add_music_decoder("OGG");
   390 	}
   391 #endif
   392 #ifdef FLAC_MUSIC
   393 	if ( FLAC_init(mixer) == 0 ) {
   394 		add_music_decoder("FLAC");
   395 	}
   396 #endif
   397 #if defined(MP3_MUSIC) || defined(MP3_MAD_MUSIC)
   398 	/* Keep a copy of the mixer */
   399 	used_mixer = *mixer;
   400 	add_music_decoder("MP3");
   401 #endif
   402 
   403 	music_playing = NULL;
   404 	music_stopped = 0;
   405 	Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
   406 
   407 	/* Calculate the number of ms for each callback */
   408 	ms_per_step = (int) (((float)mixer->samples * 1000.0) / mixer->freq);
   409 
   410 	return(0);
   411 }
   412 
   413 /* Portable case-insensitive string compare function */
   414 int MIX_string_equals(const char *str1, const char *str2)
   415 {
   416 	while ( *str1 && *str2 ) {
   417 		if ( toupper((unsigned char)*str1) !=
   418 		     toupper((unsigned char)*str2) )
   419 			break;
   420 		++str1;
   421 		++str2;
   422 	}
   423 	return (!*str1 && !*str2);
   424 }
   425 
   426 /* Load a music file */
   427 Mix_Music *Mix_LoadMUS(const char *file)
   428 {
   429 	FILE *fp;
   430 	char *ext;
   431 	Uint8 magic[5], moremagic[9];
   432 	Mix_Music *music;
   433 
   434 	/* Figure out what kind of file this is */
   435 	fp = fopen(file, "rb");
   436 	if ( (fp == NULL) || !fread(magic, 4, 1, fp) ) {
   437 		if ( fp != NULL ) {
   438 			fclose(fp);
   439 		}
   440 		Mix_SetError("Couldn't read from '%s'", file);
   441 		return(NULL);
   442 	}
   443 	if (!fread(moremagic, 8, 1, fp)) {
   444 		Mix_SetError("Couldn't read from '%s'", file);
   445 		return(NULL);
   446 	}
   447 	magic[4] = '\0';
   448 	moremagic[8] = '\0';
   449 	fclose(fp);
   450 
   451 	/* Figure out the file extension, so we can determine the type */
   452 	ext = strrchr(file, '.');
   453 	if ( ext ) ++ext; /* skip the dot in the extension */
   454 
   455 	/* Allocate memory for the music structure */
   456 	music = (Mix_Music *)malloc(sizeof(Mix_Music));
   457 	if ( music == NULL ) {
   458 		Mix_SetError("Out of memory");
   459 		return(NULL);
   460 	}
   461 	music->error = 0;
   462 
   463 #ifdef CMD_MUSIC
   464 	if ( music_cmd ) {
   465 		music->type = MUS_CMD;
   466 		music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
   467 		if ( music->data.cmd == NULL ) {
   468 			music->error = 1;
   469 		}
   470 	} else
   471 #endif
   472 #ifdef WAV_MUSIC
   473 	/* WAVE files have the magic four bytes "RIFF"
   474 	   AIFF files have the magic 12 bytes "FORM" XXXX "AIFF"
   475 	 */
   476 	if ( (ext && MIX_string_equals(ext, "WAV")) ||
   477 	     ((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
   478 	     (strcmp((char *)magic, "FORM") == 0) ) {
   479 		music->type = MUS_WAV;
   480 		music->data.wave = WAVStream_LoadSong(file, (char *)magic);
   481 		if ( music->data.wave == NULL ) {
   482 		  	Mix_SetError("Unable to load WAV file");
   483 			music->error = 1;
   484 		}
   485 	} else
   486 #endif
   487 #ifdef MID_MUSIC
   488 	/* MIDI files have the magic four bytes "MThd" */
   489 	if ( (ext && MIX_string_equals(ext, "MID")) ||
   490 	     (ext && MIX_string_equals(ext, "MIDI")) ||
   491 	     strcmp((char *)magic, "MThd") == 0  ||
   492 	     ( strcmp((char *)magic, "RIFF") == 0  &&
   493 	  	strcmp((char *)(moremagic+4), "RMID") == 0 ) ) {
   494 		music->type = MUS_MID;
   495 #ifdef USE_NATIVE_MIDI
   496   		if ( native_midi_ok ) {
   497   			music->data.nativemidi = native_midi_loadsong(file);
   498 	  		if ( music->data.nativemidi == NULL ) {
   499 		  		Mix_SetError("%s", native_midi_error());
   500 			  	music->error = 1;
   501 			}
   502 			goto skip;
   503 	  	}
   504 #endif
   505 #ifdef USE_FLUIDSYNTH_MIDI
   506 		if ( fluidsynth_ok ) {
   507 			music->data.fluidsynthmidi = fluidsynth_loadsong(file);
   508 			if ( music->data.fluidsynthmidi == NULL ) {
   509 				music->error = 1;
   510 			}
   511 			goto skip;
   512 		}
   513 #endif
   514 #ifdef USE_TIMIDITY_MIDI
   515 		if ( timidity_ok ) {
   516 			music->data.midi = Timidity_LoadSong(file);
   517 			if ( music->data.midi == NULL ) {
   518 				Mix_SetError("%s", Timidity_Error());
   519 				music->error = 1;
   520 			}
   521 		} else {
   522 			Mix_SetError("%s", Timidity_Error());
   523 			music->error = 1;
   524 		}
   525 #endif
   526 	} else
   527 #endif
   528 #ifdef OGG_MUSIC
   529 	/* Ogg Vorbis files have the magic four bytes "OggS" */
   530 	if ( (ext && MIX_string_equals(ext, "OGG")) ||
   531 	     strcmp((char *)magic, "OggS") == 0 ) {
   532 		music->type = MUS_OGG;
   533 		music->data.ogg = OGG_new(file);
   534 		if ( music->data.ogg == NULL ) {
   535 			music->error = 1;
   536 		}
   537 	} else
   538 #endif
   539 #ifdef FLAC_MUSIC
   540 	/* FLAC files have the magic four bytes "fLaC" */
   541 	if ( (ext && MIX_string_equals(ext, "FLAC")) ||
   542 		 strcmp((char *)magic, "fLaC") == 0 ) {
   543 		music->type = MUS_FLAC;
   544 		music->data.flac = FLAC_new(file);
   545 		if ( music->data.flac == NULL ) {
   546 			music->error = 1;
   547 		}
   548 	} else
   549 #endif
   550 #ifdef MP3_MUSIC
   551 	if ( (ext && MIX_string_equals(ext, "MPG")) ||
   552 	     (ext && MIX_string_equals(ext, "MP3")) ||
   553 	     (ext && MIX_string_equals(ext, "MPEG")) ||
   554 	     (magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ||
   555 	     (strncmp((char *)magic, "ID3", 3) == 0) ) {
   556 		if ( Mix_Init(MIX_INIT_MP3) ) {
   557 			SMPEG_Info info;
   558 			music->type = MUS_MP3;
   559 			music->data.mp3 = smpeg.SMPEG_new(file, &info, 0);
   560 			if ( !info.has_audio ) {
   561 				Mix_SetError("MPEG file does not have any audio stream.");
   562 				music->error = 1;
   563 			} else {
   564 				smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
   565 			}
   566 		} else {
   567 			music->error = 1;
   568 		}
   569 	} else
   570 #endif
   571 #ifdef MP3_MAD_MUSIC
   572 	if ( (ext && MIX_string_equals(ext, "MPG")) ||
   573 	     (ext && MIX_string_equals(ext, "MP3")) ||
   574 	     (ext && MIX_string_equals(ext, "MPEG")) ||
   575 	     (ext && MIX_string_equals(ext, "MAD")) ||
   576 	     (magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) ||
   577 	     (strncmp((char *)magic, "ID3", 3) == 0) ) {
   578 		music->type = MUS_MP3_MAD;
   579 		music->data.mp3_mad = mad_openFile(file, &used_mixer);
   580 		if (music->data.mp3_mad == 0) {
   581 		    Mix_SetError("Could not initialize MPEG stream.");
   582 			music->error = 1;
   583 		}
   584 	} else
   585 #endif
   586 #ifdef MODPLUG_MUSIC
   587 	if ( 1 ) {
   588 		music->type = MUS_MODPLUG;
   589 		music->data.modplug = modplug_new(file);
   590 		if ( music->data.modplug == NULL ) {
   591 			music->error = 1;
   592 		}
   593 	} else
   594 #endif
   595 #ifdef MOD_MUSIC
   596 	if ( 1 ) {
   597 		music->type = MUS_MOD;
   598 		music->data.module = MOD_new(file);
   599 		if ( music->data.module == NULL ) {
   600 			music->error = 1;
   601 		}
   602 	} else
   603 #endif
   604 	{
   605 		Mix_SetError("Unrecognized music format");
   606 		music->error = 1;
   607 	}
   608 
   609 skip:
   610 	if ( music->error ) {
   611 		free(music);
   612 		music = NULL;
   613 	}
   614 	return(music);
   615 }
   616 
   617 /* Free a music chunk previously loaded */
   618 void Mix_FreeMusic(Mix_Music *music)
   619 {
   620 	if ( music ) {
   621 		/* Stop the music if it's currently playing */
   622 		SDL_LockAudio();
   623 		if ( music == music_playing ) {
   624 			/* Wait for any fade out to finish */
   625 			while ( music->fading == MIX_FADING_OUT ) {
   626 				SDL_UnlockAudio();
   627 				SDL_Delay(100);
   628 				SDL_LockAudio();
   629 			}
   630 			if ( music == music_playing ) {
   631 				music_internal_halt();
   632 			}
   633 		}
   634 		SDL_UnlockAudio();
   635 		switch (music->type) {
   636 #ifdef CMD_MUSIC
   637 			case MUS_CMD:
   638 				MusicCMD_FreeSong(music->data.cmd);
   639 				break;
   640 #endif
   641 #ifdef WAV_MUSIC
   642 			case MUS_WAV:
   643 				WAVStream_FreeSong(music->data.wave);
   644 				break;
   645 #endif
   646 #ifdef MODPLUG_MUSIC
   647 			case MUS_MODPLUG:
   648 				modplug_delete(music->data.modplug);
   649 				break;
   650 #endif
   651 #ifdef MOD_MUSIC
   652 			case MUS_MOD:
   653 				MOD_delete(music->data.module);
   654 				break;
   655 #endif
   656 #ifdef MID_MUSIC
   657 			case MUS_MID:
   658 #ifdef USE_NATIVE_MIDI
   659   				if ( native_midi_ok ) {
   660 					native_midi_freesong(music->data.nativemidi);
   661 					goto skip;
   662 				}
   663 #endif
   664 #ifdef USE_FLUIDSYNTH_MIDI
   665 				if ( fluidsynth_ok ) {
   666 					fluidsynth_freesong(music->data.fluidsynthmidi);
   667 					goto skip;
   668 				}
   669 #endif
   670 #ifdef USE_TIMIDITY_MIDI
   671 				if ( timidity_ok ) {
   672 					Timidity_FreeSong(music->data.midi);
   673 					goto skip;
   674 				}
   675 #endif
   676 				break;
   677 #endif
   678 #ifdef OGG_MUSIC
   679 			case MUS_OGG:
   680 				OGG_delete(music->data.ogg);
   681 				break;
   682 #endif
   683 #ifdef FLAC_MUSIC
   684 			case MUS_FLAC:
   685 				FLAC_delete(music->data.flac);
   686 				break;
   687 #endif
   688 #ifdef MP3_MUSIC
   689 			case MUS_MP3:
   690 				smpeg.SMPEG_delete(music->data.mp3);
   691 				break;
   692 #endif
   693 #ifdef MP3_MAD_MUSIC
   694 			case MUS_MP3_MAD:
   695 				mad_closeFile(music->data.mp3_mad);
   696 				break;
   697 #endif
   698 			default:
   699 				/* Unknown music type?? */
   700 				break;
   701 		}
   702 
   703     skip:
   704 		free(music);
   705 	}
   706 }
   707 
   708 /* Find out the music format of a mixer music, or the currently playing
   709    music, if 'music' is NULL.
   710 */
   711 Mix_MusicType Mix_GetMusicType(const Mix_Music *music)
   712 {
   713 	Mix_MusicType type = MUS_NONE;
   714 
   715 	if ( music ) {
   716 		type = music->type;
   717 	} else {
   718 		SDL_LockAudio();
   719 		if ( music_playing ) {
   720 			type = music_playing->type;
   721 		}
   722 		SDL_UnlockAudio();
   723 	}
   724 	return(type);
   725 }
   726 
   727 /* Play a music chunk.  Returns 0, or -1 if there was an error.
   728  */
   729 static int music_internal_play(Mix_Music *music, double position)
   730 {
   731 	int retval = 0;
   732 
   733 	/* Note the music we're playing */
   734 	if ( music_playing ) {
   735 		music_internal_halt();
   736 	}
   737 	music_playing = music;
   738 
   739 	/* Set the initial volume */
   740 	if ( music->type != MUS_MOD ) {
   741 		music_internal_initialize_volume();
   742 	}
   743 
   744 	/* Set up for playback */
   745 	switch (music->type) {
   746 #ifdef CMD_MUSIC
   747 	    case MUS_CMD:
   748 		MusicCMD_Start(music->data.cmd);
   749 		break;
   750 #endif
   751 #ifdef WAV_MUSIC
   752 	    case MUS_WAV:
   753 		WAVStream_Start(music->data.wave);
   754 		break;
   755 #endif
   756 #ifdef MODPLUG_MUSIC
   757 	    case MUS_MODPLUG:
   758 		/* can't set volume until file is loaded, so finally set it now */
   759 		music_internal_initialize_volume();
   760 		modplug_play(music->data.modplug);
   761 		break;
   762 #endif
   763 #ifdef MOD_MUSIC
   764 	    case MUS_MOD:
   765 		MOD_play(music->data.module);
   766 		/* Player_SetVolume() does nothing before Player_Start() */
   767 		music_internal_initialize_volume();
   768 		break;
   769 #endif
   770 #ifdef MID_MUSIC
   771 	    case MUS_MID:
   772 #ifdef USE_NATIVE_MIDI
   773 		if ( native_midi_ok ) {
   774 			native_midi_start(music->data.nativemidi);
   775 			goto skip;
   776 		}
   777 #endif
   778 #ifdef USE_FLUIDSYNTH_MIDI
   779 		if (fluidsynth_ok ) {
   780 			fluidsynth_start(music->data.fluidsynthmidi);
   781 			goto skip;
   782 		}
   783 #endif
   784 #ifdef USE_TIMIDITY_MIDI
   785 		if ( timidity_ok ) {
   786 			Timidity_Start(music->data.midi);
   787 			goto skip;
   788 		}
   789 #endif
   790 		break;
   791 #endif
   792 #ifdef OGG_MUSIC
   793 	    case MUS_OGG:
   794 		OGG_play(music->data.ogg);
   795 		break;
   796 #endif
   797 #ifdef FLAC_MUSIC
   798 	    case MUS_FLAC:
   799 		FLAC_play(music->data.flac);
   800 		break;
   801 #endif
   802 #ifdef MP3_MUSIC
   803 	    case MUS_MP3:
   804 		smpeg.SMPEG_enableaudio(music->data.mp3,1);
   805 		smpeg.SMPEG_enablevideo(music->data.mp3,0);
   806 		smpeg.SMPEG_play(music_playing->data.mp3);
   807 		break;
   808 #endif
   809 #ifdef MP3_MAD_MUSIC
   810 	    case MUS_MP3_MAD:
   811 		mad_start(music->data.mp3_mad);
   812 		break;
   813 #endif
   814 	    default:
   815 		Mix_SetError("Can't play unknown music type");
   816 		retval = -1;
   817 		break;
   818 	}
   819 
   820 skip:
   821 	/* Set the playback position, note any errors if an offset is used */
   822 	if ( retval == 0 ) {
   823 		if ( position > 0.0 ) {
   824 			if ( music_internal_position(position) < 0 ) {
   825 				Mix_SetError("Position not implemented for music type");
   826 				retval = -1;
   827 			}
   828 		} else {
   829 			music_internal_position(0.0);
   830 		}
   831 	}
   832 
   833 	/* If the setup failed, we're not playing any music anymore */
   834 	if ( retval < 0 ) {
   835 		music_playing = NULL;
   836 	}
   837 	return(retval);
   838 }
   839 int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
   840 {
   841 	int retval;
   842 
   843 	if ( ms_per_step == 0 ) {
   844 		SDL_SetError("Audio device hasn't been opened");
   845 		return(-1);
   846 	}
   847 
   848 	/* Don't play null pointers :-) */
   849 	if ( music == NULL ) {
   850 		Mix_SetError("music parameter was NULL");
   851 		return(-1);
   852 	}
   853 
   854 	/* Setup the data */
   855 	if ( ms ) {
   856 		music->fading = MIX_FADING_IN;
   857 	} else {
   858 		music->fading = MIX_NO_FADING;
   859 	}
   860 	music->fade_step = 0;
   861 	music->fade_steps = ms/ms_per_step;
   862 
   863 	/* Play the puppy */
   864 	SDL_LockAudio();
   865 	/* If the current music is fading out, wait for the fade to complete */
   866 	while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) {
   867 		SDL_UnlockAudio();
   868 		SDL_Delay(100);
   869 		SDL_LockAudio();
   870 	}
   871 	music_active = 1;
   872 	music_loops = loops;
   873 	retval = music_internal_play(music, position);
   874 	SDL_UnlockAudio();
   875 
   876 	return(retval);
   877 }
   878 int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
   879 {
   880 	return Mix_FadeInMusicPos(music, loops, ms, 0.0);
   881 }
   882 int Mix_PlayMusic(Mix_Music *music, int loops)
   883 {
   884 	return Mix_FadeInMusicPos(music, loops, 0, 0.0);
   885 }
   886 
   887 /* Set the playing music position */
   888 int music_internal_position(double position)
   889 {
   890 	int retval = 0;
   891 
   892 	switch (music_playing->type) {
   893 #ifdef MODPLUG_MUSIC
   894 	    case MUS_MODPLUG:
   895 		modplug_jump_to_time(music_playing->data.modplug, position);
   896 		break;
   897 #endif
   898 #ifdef MOD_MUSIC
   899 	    case MUS_MOD:
   900 		MOD_jump_to_time(music_playing->data.module, position);
   901 		break;
   902 #endif
   903 #ifdef OGG_MUSIC
   904 	    case MUS_OGG:
   905 		OGG_jump_to_time(music_playing->data.ogg, position);
   906 		break;
   907 #endif
   908 #ifdef FLAC_MUSIC
   909 	    case MUS_FLAC:
   910 		FLAC_jump_to_time(music_playing->data.flac, position);
   911 		break;
   912 #endif
   913 #ifdef MP3_MUSIC
   914 	    case MUS_MP3:
   915 		if ( position > 0.0 ) {
   916 			smpeg.SMPEG_skip(music_playing->data.mp3, (float)position);
   917 		} else {
   918 			smpeg.SMPEG_rewind(music_playing->data.mp3);
   919 			smpeg.SMPEG_play(music_playing->data.mp3);
   920 		}
   921 		break;
   922 #endif
   923 #ifdef MP3_MAD_MUSIC
   924 	    case MUS_MP3_MAD:
   925 		mad_seek(music_playing->data.mp3_mad, position);
   926 		break;
   927 #endif
   928 	    default:
   929 		/* TODO: Implement this for other music backends */
   930 		retval = -1;
   931 		break;
   932 	}
   933 	return(retval);
   934 }
   935 int Mix_SetMusicPosition(double position)
   936 {
   937 	int retval;
   938 
   939 	SDL_LockAudio();
   940 	if ( music_playing ) {
   941 		retval = music_internal_position(position);
   942 		if ( retval < 0 ) {
   943 			Mix_SetError("Position not implemented for music type");
   944 		}
   945 	} else {
   946 		Mix_SetError("Music isn't playing");
   947 		retval = -1;
   948 	}
   949 	SDL_UnlockAudio();
   950 
   951 	return(retval);
   952 }
   953 
   954 /* Set the music's initial volume */
   955 static void music_internal_initialize_volume(void)
   956 {
   957 	if ( music_playing->fading == MIX_FADING_IN ) {
   958 		music_internal_volume(0);
   959 	} else {
   960 		music_internal_volume(music_volume);
   961 	}
   962 }
   963 
   964 /* Set the music volume */
   965 static void music_internal_volume(int volume)
   966 {
   967 	switch (music_playing->type) {
   968 #ifdef CMD_MUSIC
   969 	    case MUS_CMD:
   970 		MusicCMD_SetVolume(volume);
   971 		break;
   972 #endif
   973 #ifdef WAV_MUSIC
   974 	    case MUS_WAV:
   975 		WAVStream_SetVolume(volume);
   976 		break;
   977 #endif
   978 #ifdef MODPLUG_MUSIC
   979 	    case MUS_MODPLUG:
   980 		modplug_setvolume(music_playing->data.modplug, volume);
   981 		break;
   982 #endif
   983 #ifdef MOD_MUSIC
   984 	    case MUS_MOD:
   985 		MOD_setvolume(music_playing->data.module, volume);
   986 		break;
   987 #endif
   988 #ifdef MID_MUSIC
   989 	    case MUS_MID:
   990 #ifdef USE_NATIVE_MIDI
   991 		if ( native_midi_ok ) {
   992 			native_midi_setvolume(volume);
   993 			return;
   994 		}
   995 #endif
   996 #ifdef USE_FLUIDSYNTH_MIDI
   997 		if ( fluidsynth_ok ) {
   998 			fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
   999 			return;
  1000 		}
  1001 #endif
  1002 #ifdef USE_TIMIDITY_MIDI
  1003 		if ( timidity_ok ) {
  1004 			Timidity_SetVolume(volume);
  1005 			return;
  1006 		}
  1007 #endif
  1008 		break;
  1009 #endif
  1010 #ifdef OGG_MUSIC
  1011 	    case MUS_OGG:
  1012 		OGG_setvolume(music_playing->data.ogg, volume);
  1013 		break;
  1014 #endif
  1015 #ifdef FLAC_MUSIC
  1016 	    case MUS_FLAC:
  1017 		FLAC_setvolume(music_playing->data.flac, volume);
  1018 		break;
  1019 #endif
  1020 #ifdef MP3_MUSIC
  1021 	    case MUS_MP3:
  1022 		smpeg.SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
  1023 		break;
  1024 #endif
  1025 #ifdef MP3_MAD_MUSIC
  1026 	    case MUS_MP3_MAD:
  1027 		mad_setVolume(music_playing->data.mp3_mad, volume);
  1028 		break;
  1029 #endif
  1030 	    default:
  1031 		/* Unknown music type?? */
  1032 		break;
  1033 	}
  1034 }
  1035 int Mix_VolumeMusic(int volume)
  1036 {
  1037 	int prev_volume;
  1038 
  1039 	prev_volume = music_volume;
  1040 	if ( volume < 0 ) {
  1041 		return prev_volume;
  1042 	}
  1043 	if ( volume > SDL_MIX_MAXVOLUME ) {
  1044 		volume = SDL_MIX_MAXVOLUME;
  1045 	}
  1046 	music_volume = volume;
  1047 	SDL_LockAudio();
  1048 	if ( music_playing ) {
  1049 		music_internal_volume(music_volume);
  1050 	}
  1051 	SDL_UnlockAudio();
  1052 	return(prev_volume);
  1053 }
  1054 
  1055 /* Halt playing of music */
  1056 static void music_internal_halt(void)
  1057 {
  1058 	switch (music_playing->type) {
  1059 #ifdef CMD_MUSIC
  1060 	    case MUS_CMD:
  1061 		MusicCMD_Stop(music_playing->data.cmd);
  1062 		break;
  1063 #endif
  1064 #ifdef WAV_MUSIC
  1065 	    case MUS_WAV:
  1066 		WAVStream_Stop();
  1067 		break;
  1068 #endif
  1069 #ifdef MODPLUG_MUSIC
  1070 	    case MUS_MODPLUG:
  1071 		modplug_stop(music_playing->data.modplug);
  1072 		break;
  1073 #endif
  1074 #ifdef MOD_MUSIC
  1075 	    case MUS_MOD:
  1076 		MOD_stop(music_playing->data.module);
  1077 		break;
  1078 #endif
  1079 #ifdef MID_MUSIC
  1080 	    case MUS_MID:
  1081 #ifdef USE_NATIVE_MIDI
  1082 		if ( native_midi_ok ) {
  1083 			native_midi_stop();
  1084 			goto skip;
  1085 		}
  1086 #endif
  1087 #ifdef USE_FLUIDSYNTH_MIDI
  1088 		if ( fluidsynth_ok ) {
  1089 			fluidsynth_stop(music_playing->data.fluidsynthmidi);
  1090 			goto skip;
  1091 		}
  1092 #endif
  1093 #ifdef USE_TIMIDITY_MIDI
  1094 		if ( timidity_ok ) {
  1095 			Timidity_Stop();
  1096 			goto skip;
  1097 		}
  1098 #endif
  1099 		break;
  1100 #endif
  1101 #ifdef OGG_MUSIC
  1102 	    case MUS_OGG:
  1103 		OGG_stop(music_playing->data.ogg);
  1104 		break;
  1105 #endif
  1106 #ifdef FLAC_MUSIC
  1107 	    case MUS_FLAC:
  1108 		FLAC_stop(music_playing->data.flac);
  1109 		break;
  1110 #endif
  1111 #ifdef MP3_MUSIC
  1112 	    case MUS_MP3:
  1113 		smpeg.SMPEG_stop(music_playing->data.mp3);
  1114 		break;
  1115 #endif
  1116 #ifdef MP3_MAD_MUSIC
  1117 	    case MUS_MP3_MAD:
  1118 		mad_stop(music_playing->data.mp3_mad);
  1119 		break;
  1120 #endif
  1121 	    default:
  1122 		/* Unknown music type?? */
  1123 		return;
  1124 	}
  1125 
  1126 skip:
  1127 	music_playing->fading = MIX_NO_FADING;
  1128 	music_playing = NULL;
  1129 }
  1130 int Mix_HaltMusic(void)
  1131 {
  1132 	SDL_LockAudio();
  1133 	if ( music_playing ) {
  1134 		music_internal_halt();
  1135 	}
  1136 	SDL_UnlockAudio();
  1137 
  1138 	return(0);
  1139 }
  1140 
  1141 /* Progressively stop the music */
  1142 int Mix_FadeOutMusic(int ms)
  1143 {
  1144 	int retval = 0;
  1145 
  1146 	if ( ms_per_step == 0 ) {
  1147 		SDL_SetError("Audio device hasn't been opened");
  1148 		return 0;
  1149 	}
  1150 
  1151 	if (ms <= 0) {  /* just halt immediately. */
  1152 		Mix_HaltMusic();
  1153 		return 1;
  1154 	}
  1155 
  1156 	SDL_LockAudio();
  1157 	if ( music_playing) {
  1158                 int fade_steps = (ms + ms_per_step - 1)/ms_per_step;
  1159                 if ( music_playing->fading == MIX_NO_FADING ) {
  1160 	        	music_playing->fade_step = 0;
  1161                 } else {
  1162                         int step;
  1163                         int old_fade_steps = music_playing->fade_steps;
  1164                         if ( music_playing->fading == MIX_FADING_OUT ) {
  1165                                 step = music_playing->fade_step;
  1166                         } else {
  1167                                 step = old_fade_steps
  1168                                         - music_playing->fade_step + 1;
  1169                         }
  1170                         music_playing->fade_step = (step * fade_steps)
  1171                                 / old_fade_steps;
  1172                 }
  1173 		music_playing->fading = MIX_FADING_OUT;
  1174 		music_playing->fade_steps = fade_steps;
  1175 		retval = 1;
  1176 	}
  1177 	SDL_UnlockAudio();
  1178 
  1179 	return(retval);
  1180 }
  1181 
  1182 Mix_Fading Mix_FadingMusic(void)
  1183 {
  1184 	Mix_Fading fading = MIX_NO_FADING;
  1185 
  1186 	SDL_LockAudio();
  1187 	if ( music_playing ) {
  1188 		fading = music_playing->fading;
  1189 	}
  1190 	SDL_UnlockAudio();
  1191 
  1192 	return(fading);
  1193 }
  1194 
  1195 /* Pause/Resume the music stream */
  1196 void Mix_PauseMusic(void)
  1197 {
  1198 	music_active = 0;
  1199 }
  1200 
  1201 void Mix_ResumeMusic(void)
  1202 {
  1203 	music_active = 1;
  1204 }
  1205 
  1206 void Mix_RewindMusic(void)
  1207 {
  1208 	Mix_SetMusicPosition(0.0);
  1209 }
  1210 
  1211 int Mix_PausedMusic(void)
  1212 {
  1213 	return (music_active == 0);
  1214 }
  1215 
  1216 /* Check the status of the music */
  1217 static int music_internal_playing()
  1218 {
  1219 	int playing = 1;
  1220 
  1221 	if (music_playing == NULL) {
  1222 		return 0;
  1223 	}
  1224 
  1225 	switch (music_playing->type) {
  1226 #ifdef CMD_MUSIC
  1227 	    case MUS_CMD:
  1228 		if (!MusicCMD_Active(music_playing->data.cmd)) {
  1229 			playing = 0;
  1230 		}
  1231 		break;
  1232 #endif
  1233 #ifdef WAV_MUSIC
  1234 	    case MUS_WAV:
  1235 		if ( ! WAVStream_Active() ) {
  1236 			playing = 0;
  1237 		}
  1238 		break;
  1239 #endif
  1240 #ifdef MODPLUG_MUSIC
  1241 	    case MUS_MODPLUG:
  1242 		if ( ! modplug_playing(music_playing->data.modplug) ) {
  1243 			playing = 0;
  1244 		}
  1245 		break;
  1246 #endif
  1247 #ifdef MOD_MUSIC
  1248 	    case MUS_MOD:
  1249 		if ( ! MOD_playing(music_playing->data.module) ) {
  1250 			playing = 0;
  1251 		}
  1252 		break;
  1253 #endif
  1254 #ifdef MID_MUSIC
  1255 	    case MUS_MID:
  1256 #ifdef USE_NATIVE_MIDI
  1257 		if ( native_midi_ok ) {
  1258 			if ( ! native_midi_active() )
  1259 				playing = 0;
  1260 			goto skip;
  1261 		}
  1262 #endif
  1263 #ifdef USE_FLUIDSYNTH_MIDI
  1264 		if ( fluidsynth_ok ) {
  1265 			if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) )
  1266 				playing = 0;
  1267 			goto skip;
  1268 		}
  1269 #endif
  1270 #ifdef USE_TIMIDITY_MIDI
  1271 		if ( timidity_ok ) {
  1272 			if ( ! Timidity_Active() )
  1273 				playing = 0;
  1274 			goto skip;
  1275 		}
  1276 #endif
  1277 		break;
  1278 #endif
  1279 #ifdef OGG_MUSIC
  1280 	    case MUS_OGG:
  1281 		if ( ! OGG_playing(music_playing->data.ogg) ) {
  1282 			playing = 0;
  1283 		}
  1284 		break;
  1285 #endif
  1286 #ifdef FLAC_MUSIC
  1287 	    case MUS_FLAC:
  1288 		if ( ! FLAC_playing(music_playing->data.flac) ) {
  1289 			playing = 0;
  1290 		}
  1291 		break;
  1292 #endif
  1293 #ifdef MP3_MUSIC
  1294 	    case MUS_MP3:
  1295 		if ( smpeg.SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING )
  1296 			playing = 0;
  1297 		break;
  1298 #endif
  1299 #ifdef MP3_MAD_MUSIC
  1300 	    case MUS_MP3_MAD:
  1301 		if (!mad_isPlaying(music_playing->data.mp3_mad)) {
  1302 			playing = 0;
  1303 		}
  1304 		break;
  1305 #endif
  1306 	    default:
  1307 		playing = 0;
  1308 		break;
  1309 	}
  1310 
  1311 skip:
  1312 	return(playing);
  1313 }
  1314 int Mix_PlayingMusic(void)
  1315 {
  1316 	int playing = 0;
  1317 
  1318 	SDL_LockAudio();
  1319 	if ( music_playing ) {
  1320 		playing = music_internal_playing();
  1321 	}
  1322 	SDL_UnlockAudio();
  1323 
  1324 	return(playing);
  1325 }
  1326 
  1327 /* Set the external music playback command */
  1328 int Mix_SetMusicCMD(const char *command)
  1329 {
  1330 	Mix_HaltMusic();
  1331 	if ( music_cmd ) {
  1332 		free(music_cmd);
  1333 		music_cmd = NULL;
  1334 	}
  1335 	if ( command ) {
  1336 		music_cmd = (char *)malloc(strlen(command)+1);
  1337 		if ( music_cmd == NULL ) {
  1338 			return(-1);
  1339 		}
  1340 		strcpy(music_cmd, command);
  1341 	}
  1342 	return(0);
  1343 }
  1344 
  1345 int Mix_SetSynchroValue(int i)
  1346 {
  1347 	/* Not supported by any players at this time */
  1348 	return(-1);
  1349 }
  1350 
  1351 int Mix_GetSynchroValue(void)
  1352 {
  1353 	/* Not supported by any players at this time */
  1354 	return(-1);
  1355 }
  1356 
  1357 
  1358 /* Uninitialize the music players */
  1359 void close_music(void)
  1360 {
  1361 	Mix_HaltMusic();
  1362 #ifdef CMD_MUSIC
  1363 	Mix_SetMusicCMD(NULL);
  1364 #endif
  1365 #ifdef MODPLUG_MUSIC
  1366 	modplug_exit();
  1367 #endif
  1368 #ifdef MOD_MUSIC
  1369 	MOD_exit();
  1370 #endif
  1371 #ifdef MID_MUSIC
  1372 # ifdef USE_TIMIDITY_MIDI
  1373 	Timidity_Close();
  1374 # endif
  1375 #endif
  1376 
  1377 	/* rcg06042009 report available decoders at runtime. */
  1378 	free(music_decoders);
  1379 	music_decoders = NULL;
  1380 	num_decoders = 0;
  1381 
  1382 	ms_per_step = 0;
  1383 }
  1384 
  1385 Mix_Music *Mix_LoadMUS_RW(SDL_RWops *rw)
  1386 {
  1387 	Uint8 magic[5];	  /*Apparently there is no way to check if the file is really a MOD,*/
  1388 	/*		    or there are too many formats supported by MikMod or MikMod does */
  1389 	/*		    this check by itself. If someone implements other formats (e.g. MP3) */
  1390 	/*		    the check can be uncommented */
  1391 	Uint8 moremagic[9];
  1392 	Mix_Music *music;
  1393 	int start;
  1394 	int freerw = 0;
  1395 
  1396 	if (!rw) {
  1397 		Mix_SetError("RWops pointer is NULL");
  1398 		return NULL;
  1399 	}
  1400 
  1401 	/* Figure out what kind of file this is */
  1402 	start = SDL_RWtell(rw);
  1403 	if ( SDL_RWread(rw,magic,1,4) != 4 ||
  1404 	     SDL_RWread(rw,moremagic,1,8) != 8 ) {
  1405 		Mix_SetError("Couldn't read from RWops");
  1406 		return NULL;
  1407 	}
  1408 	SDL_RWseek(rw, start, RW_SEEK_SET);
  1409 	magic[4]='\0';
  1410 	moremagic[8] = '\0';
  1411 
  1412 	/* Allocate memory for the music structure */
  1413 	music=(Mix_Music *)malloc(sizeof(Mix_Music));
  1414 	if (music==NULL ) {
  1415 		Mix_SetError("Out of memory");
  1416 		return(NULL);
  1417 	}
  1418 	music->error = 0;
  1419 
  1420 #ifdef WAV_MUSIC
  1421 	/* WAVE files have the magic four bytes "RIFF"
  1422 	   AIFF files have the magic 12 bytes "FORM" XXXX "AIFF"
  1423 	 */
  1424 	if ( ((strcmp((char *)magic, "RIFF") == 0) && (strcmp((char *)(moremagic+4), "WAVE") == 0)) ||
  1425 	     (strcmp((char *)magic, "FORM") == 0) ) {
  1426 		music->type = MUS_WAV;
  1427 		music->data.wave = WAVStream_LoadSong_RW(rw, (char *)magic, freerw);
  1428 		if ( music->data.wave == NULL ) {
  1429 			music->error = 1;
  1430 		}
  1431 
  1432 	} else
  1433 #endif
  1434 #ifdef OGG_MUSIC
  1435 	/* Ogg Vorbis files have the magic four bytes "OggS" */
  1436 	if ( strcmp((char *)magic, "OggS") == 0 ) {
  1437 		music->type = MUS_OGG;
  1438 		music->data.ogg = OGG_new_RW(rw, freerw);
  1439 		if ( music->data.ogg == NULL ) {
  1440 			music->error = 1;
  1441 		}
  1442 	} else
  1443 #endif
  1444 #ifdef FLAC_MUSIC
  1445 	/* FLAC files have the magic four bytes "fLaC" */
  1446 	if ( strcmp((char *)magic, "fLaC") == 0 ) {
  1447 		music->type = MUS_FLAC;
  1448 		music->data.flac = FLAC_new_RW(rw, freerw);
  1449 		if ( music->data.flac == NULL ) {
  1450 			music->error = 1;
  1451 		}
  1452 	} else
  1453 #endif
  1454 #ifdef MP3_MUSIC
  1455 	if ( ( magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) || ( strncmp((char *)magic, "ID3", 3) == 0 ) ) {
  1456 		if ( Mix_Init(MIX_INIT_MP3) ) {
  1457 			SMPEG_Info info;
  1458 			music->type = MUS_MP3;
  1459 			music->data.mp3 = smpeg.SMPEG_new_rwops(rw, &info, 0);
  1460 			if ( !info.has_audio ) {
  1461 				Mix_SetError("MPEG file does not have any audio stream.");
  1462 				music->error = 1;
  1463 			} else {
  1464 				smpeg.SMPEG_actualSpec(music->data.mp3, &used_mixer);
  1465 			}
  1466 		} else {
  1467 			music->error = 1;
  1468 		}
  1469 	} else
  1470 #endif
  1471 #ifdef MP3_MAD_MUSIC
  1472 	if ( ( magic[0] == 0xFF && (magic[1] & 0xF0) == 0xF0) || ( strncmp((char *)magic, "ID3", 3) == 0 ) ) {
  1473 		music->type = MUS_MP3_MAD;
  1474 		music->data.mp3_mad = mad_openFileRW(rw, &used_mixer, freerw);
  1475 		if (music->data.mp3_mad == 0) {
  1476 			Mix_SetError("Could not initialize MPEG stream.");
  1477 			music->error = 1;
  1478 		}
  1479 	} else
  1480 #endif
  1481 #ifdef MID_MUSIC
  1482 	/* MIDI files have the magic four bytes "MThd" */
  1483 	if ( strcmp((char *)magic, "MThd") == 0 ) {
  1484 		music->type = MUS_MID;
  1485 #ifdef USE_NATIVE_MIDI
  1486 		if ( native_midi_ok ) {
  1487 			music->data.nativemidi = native_midi_loadsong_RW(rw, freerw);
  1488 	  		if ( music->data.nativemidi == NULL ) {
  1489 		  		Mix_SetError("%s", native_midi_error());
  1490 			  	music->error = 1;
  1491 			}
  1492 			goto skip;
  1493 		}
  1494 #endif
  1495 #ifdef USE_FLUIDSYNTH_MIDI
  1496 		if ( fluidsynth_ok ) {
  1497 			music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw, freerw);
  1498 			if ( music->data.fluidsynthmidi == NULL ) {
  1499 				music->error = 1;
  1500 			}
  1501 			goto skip;
  1502 		}
  1503 #endif
  1504 #ifdef USE_TIMIDITY_MIDI
  1505 		if ( timidity_ok ) {
  1506 			music->data.midi = Timidity_LoadSong_RW(rw, freerw);
  1507 			if ( music->data.midi == NULL ) {
  1508 				Mix_SetError("%s", Timidity_Error());
  1509 				music->error = 1;
  1510 			}
  1511 		} else {
  1512 			Mix_SetError("%s", Timidity_Error());
  1513 			music->error = 1;
  1514 		}
  1515 #endif
  1516 	} else
  1517 #endif
  1518 #if defined(MODPLUG_MUSIC) || defined(MOD_MUSIC)
  1519 	if (1) {
  1520 		music->error = 1;
  1521 #ifdef MODPLUG_MUSIC
  1522 		if ( music->error ) {
  1523 			music->type = MUS_MODPLUG;
  1524 			music->data.modplug = modplug_new_RW(rw, freerw);
  1525 			if ( music->data.modplug ) {
  1526 				music->error = 0;
  1527 			}
  1528 		}
  1529 #endif
  1530 #ifdef MOD_MUSIC
  1531 		if ( music->error ) {
  1532 			music->type = MUS_MOD;
  1533 			music->data.module = MOD_new_RW(rw, freerw);
  1534 			if ( music->data.module ) {
  1535 				music->error = 0;
  1536 			}
  1537 		}
  1538 #endif
  1539 	} else
  1540 #endif /* MODPLUG_MUSIC || MOD_MUSIC */
  1541 	{
  1542 		Mix_SetError("Unrecognized music format");
  1543 		music->error=1;
  1544 	}
  1545 
  1546 skip:
  1547 	if (music->error) {
  1548 		free(music);
  1549 		music=NULL;
  1550 	}
  1551 	return(music);
  1552 }
  1553 
  1554 int Mix_SetSoundFonts(const char *paths)
  1555 {
  1556 #ifdef MID_MUSIC
  1557 	if (soundfont_paths) {
  1558 		free(soundfont_paths);
  1559 		soundfont_paths = NULL;
  1560 	}
  1561 
  1562 	if (paths) {
  1563 		if (!(soundfont_paths = strdup(paths))) {
  1564 			Mix_SetError("Insufficient memory to set SoundFonts");
  1565 			return 0;
  1566 		}
  1567 	}
  1568 #endif
  1569 	return 1;
  1570 }
  1571 
  1572 #ifdef MID_MUSIC
  1573 const char* Mix_GetSoundFonts(void)
  1574 {
  1575 	const char* force = getenv("SDL_FORCE_SOUNDFONTS");
  1576 
  1577 	if (!soundfont_paths || (force && force[0] == '1')) {
  1578 		return getenv("SDL_SOUNDFONTS");
  1579 	} else {
  1580 		return soundfont_paths;
  1581 	}
  1582 }
  1583 
  1584 int Mix_EachSoundFont(int (*function)(const char*, void*), void *data)
  1585 {
  1586 	char *context, *path, *paths;
  1587 	const char* cpaths = Mix_GetSoundFonts();
  1588 
  1589 	if (!cpaths) {
  1590 		Mix_SetError("No SoundFonts have been requested");
  1591 		return 0;
  1592 	}
  1593 
  1594 	if (!(paths = strdup(cpaths))) {
  1595 		Mix_SetError("Insufficient memory to iterate over SoundFonts");
  1596 		return 0;
  1597 	}
  1598 
  1599 #if defined(__MINGW32__) || defined(__MINGW64__)
  1600 	for (path = strtok(paths, ";"); path; path = strtok(NULL, ";")) {
  1601 #elif defined(_WIN32)
  1602 	for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) {
  1603 #else
  1604 	for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) {
  1605 #endif
  1606 		if (!function(path, data)) {
  1607 			free(paths);
  1608 			return 0;
  1609 		}
  1610 	}
  1611 
  1612 	free(paths);
  1613 	return 1;
  1614 }
  1615 #endif