music.c
author Sam Lantinga <slouken@lokigames.com>
Thu, 11 Nov 1999 17:13:44 +0000
changeset 17 d5638c74656f
parent 16 ada544ec16c6
child 18 461dd4cb63ba
permissions -rw-r--r--
Removed FadeInOut because it leads to deadlock problems
     1 /*
     2     MIXERLIB:  An audio mixer library based on the SDL library
     3     Copyright (C) 1997-1999  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     5635-34 Springhouse Dr.
    21     Pleasanton, CA 94588 (USA)
    22     slouken@devolution.com
    23 */
    24 
    25 #include <stdlib.h>
    26 #include <string.h>
    27 #include <SDL/SDL_endian.h>
    28 #include <SDL/SDL_audio.h>
    29 
    30 #include "mixer.h"
    31 
    32 /* The music command hack is UNIX specific */
    33 #ifndef unix
    34 #undef CMD_MUSIC
    35 #endif
    36 
    37 #ifdef CMD_MUSIC
    38 #include "music_cmd.h"
    39 #endif
    40 #ifdef WAV_MUSIC
    41 #include "wavestream.h"
    42 #endif
    43 #ifdef MOD_MUSIC
    44 #include "mikmod.h"
    45 #endif
    46 #ifdef MID_MUSIC
    47 #include "timidity.h"
    48 #endif
    49 #ifdef MP3_MUSIC
    50 #include <smpeg/smpeg.h>
    51 
    52 static SDL_AudioSpec used_mixer;
    53 #endif
    54 
    55 int music_active = 1;
    56 static int music_stopped = 0;
    57 static int music_loops = 0;
    58 static char *music_cmd = NULL;
    59 static int samplesize;
    60 static Mix_Music *music_playing = 0;
    61 static int music_volume = MIX_MAX_VOLUME;
    62 static int music_swap8;
    63 static int music_swap16;
    64 
    65 struct _Mix_Music {
    66 	enum {
    67 		MUS_CMD,
    68 		MUS_WAV,
    69 		MUS_MOD,
    70 		MUS_MID,
    71 		MUS_MP3
    72 	} type;
    73 	union {
    74 #ifdef CMD_MUSIC
    75 		MusicCMD *cmd;
    76 #endif
    77 #ifdef WAV_MUSIC
    78 		WAVStream *wave;
    79 #endif
    80 #ifdef MOD_MUSIC
    81 		UNIMOD *module;
    82 #endif
    83 #ifdef MID_MUSIC
    84 		MidiSong *midi;
    85 #endif
    86 #ifdef MP3_MUSIC
    87 		SMPEG *mp3;
    88 #endif
    89 	} data;
    90 	Mix_Fading fading;
    91 	int fade_volume;
    92 	int fade_step;
    93 	int fade_steps;
    94 	int error;
    95 };
    96 static int timidity_ok;
    97 
    98 /* Used to calculate fading steps */
    99 static int ms_per_step;
   100 
   101 /* Local low-level functions prototypes */
   102 static void lowlevel_halt(void);
   103 static int  lowlevel_play(Mix_Music *music);
   104 
   105 /* Mixing function */
   106 void music_mixer(void *udata, Uint8 *stream, int len)
   107 {
   108 	int i;
   109 
   110 	if ( music_playing ) {
   111 		if ( music_stopped ) {
   112 			/* To avoid concurrency problems and the use of mutexes,
   113 			   the music is always stopped from the sound thread */
   114 			lowlevel_halt(); /* This function sets music_playing to NULL */
   115 			return;
   116 		}	
   117 		/* Handle fading */
   118 		if ( music_playing->fading != MIX_NO_FADING ) {
   119 			if ( music_playing->fade_step++ < music_playing->fade_steps ) {
   120                 int fade_volume = music_playing->fade_volume;
   121                 int fade_step = music_playing->fade_step;
   122                 int fade_steps = music_playing->fade_steps;
   123 
   124 				if ( music_playing->fading == MIX_FADING_OUT ) {
   125 					Mix_VolumeMusic((fade_volume * (fade_steps-fade_step)) 
   126 									/ fade_steps);
   127 				} else { /* Fading in */
   128 					Mix_VolumeMusic((fade_volume * fade_step) / fade_steps);
   129 				}
   130 			} else {
   131 				if ( music_playing->fading == MIX_FADING_OUT ) {
   132 					lowlevel_halt();
   133 					return;
   134 				}
   135 				music_playing->fading = MIX_NO_FADING;
   136 			}
   137 		}
   138 		/* Restart music if it has to loop */
   139 		if ( music_loops && !Mix_PlayingMusic() ) {
   140 			if ( -- music_loops ) {
   141 				Mix_RewindMusic();
   142 				if ( lowlevel_play(music_playing) < 0 ) {
   143 					fprintf(stderr,"Warning: Music restart failed.\n");
   144 					music_stopped = 1; /* Something went wrong */
   145 					music_playing->fading = MIX_NO_FADING;
   146 				}
   147 			}
   148 		}
   149 		if ( music_volume <= 0 ) { /* Don't mix if volume is null */
   150 			return;
   151 		}
   152 		switch (music_playing->type) {
   153 #ifdef CMD_MUSIC
   154 			case MUS_CMD:
   155 				/* The playing is done externally */
   156 				break;
   157 #endif
   158 #ifdef WAV_MUSIC
   159 			case MUS_WAV:
   160 				WAVStream_PlaySome(stream, len);
   161 				break;
   162 #endif
   163 #ifdef MOD_MUSIC
   164 			case MUS_MOD:
   165 				VC_WriteBytes((SBYTE *)stream, len);
   166 				if ( music_swap8 ) {
   167 					Uint8 *dst;
   168 
   169 					dst = stream;
   170 					for ( i=len; i; --i ) {
   171 						*dst++ ^= 0x80;
   172 					}
   173 				} else
   174 				if ( music_swap16 ) {
   175 					Uint8 *dst, tmp;
   176 
   177 					dst = stream;
   178 					for ( i=(len/2); i; --i ) {
   179 						tmp = dst[0];
   180 						dst[0] = dst[1];
   181 						dst[1] = tmp;
   182 						dst += 2;
   183 					}
   184 				}
   185 				break;
   186 #endif
   187 #ifdef MID_MUSIC
   188 			case MUS_MID:
   189 				Timidity_PlaySome(stream, len/samplesize);
   190 				break;
   191 #endif
   192 #ifdef MP3_MUSIC
   193 		    case MUS_MP3:
   194 			    SMPEG_playAudio(music_playing->data.mp3, stream, len);
   195 				break;
   196 #endif
   197 			default:
   198 				/* Unknown music type?? */
   199 				break;
   200 		}
   201 	}
   202 }
   203 
   204 /* Initialize the music players with a certain desired audio format */
   205 int open_music(SDL_AudioSpec *mixer)
   206 {
   207 	int music_error;
   208 
   209 	music_error = 0;
   210 #ifdef WAV_MUSIC
   211 	if ( WAVStream_Init(mixer) < 0 ) {
   212 		++music_error;
   213 	}
   214 #endif
   215 #ifdef MOD_MUSIC
   216 	/* Set the MikMod music format */
   217 	music_swap8 = 0;
   218 	music_swap16 = 0;
   219 	switch (mixer->format) {
   220 
   221 		case AUDIO_U8:
   222 		case AUDIO_S8: {
   223 			if ( mixer->format == AUDIO_S8 ) {
   224 				music_swap8 = 1;
   225 			}
   226 			md_mode = 0;
   227 		}
   228 		break;
   229 
   230 		case AUDIO_S16LSB:
   231 		case AUDIO_S16MSB: {
   232 			/* See if we need to correct MikMod mixing */
   233 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
   234 			if ( mixer->format == AUDIO_S16MSB ) {
   235 #else
   236 			if ( mixer->format == AUDIO_S16LSB ) {
   237 #endif
   238 				music_swap16 = 1;
   239 			}
   240 			md_mode = DMODE_16BITS;
   241 		}
   242 		break;
   243 
   244 		default: {
   245 			SDL_SetError("Unknown hardware audio format");
   246 			++music_error;
   247 		}
   248 	}
   249 	if ( mixer->channels > 1 ) {
   250 		if ( mixer->channels > 2 ) {
   251 			SDL_SetError("Hardware uses more channels than mixer");
   252 			++music_error;
   253 		}
   254 		md_mode |= DMODE_STEREO;
   255 	}
   256 	samplesize     = mixer->size/mixer->samples;
   257 	md_mixfreq     = mixer->freq;
   258 	md_device      = 0;
   259 	md_volume      = 96;
   260 	md_musicvolume = 128;
   261 	md_sndfxvolume = 128;
   262 	md_pansep      = 128;
   263 	md_reverb      = 0;
   264 	MikMod_RegisterAllLoaders();
   265 	MikMod_RegisterAllDrivers();
   266 	if ( MikMod_Init() ) {
   267 		SDL_SetError("%s", _mm_errmsg[_mm_errno]);
   268 		++music_error;
   269 	}
   270 #endif
   271 #ifdef MID_MUSIC
   272 	if ( Timidity_Init(mixer->freq,
   273 			mixer->format, mixer->channels, mixer->samples) == 0 ) {
   274 		timidity_ok = 1;
   275 	} else {
   276 		timidity_ok = 0;
   277 	}
   278 #endif
   279 #ifdef MP3_MUSIC
   280 	/* Keep a copy of the mixer */
   281 	used_mixer = *mixer;
   282 #endif
   283 	music_playing = 0;
   284 	music_stopped = 0;
   285 	if ( music_error ) {
   286 		return(-1);
   287 	}
   288 	Mix_VolumeMusic(SDL_MIX_MAXVOLUME);
   289 
   290     /* Calculate the number of ms for each callback */
   291     ms_per_step = ((float)mixer->samples * 1000.0) / mixer->freq;
   292 printf("MS per step = %d\n", ms_per_step);
   293 
   294 	return(0);
   295 }
   296 
   297 /* Load a music file */
   298 Mix_Music *Mix_LoadMUS(const char *file)
   299 {
   300 	FILE *fp;
   301 	unsigned char magic[5];
   302 	Mix_Music *music;
   303 
   304 	/* Figure out what kind of file this is */
   305 	fp = fopen(file, "rb");
   306 	if ( (fp == NULL) || !fread(magic, 4, 1, fp) ) {
   307 		if ( fp != NULL ) {
   308 			fclose(fp);
   309 		}
   310 		SDL_SetError("Couldn't read from '%s'", file);
   311 		return(NULL);
   312 	}
   313 	magic[4] = '\0';
   314 	fclose(fp);
   315 
   316 	/* Allocate memory for the music structure */
   317 	music = (Mix_Music *)malloc(sizeof(Mix_Music));
   318 	if ( music == NULL ) {
   319 		SDL_SetError("Out of memory");
   320 		return(NULL);
   321 	}
   322 	music->error = 0;
   323 
   324 #ifdef CMD_MUSIC
   325 	if ( music_cmd ) {
   326 		music->type = MUS_CMD;
   327 		music->data.cmd = MusicCMD_LoadSong(music_cmd, file);
   328 		if ( music->data.cmd == NULL ) {
   329 			music->error = 1;
   330 		}
   331 	} else
   332 #endif
   333 #ifdef WAV_MUSIC
   334 	/* WAVE files have the magic four bytes "RIFF"
   335 	   AIFF files have the magic 12 bytes "FORM" XXXX "AIFF"
   336 	 */
   337 	if ( (strcmp(magic, "RIFF") == 0) || (strcmp(magic, "FORM") == 0) ) {
   338 		music->type = MUS_WAV;
   339 		music->data.wave = WAVStream_LoadSong(file, magic);
   340 		if ( music->data.wave == NULL ) {
   341 			music->error = 1;
   342 		}
   343 	} else
   344 #endif
   345 #ifdef MID_MUSIC
   346 	/* MIDI files have the magic four bytes "MThd" */
   347 	if ( strcmp(magic, "MThd") == 0 ) {
   348 		music->type = MUS_MID;
   349 		if ( timidity_ok ) {
   350 			music->data.midi = Timidity_LoadSong((char *)file);
   351 			if ( music->data.midi == NULL ) {
   352 				SDL_SetError("%s", Timidity_Error());
   353 				music->error = 1;
   354 			}
   355 		}
   356 		else {
   357 			SDL_SetError("%s", Timidity_Error());
   358 			music->error = 1;
   359 		}
   360 	} else
   361 #endif
   362 #ifdef MP3_MUSIC
   363 	if ( magic[0]==0xFF && (magic[1]&0xF0)==0xF0) {
   364 		SMPEG_Info info;
   365 		music->type = MUS_MP3;
   366 		music->data.mp3 = SMPEG_new(file, &info, 0);
   367 		if(!info.has_audio){
   368 			SDL_SetError("MPEG file does not have any audio stream.");
   369 			music->error = 1;
   370 		}else{
   371 			SMPEG_actualSpec(music->data.mp3, &used_mixer);
   372 		}
   373 	} else
   374 #endif
   375 #ifdef MOD_MUSIC
   376 	if ( 1 ) {
   377 		music->type = MUS_MOD;
   378 		music->data.module = MikMod_LoadSong((char *)file, 64);
   379 		if ( music->data.module == NULL ) {
   380 			SDL_SetError("%s", _mm_errmsg[_mm_errno]);
   381 			music->error = 1;
   382 		}
   383 	} else
   384 #endif
   385 	{
   386 		SDL_SetError("Unrecognized music format");
   387 		music->error = 1;
   388 	}
   389 	if ( music->error ) {
   390 		free(music);
   391 		music = NULL;
   392 	}
   393 	return(music);
   394 }
   395 
   396 /* Free a music chunk previously loaded */
   397 void Mix_FreeMusic(Mix_Music *music)
   398 {
   399 	if ( music ) {
   400 		/* Caution: If music is playing, mixer will crash */
   401 		if ( music == music_playing && !music_stopped ) {
   402 			if ( music->fading == MIX_FADING_OUT ) {
   403 				/* Wait for the fade out to finish */
   404 				while ( music_playing && !music_stopped && (music_playing->fading == MIX_FADING_OUT) )
   405 					SDL_Delay(100);
   406 			} else {
   407 				Mix_HaltMusic(); /* Stop it immediately */
   408 			}
   409 		}
   410 		switch (music->type) {
   411 #ifdef CMD_MUSIC
   412 			case MUS_CMD:
   413 				MusicCMD_FreeSong(music->data.cmd);
   414 				break;
   415 #endif
   416 #ifdef WAV_MUSIC
   417 			case MUS_WAV:
   418 				WAVStream_FreeSong(music->data.wave);
   419 				break;
   420 #endif
   421 #ifdef MOD_MUSIC
   422 			case MUS_MOD:
   423 				MikMod_FreeSong(music->data.module);
   424 				break;
   425 #endif
   426 #ifdef MID_MUSIC
   427 			case MUS_MID:
   428 				Timidity_FreeSong(music->data.midi);
   429 				break;
   430 #endif
   431 #ifdef MP3_MUSIC
   432 		    case MUS_MP3:
   433 				SMPEG_delete(music->data.mp3);
   434 				break;
   435 #endif
   436 			default:
   437 				/* Unknown music type?? */
   438 				break;
   439 		}
   440 		free(music);
   441 	}
   442 }
   443 
   444 static int lowlevel_play(Mix_Music *music)
   445 {
   446 	if(!music)
   447 		return(-1);
   448 
   449 	switch (music->type) {
   450 #ifdef CMD_MUSIC
   451 		case MUS_CMD:
   452 			MusicCMD_SetVolume(music_volume);
   453 			MusicCMD_Start(music->data.cmd);
   454 			break;
   455 #endif
   456 #ifdef WAV_MUSIC
   457 		case MUS_WAV:
   458 			WAVStream_SetVolume(music_volume);
   459 			WAVStream_Start(music->data.wave);
   460 			break;
   461 #endif
   462 #ifdef MOD_MUSIC
   463 		case MUS_MOD:
   464 			Player_SetVolume(music_volume);
   465 			Player_Start(music->data.module);
   466 			Player_SetPosition(0);
   467 			break;
   468 #endif
   469 #ifdef MID_MUSIC
   470 		case MUS_MID:
   471 			Timidity_SetVolume(music_volume);
   472 			Timidity_Start(music->data.midi);
   473 			break;
   474 #endif
   475 #ifdef MP3_MUSIC
   476 	    case MUS_MP3:
   477 			SMPEG_enableaudio(music->data.mp3,1);
   478 			SMPEG_enablevideo(music->data.mp3,0);
   479 			SMPEG_setvolume(music->data.mp3,((float)music_volume/(float)MIX_MAX_VOLUME)*100.0);
   480 			SMPEG_play(music->data.mp3);
   481 			break;
   482 #endif
   483 		default:
   484 			/* Unknown music type?? */
   485 			return(-1);
   486 	}
   487 	return(0);
   488 }
   489 
   490 /* Play a music chunk.  Returns 0, or -1 if there was an error.
   491 */
   492 int Mix_PlayMusic(Mix_Music *music, int loops)
   493 {
   494 	/* Don't play null pointers :-) */
   495 	if ( music == NULL ) {
   496 		return(-1);
   497 	}
   498 	/* If the current music is fading out, wait for the fade to complete */
   499 	while ( music_playing && !music_stopped && music_playing->fading==MIX_FADING_OUT ) {
   500 		SDL_Delay(100);
   501 	}
   502 
   503 	if ( lowlevel_play(music) < 0 ) {
   504 		return(-1);
   505     }
   506 	music_active = 1;
   507 	music_stopped = 0;
   508 	music_loops = loops;
   509 	music_playing = music;
   510 	music_playing->fading = MIX_NO_FADING;
   511 	return(0);
   512 }
   513 
   514 /* Fade in a music over "ms" milliseconds */
   515 int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
   516 {
   517 	if ( music && music_volume > 0 ) { /* No need to fade if we can't hear it */
   518 		music->fade_volume = music_volume;
   519 		music_volume = 0;
   520 		if ( Mix_PlayMusic(music, loops) < 0 ) {
   521 			return(-1);
   522         }
   523 		music_playing->fade_step = 0;
   524 		music_playing->fade_steps = ms/ms_per_step;
   525 		music_playing->fading = MIX_FADING_IN;
   526 	}
   527 	return(0);
   528 }
   529 
   530 /* Set the music volume */
   531 int Mix_VolumeMusic(int volume)
   532 {
   533 	int prev_volume;
   534 
   535 	prev_volume = music_volume;
   536 	if ( volume < 0 ) {
   537 		volume = 0;
   538 	}
   539 	if ( volume > SDL_MIX_MAXVOLUME ) {
   540 		volume = SDL_MIX_MAXVOLUME;
   541 	}
   542 	music_volume = volume;
   543 	if ( music_playing && !music_stopped ) {
   544 		switch (music_playing->type) {
   545 #ifdef CMD_MUSIC
   546 		case MUS_CMD:
   547 			MusicCMD_SetVolume(music_volume);
   548 			break;
   549 #endif
   550 #ifdef WAV_MUSIC
   551 		case MUS_WAV:
   552 			WAVStream_SetVolume(music_volume);
   553 			break;
   554 #endif
   555 #ifdef MOD_MUSIC
   556 		case MUS_MOD:
   557 			Player_SetVolume(music_volume);
   558 			break;
   559 #endif
   560 #ifdef MID_MUSIC
   561 		case MUS_MID:
   562 			Timidity_SetVolume(music_volume);
   563 			break;
   564 #endif
   565 #ifdef MP3_MUSIC
   566 		case MUS_MP3:
   567 			SMPEG_setvolume(music_playing->data.mp3,((float)music_volume/(float)MIX_MAX_VOLUME)*100.0);
   568 			break;
   569 #endif
   570 		default:
   571 			/* Unknown music type?? */
   572 			break;
   573 		}
   574 	}
   575 	return(prev_volume);
   576 }
   577 
   578 static void lowlevel_halt(void)
   579 {
   580 	switch (music_playing->type) {
   581 #ifdef CMD_MUSIC
   582 	case MUS_CMD:
   583 		MusicCMD_Stop(music_playing->data.cmd);
   584 		break;
   585 #endif
   586 #ifdef WAV_MUSIC
   587 	case MUS_WAV:
   588 		WAVStream_Stop();
   589 		break;
   590 #endif
   591 #ifdef MOD_MUSIC
   592 	case MUS_MOD:
   593 		Player_Stop();
   594 		break;
   595 #endif
   596 #ifdef MID_MUSIC
   597 	case MUS_MID:
   598 		Timidity_Stop();
   599 		break;
   600 #endif
   601 #ifdef MP3_MUSIC
   602 	case MUS_MP3:
   603 		SMPEG_stop(music_playing->data.mp3);
   604 		break;
   605 #endif
   606 	default:
   607 		/* Unknown music type?? */
   608 		return;
   609 	}
   610 	if ( music_playing->fading != MIX_NO_FADING ) /* Restore volume */
   611 		music_volume = music_playing->fade_volume;
   612 	music_playing->fading = MIX_NO_FADING;
   613 	music_playing = NULL;
   614 	music_active = 0;
   615 	music_loops = 0;
   616 	music_stopped = 0;
   617 }
   618 
   619 /* Halt playing of music */
   620 int Mix_HaltMusic(void)
   621 {
   622 	if ( music_playing && !music_stopped ) {
   623 		/* Mark the music to be stopped from the sound thread */
   624 		music_stopped = 1;
   625 		/* Wait for it to be actually stopped */
   626 		while ( music_playing )
   627 			SDL_Delay(10);
   628 	}
   629 	return(0);
   630 }
   631 
   632 /* Progressively stop the music */
   633 int Mix_FadeOutMusic(int ms)
   634 {
   635 	if ( music_playing && !music_stopped && (music_playing->fading == MIX_NO_FADING) ) {
   636 		if ( music_volume > 0 ) {
   637 			music_playing->fading = MIX_FADING_OUT;
   638 			music_playing->fade_volume = music_volume;
   639 		    music_playing->fade_step = 0;
   640 		    music_playing->fade_steps = ms/ms_per_step;
   641 			return(1);
   642 		}
   643 	}
   644 	return(0);
   645 }
   646 
   647 Mix_Fading Mix_FadingMusic(void)
   648 {
   649 	if( music_playing && !music_stopped )
   650 		return music_playing->fading;
   651 	return MIX_NO_FADING;
   652 }
   653 
   654 /* Pause/Resume the music stream */
   655 void Mix_PauseMusic(void)
   656 {
   657 	if ( music_playing && !music_stopped ) {
   658 		music_active = 0;
   659 	}
   660 }
   661 
   662 void Mix_ResumeMusic(void)
   663 {
   664 	if ( music_playing && !music_stopped ) {
   665 		music_active = 1;
   666 	}
   667 }
   668 
   669 void Mix_RewindMusic(void)
   670 {
   671 	if ( music_playing && !music_stopped ) {
   672 		switch ( music_playing->type ) {
   673 #ifdef MP3_MUSIC
   674 		case MUS_MP3:
   675 			SMPEG_rewind(music_playing->data.mp3);
   676 			break;
   677 #endif
   678 			/* TODO: Implement this for other music backends */
   679 		}
   680 	}
   681 }
   682 
   683 int Mix_PausedMusic(void)
   684 {
   685 	return (music_active == 0);
   686 }
   687 
   688 /* Check the status of the music */
   689 int Mix_PlayingMusic(void)
   690 {
   691 	if ( music_playing && ! music_stopped ) {
   692 		switch (music_playing->type) {
   693 #ifdef CMD_MUSIC
   694 			case MUS_CMD:
   695 				if (!MusicCMD_Active(music_playing->data.cmd)) {
   696 					return(0);
   697 				}
   698 				break;
   699 #endif
   700 #ifdef WAV_MUSIC
   701 			case MUS_WAV:
   702 				if ( ! WAVStream_Active() ) {
   703 					return(0);
   704 				}
   705 				break;
   706 #endif
   707 #ifdef MOD_MUSIC
   708 			case MUS_MOD:
   709 				if ( ! Player_Active() ) {
   710 					return(0);
   711 				}
   712 				break;
   713 #endif
   714 #ifdef MID_MUSIC
   715 			case MUS_MID:
   716 				if ( ! Timidity_Active() ) {
   717 					return(0);
   718 				}
   719 				break;
   720 #endif
   721 #ifdef MP3_MUSIC
   722 			case MUS_MP3:
   723 				if(SMPEG_status(music_playing->data.mp3)!=SMPEG_PLAYING)
   724 					return(0);
   725 				break;
   726 #endif
   727 		}
   728 		return(1);
   729 	}
   730 	return(0);
   731 }
   732 
   733 /* Set the external music playback command */
   734 int Mix_SetMusicCMD(const char *command)
   735 {
   736 	Mix_HaltMusic();
   737 	if ( music_cmd ) {
   738 		free(music_cmd);
   739 		music_cmd = NULL;
   740 	}
   741 	if ( command ) {
   742 		music_cmd = (char *)malloc(strlen(command)+1);
   743 		if ( music_cmd == NULL ) {
   744 			return(-1);
   745 		}
   746 		strcpy(music_cmd, command);
   747 	}
   748 	return(0);
   749 }
   750 
   751 /* Uninitialize the music players */
   752 void close_music(void)
   753 {
   754 	Mix_HaltMusic();
   755 #ifdef CMD_MUSIC
   756 	Mix_SetMusicCMD(NULL);
   757 #endif
   758 #ifdef MOD_MUSIC
   759 	MikMod_Exit();
   760 #endif
   761 }
   762