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