music.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 23:00:03 -0500
changeset 527 1eddea51f162
parent 521 565549e046b0
child 528 bc0dfe8ae026
permissions -rw-r--r--
Partial fix for bug 934 - Native MIDI on OS X does not loop

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