music.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 26 Sep 2009 22:23:16 +0000
changeset 401 ee71829d80e7
parent 398 15acba767487
child 407 73a92ea2c061
permissions -rw-r--r--
Fixed bug #809

O.Sezer 2009-09-26 04:38:45 PDT

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