Sam Lantinga - Thu May 16 11:26:46 PDT 2002
authorSam Lantinga <slouken@libsdl.org>
Thu, 16 May 2002 18:28:06 +0000
changeset 1730821a4ea0008
parent 172 fb810079d5f1
child 174 f9648fd517de
Sam Lantinga - Thu May 16 11:26:46 PDT 2002
* Cleaned up threading issues in the music playback code
CHANGES
SDL_mixer.h
music.c
wavestream.c
     1.1 --- a/CHANGES	Fri May 03 04:09:27 2002 +0000
     1.2 +++ b/CHANGES	Thu May 16 18:28:06 2002 +0000
     1.3 @@ -1,5 +1,7 @@
     1.4  
     1.5  1.2.4:
     1.6 +Sam Lantinga - Thu May 16 11:26:46 PDT 2002
     1.7 + * Cleaned up threading issues in the music playback code
     1.8  Ryan Gordon - Thu May  2 21:08:48 PDT 2002
     1.9   * Fixed deadlock introduced in the last release
    1.10  
     2.1 --- a/SDL_mixer.h	Fri May 03 04:09:27 2002 +0000
     2.2 +++ b/SDL_mixer.h	Thu May 16 18:28:06 2002 +0000
     2.3 @@ -141,7 +141,9 @@
     2.4  extern DECLSPEC void SDLCALL Mix_HookMusic(void (*mix_func)
     2.5                            (void *udata, Uint8 *stream, int len), void *arg);
     2.6  
     2.7 -/* Add your own callback when the music has finished playing. */
     2.8 +/* Add your own callback when the music has finished playing.
     2.9 +   This callback is only called if the music finishes naturally.
    2.10 + */
    2.11  extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (*music_finished)(void));
    2.12  
    2.13  /* Get a pointer to the user data for the current music hook */
     3.1 --- a/music.c	Fri May 03 04:09:27 2002 +0000
     3.2 +++ b/music.c	Thu May 16 18:28:06 2002 +0000
     3.3 @@ -121,7 +121,6 @@
     3.4  #endif
     3.5  	} data;
     3.6  	Mix_Fading fading;
     3.7 -	int fade_volume;
     3.8  	int fade_step;
     3.9  	int fade_steps;
    3.10  	int error;
    3.11 @@ -140,8 +139,11 @@
    3.12  static int ms_per_step;
    3.13  
    3.14  /* Local low-level functions prototypes */
    3.15 -static void lowlevel_halt(void);
    3.16 -static int  lowlevel_play(Mix_Music *music);
    3.17 +static void music_internal_volume(int volume);
    3.18 +static int  music_internal_play(Mix_Music *music, double position);
    3.19 +static int  music_internal_position(double position);
    3.20 +static int  music_internal_playing();
    3.21 +static void music_internal_halt(void);
    3.22  
    3.23  
    3.24  /* Support for hooking when the music has finished */
    3.25 @@ -158,53 +160,43 @@
    3.26  /* Mixing function */
    3.27  void music_mixer(void *udata, Uint8 *stream, int len)
    3.28  {
    3.29 -	if ( music_playing ) {
    3.30 -		if ( music_stopped ) {
    3.31 -			/* To avoid concurrency problems and the use of mutexes,
    3.32 -			   the music is always stopped from the sound thread */
    3.33 -			lowlevel_halt(); /* This function sets music_playing to NULL */
    3.34 -			return;
    3.35 -		}
    3.36 +	if ( music_playing && music_active ) {
    3.37  		/* Handle fading */
    3.38  		if ( music_playing->fading != MIX_NO_FADING ) {
    3.39  			if ( music_playing->fade_step++ < music_playing->fade_steps ) {
    3.40 -				int fade_volume = music_playing->fade_volume;
    3.41 +				int volume;
    3.42  				int fade_step = music_playing->fade_step;
    3.43  				int fade_steps = music_playing->fade_steps;
    3.44  
    3.45  				if ( music_playing->fading == MIX_FADING_OUT ) {
    3.46 -					Mix_VolumeMusic((fade_volume * (fade_steps-fade_step))
    3.47 -									/ fade_steps);
    3.48 +					volume = (music_volume * (fade_steps-fade_step)) / fade_steps;
    3.49  				} else { /* Fading in */
    3.50 -					Mix_VolumeMusic((fade_volume * fade_step) / fade_steps);
    3.51 +					volume = (music_volume * fade_step) / fade_steps;
    3.52  				}
    3.53 +				music_internal_volume(volume);
    3.54  			} else {
    3.55  				if ( music_playing->fading == MIX_FADING_OUT ) {
    3.56 -					lowlevel_halt();
    3.57 +					music_internal_halt();
    3.58 +					if ( music_finished_hook ) {
    3.59 +						music_finished_hook();
    3.60 +					}
    3.61  					return;
    3.62  				}
    3.63  				music_playing->fading = MIX_NO_FADING;
    3.64  			}
    3.65  		}
    3.66  		/* Restart music if it has to loop */
    3.67 -		if ( !Mix_PlayingMusic() ) {
    3.68 -			/* Restart music if it has to loop */
    3.69 +		if ( !music_internal_playing() ) {
    3.70 +			/* Restart music if it has to loop at a high level */
    3.71  			if ( music_loops && --music_loops ) {
    3.72 -				Mix_RewindMusic();
    3.73 -				if ( lowlevel_play(music_playing) < 0 ) {
    3.74 -					fprintf(stderr,"Warning: Music restart failed.\n");
    3.75 -					music_stopped = 1; /* Something went wrong */
    3.76 -					music_playing->fading = MIX_NO_FADING;
    3.77 +				music_internal_play(music_playing, 0.0);
    3.78 +			} else {
    3.79 +				music_internal_halt();
    3.80 +				if ( music_finished_hook ) {
    3.81 +					music_finished_hook();
    3.82  				}
    3.83 +				return;
    3.84  			}
    3.85 -			else if (music_finished_hook) {
    3.86 -			    lowlevel_halt();
    3.87 -			    music_finished_hook();
    3.88 -			    return;
    3.89 -			}
    3.90 -		}
    3.91 -		if ( music_volume <= 0 ) { /* Don't mix if volume is null */
    3.92 -			return;
    3.93  		}
    3.94  		switch (music_playing->type) {
    3.95  #ifdef CMD_MUSIC
    3.96 @@ -535,16 +527,20 @@
    3.97  void Mix_FreeMusic(Mix_Music *music)
    3.98  {
    3.99  	if ( music ) {
   3.100 -		/* Caution: If music is playing, mixer will crash */
   3.101 -		if ( music == music_playing && !music_stopped ) {
   3.102 -			if ( music->fading == MIX_FADING_OUT ) {
   3.103 -				/* Wait for the fade out to finish */
   3.104 -				while ( music_playing && !music_stopped && (music_playing->fading == MIX_FADING_OUT) )
   3.105 -					SDL_Delay(100);
   3.106 -			} else {
   3.107 -				Mix_HaltMusic(); /* Stop it immediately */
   3.108 +		/* Stop the music if it's currently playing */
   3.109 +		SDL_LockAudio();
   3.110 +		if ( music == music_playing ) {
   3.111 +			/* Wait for any fade out to finish */
   3.112 +			while ( music->fading == MIX_FADING_OUT ) {
   3.113 +				SDL_UnlockAudio();
   3.114 +				SDL_Delay(100);
   3.115 +				SDL_LockAudio();
   3.116 +			}
   3.117 +			if ( music == music_playing ) {
   3.118 +				music_internal_halt();
   3.119  			}
   3.120  		}
   3.121 +		SDL_UnlockAudio();
   3.122  		switch (music->type) {
   3.123  #ifdef CMD_MUSIC
   3.124  			case MUS_CMD:
   3.125 @@ -593,150 +589,234 @@
   3.126  	}
   3.127  }
   3.128  
   3.129 -static int lowlevel_play(Mix_Music *music)
   3.130 +/* Play a music chunk.  Returns 0, or -1 if there was an error.
   3.131 + */
   3.132 +static int music_internal_play(Mix_Music *music, double position)
   3.133  {
   3.134 -	if(!music)
   3.135 -		return(-1);
   3.136 +	int retval = 0;
   3.137  
   3.138 +	/* Note the music we're playing */
   3.139 +	if ( music_playing ) {
   3.140 +		music_internal_halt();
   3.141 +	}
   3.142 +	music_playing = music;
   3.143 +
   3.144 +	/* Set the initial volume */
   3.145 +	if ( music->fading == MIX_FADING_IN ) {
   3.146 +		music_internal_volume(0);
   3.147 +	} else {
   3.148 +		music_internal_volume(music_volume);
   3.149 +	}
   3.150 +
   3.151 +	/* Set up for playback */
   3.152  	switch (music->type) {
   3.153  #ifdef CMD_MUSIC
   3.154 -		case MUS_CMD:
   3.155 -			MusicCMD_SetVolume(music_volume);
   3.156 -			MusicCMD_Start(music->data.cmd);
   3.157 -			break;
   3.158 +	    case MUS_CMD:
   3.159 +		MusicCMD_Start(music->data.cmd);
   3.160 +		break;
   3.161  #endif
   3.162  #ifdef WAV_MUSIC
   3.163 -		case MUS_WAV:
   3.164 -			WAVStream_SetVolume(music_volume);
   3.165 -			WAVStream_Start(music->data.wave);
   3.166 -			break;
   3.167 +	    case MUS_WAV:
   3.168 +		WAVStream_Start(music->data.wave);
   3.169 +		break;
   3.170  #endif
   3.171  #ifdef MOD_MUSIC
   3.172 -		case MUS_MOD:
   3.173 -			Player_SetVolume((SWORD)music_volume);
   3.174 -			Player_Start(music->data.module);
   3.175 -			Player_SetPosition(0);
   3.176 -			break;
   3.177 +	    case MUS_MOD:
   3.178 +		Player_Start(music->data.module);
   3.179 +		break;
   3.180  #endif
   3.181  #ifdef MID_MUSIC
   3.182 -		case MUS_MID:
   3.183 +	    case MUS_MID:
   3.184  #ifdef USE_NATIVE_MIDI
   3.185 -  			if ( native_midi_ok ) {
   3.186 -				native_midi_setvolume(music_volume);
   3.187 -				native_midi_start(music->data.nativemidi);
   3.188 -			} MIDI_ELSE
   3.189 +		if ( native_midi_ok ) {
   3.190 +			native_midi_start(music->data.nativemidi);
   3.191 +		} MIDI_ELSE
   3.192  #endif
   3.193  #ifdef USE_TIMIDITY_MIDI
   3.194 -			if ( timidity_ok ) {
   3.195 -				Timidity_SetVolume(music_volume);
   3.196 -				Timidity_Start(music->data.midi);
   3.197 -			}
   3.198 +		if ( timidity_ok ) {
   3.199 +			Timidity_Start(music->data.midi);
   3.200 +		}
   3.201  #endif
   3.202 -			break;
   3.203 +		break;
   3.204  #endif
   3.205  #ifdef OGG_MUSIC
   3.206 -		case MUS_OGG:
   3.207 -			OGG_setvolume(music->data.ogg, music_volume);
   3.208 -			OGG_play(music->data.ogg);
   3.209 -			break;
   3.210 +	    case MUS_OGG:
   3.211 +		OGG_play(music->data.ogg);
   3.212 +		break;
   3.213  #endif
   3.214  #ifdef MP3_MUSIC
   3.215 -		case MUS_MP3:
   3.216 -			SMPEG_enableaudio(music->data.mp3,1);
   3.217 -			SMPEG_enablevideo(music->data.mp3,0);
   3.218 -			SMPEG_setvolume(music->data.mp3,(int)(((float)music_volume/(float)MIX_MAX_VOLUME)*100.0));
   3.219 -			SMPEG_play(music->data.mp3);
   3.220 -			break;
   3.221 +	    case MUS_MP3:
   3.222 +		SMPEG_enableaudio(music->data.mp3,1);
   3.223 +		SMPEG_enablevideo(music->data.mp3,0);
   3.224 +		SMPEG_play(music->data.mp3);
   3.225 +		break;
   3.226  #endif
   3.227 -		default:
   3.228 -			/* Unknown music type?? */
   3.229 -			return(-1);
   3.230 +	    default:
   3.231 +		Mix_SetError("Can't play unknown music type");
   3.232 +		retval = -1;
   3.233 +		break;
   3.234  	}
   3.235 -	return(0);
   3.236 +
   3.237 +	/* Set the playback position, note any errors if an offset is used */
   3.238 +	if ( retval == 0 ) {
   3.239 +		if ( position > 0.0 ) {
   3.240 +			if ( music_internal_position(position) < 0 ) {
   3.241 +				Mix_SetError("Position not implemented for music type");
   3.242 +				retval = -1;
   3.243 +			}
   3.244 +		} else {
   3.245 +			music_internal_position(0.0);
   3.246 +		}
   3.247 +	}
   3.248 +
   3.249 +	/* If the setup failed, we're not playing any music anymore */
   3.250 +	if ( retval < 0 ) {
   3.251 +		music_playing = NULL;
   3.252 +	}
   3.253 +	return(retval);
   3.254 +}
   3.255 +int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
   3.256 +{
   3.257 +	int retval;
   3.258 +
   3.259 +	/* Don't play null pointers :-) */
   3.260 +	if ( music == NULL ) {
   3.261 +		Mix_SetError("music parameter was NULL");
   3.262 +		return(-1);
   3.263 +	}
   3.264 +
   3.265 +	/* Setup the data */
   3.266 +	if ( ms ) {
   3.267 +		music->fading = MIX_FADING_IN;
   3.268 +	} else {
   3.269 +		music->fading = MIX_NO_FADING;
   3.270 +	}
   3.271 +	music->fade_step = 0;
   3.272 +	music->fade_steps = ms/ms_per_step;
   3.273 +
   3.274 +	/* Play the puppy */
   3.275 +	SDL_LockAudio();
   3.276 +	/* If the current music is fading out, wait for the fade to complete */
   3.277 +	while ( music_playing && (music_playing->fading == MIX_FADING_OUT) ) {
   3.278 +		SDL_UnlockAudio();
   3.279 +		SDL_Delay(100);
   3.280 +		SDL_LockAudio();
   3.281 +	}
   3.282 +	music_active = 1;
   3.283 +	music_loops = loops;
   3.284 +	retval = music_internal_play(music, position);
   3.285 +	SDL_UnlockAudio();
   3.286 +
   3.287 +	return(retval);
   3.288 +}
   3.289 +int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
   3.290 +{
   3.291 +	return Mix_FadeInMusicPos(music, loops, ms, 0.0);
   3.292 +}
   3.293 +int Mix_PlayMusic(Mix_Music *music, int loops)
   3.294 +{
   3.295 +	return Mix_FadeInMusicPos(music, loops, 0, 0.0);
   3.296  }
   3.297  
   3.298 -/* Play a music chunk.  Returns 0, or -1 if there was an error.
   3.299 -*/
   3.300 -int Mix_PlayMusic(Mix_Music *music, int loops)
   3.301 +/* Set the playing music position */
   3.302 +int music_internal_position(double position)
   3.303  {
   3.304 -	/* Don't play null pointers :-) */
   3.305 -	if ( music == NULL ) {
   3.306 -		return(-1);
   3.307 +	int retval = 0;
   3.308 +
   3.309 +	switch (music_playing->type) {
   3.310 +#ifdef MOD_MUSIC
   3.311 +	    case MUS_MOD:
   3.312 +		Player_SetPosition((UWORD)position);
   3.313 +		break;
   3.314 +#endif
   3.315 +#ifdef OGG_MUSIC
   3.316 +	    case MUS_OGG:
   3.317 +		OGG_jump_to_time(music_playing->data.ogg, position);
   3.318 +		break;
   3.319 +#endif
   3.320 +#ifdef MP3_MUSIC
   3.321 +	    case MUS_MP3:
   3.322 +		if ( position == 0.0 ) {
   3.323 +			SMPEG_rewind(music_playing->data.mp3);
   3.324 +		} else {
   3.325 +			SMPEG_skip(music_playing->data.mp3, position);
   3.326 +		}
   3.327 +		break;
   3.328 +#endif
   3.329 +	    default:
   3.330 +		/* TODO: Implement this for other music backends */
   3.331 +		retval = -1;
   3.332 +		break;
   3.333  	}
   3.334 -	/* If the current music is fading out, wait for the fade to complete */
   3.335 -	while ( music_playing && !music_stopped && music_playing->fading==MIX_FADING_OUT ) {
   3.336 -		SDL_Delay(100);
   3.337 -	}
   3.338 -
   3.339 -	if ( lowlevel_play(music) < 0 ) {
   3.340 -		return(-1);
   3.341 -	}
   3.342 -	music_active = 1;
   3.343 -	music_stopped = 0;
   3.344 -	music_loops = loops;
   3.345 -	music_playing = music;
   3.346 -	music_playing->fading = MIX_NO_FADING;
   3.347 -	return(0);
   3.348 +	return(retval);
   3.349  }
   3.350 -
   3.351  int Mix_SetMusicPosition(double position)
   3.352  {
   3.353 -	if ( music_playing && !music_stopped ) {
   3.354 -		switch ( music_playing->type ) {
   3.355 -#ifdef MOD_MUSIC
   3.356 -		case MUS_MOD:
   3.357 -			Player_SetPosition((UWORD)position);
   3.358 -			return(0);
   3.359 -			break;
   3.360 -#endif
   3.361 -#ifdef OGG_MUSIC
   3.362 -		case MUS_OGG:
   3.363 -			OGG_jump_to_time(music_playing->data.ogg, position);
   3.364 -			return(0);
   3.365 -			break;
   3.366 -#endif
   3.367 -#ifdef MP3_MUSIC
   3.368 -		case MUS_MP3:
   3.369 -			SMPEG_skip(music_playing->data.mp3, position);
   3.370 -			return(0);
   3.371 -			break;
   3.372 -#endif
   3.373 -		default:
   3.374 -			/* TODO: Implement this for other music backends */
   3.375 -			break;
   3.376 +	int retval;
   3.377 +
   3.378 +	SDL_LockAudio();
   3.379 +	if ( music_playing ) {
   3.380 +		retval = music_internal_position(position);
   3.381 +		if ( retval < 0 ) {
   3.382 +			Mix_SetError("Position not implemented for music type");
   3.383  		}
   3.384 +	} else {
   3.385 +		Mix_SetError("Music isn't playing");
   3.386 +		retval = -1;
   3.387  	}
   3.388 -	return(-1);
   3.389 -}
   3.390 +	SDL_UnlockAudio();
   3.391  
   3.392 -/* Fade in a music over "ms" milliseconds */
   3.393 -int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position)
   3.394 -{
   3.395 -	if ( music && music_volume > 0 ) { /* No need to fade if we can't hear it */
   3.396 -		music->fade_volume = music_volume;
   3.397 -		music_volume = 0;
   3.398 -		if ( Mix_PlayMusic(music, loops) < 0 ) {
   3.399 -			return(-1);
   3.400 -		}
   3.401 -		if ( position ) {
   3.402 -			if ( Mix_SetMusicPosition(position) < 0 ) {
   3.403 -				Mix_HaltMusic();
   3.404 -				return(-1);
   3.405 -			}
   3.406 -		}
   3.407 -		music_playing->fade_step = 0;
   3.408 -		music_playing->fade_steps = ms/ms_per_step;
   3.409 -		music_playing->fading = MIX_FADING_IN;
   3.410 -	}
   3.411 -	return(0);
   3.412 -}
   3.413 -
   3.414 -int Mix_FadeInMusic(Mix_Music *music, int loops, int ms)
   3.415 -{
   3.416 -	return Mix_FadeInMusicPos(music, loops, ms, 0);
   3.417 +	return(retval);
   3.418  }
   3.419  
   3.420  /* Set the music volume */
   3.421 +static void music_internal_volume(int volume)
   3.422 +{
   3.423 +	switch (music_playing->type) {
   3.424 +#ifdef CMD_MUSIC
   3.425 +	    case MUS_CMD:
   3.426 +		MusicCMD_SetVolume(volume);
   3.427 +		break;
   3.428 +#endif
   3.429 +#ifdef WAV_MUSIC
   3.430 +	    case MUS_WAV:
   3.431 +		WAVStream_SetVolume(volume);
   3.432 +		break;
   3.433 +#endif
   3.434 +#ifdef MOD_MUSIC
   3.435 +	    case MUS_MOD:
   3.436 +		Player_SetVolume((SWORD)volume);
   3.437 +		break;
   3.438 +#endif
   3.439 +#ifdef MID_MUSIC
   3.440 +	    case MUS_MID:
   3.441 +#ifdef USE_NATIVE_MIDI
   3.442 +		if ( native_midi_ok ) {
   3.443 +			native_midi_setvolume(volume);
   3.444 +		} MIDI_ELSE
   3.445 +#endif
   3.446 +#ifdef USE_TIMIDITY_MIDI
   3.447 +		if ( timidity_ok ) {
   3.448 +			Timidity_SetVolume(volume);
   3.449 +		}
   3.450 +#endif
   3.451 +		break;
   3.452 +#endif
   3.453 +#ifdef OGG_MUSIC
   3.454 +	    case MUS_OGG:
   3.455 +		OGG_setvolume(music_playing->data.ogg, volume);
   3.456 +		break;
   3.457 +#endif
   3.458 +#ifdef MP3_MUSIC
   3.459 +	    case MUS_MP3:
   3.460 +		SMPEG_setvolume(music_playing->data.mp3,(int)(((float)volume/(float)MIX_MAX_VOLUME)*100.0));
   3.461 +		break;
   3.462 +#endif
   3.463 +	    default:
   3.464 +		/* Unknown music type?? */
   3.465 +		break;
   3.466 +	}
   3.467 +}
   3.468  int Mix_VolumeMusic(int volume)
   3.469  {
   3.470  	int prev_volume;
   3.471 @@ -749,75 +829,35 @@
   3.472  		volume = SDL_MIX_MAXVOLUME;
   3.473  	}
   3.474  	music_volume = volume;
   3.475 -	if ( music_playing && !music_stopped ) {
   3.476 -		switch (music_playing->type) {
   3.477 -#ifdef CMD_MUSIC
   3.478 -		case MUS_CMD:
   3.479 -			MusicCMD_SetVolume(music_volume);
   3.480 -			break;
   3.481 -#endif
   3.482 -#ifdef WAV_MUSIC
   3.483 -		case MUS_WAV:
   3.484 -			WAVStream_SetVolume(music_volume);
   3.485 -			break;
   3.486 -#endif
   3.487 -#ifdef MOD_MUSIC
   3.488 -		case MUS_MOD:
   3.489 -			Player_SetVolume((SWORD)music_volume);
   3.490 -			break;
   3.491 -#endif
   3.492 -#ifdef MID_MUSIC
   3.493 -		case MUS_MID:
   3.494 -#ifdef USE_NATIVE_MIDI
   3.495 -			if ( native_midi_ok ) {
   3.496 -				native_midi_setvolume(music_volume);
   3.497 -			} MIDI_ELSE
   3.498 -#endif
   3.499 -#ifdef USE_TIMIDITY_MIDI
   3.500 -			if ( timidity_ok ) {
   3.501 -				Timidity_SetVolume(music_volume);
   3.502 -			}
   3.503 -#endif
   3.504 -			break;
   3.505 -#endif
   3.506 -#ifdef OGG_MUSIC
   3.507 -		case MUS_OGG:
   3.508 -			OGG_setvolume(music_playing->data.ogg, music_volume);
   3.509 -			break;
   3.510 -#endif
   3.511 -#ifdef MP3_MUSIC
   3.512 -		case MUS_MP3:
   3.513 -			SMPEG_setvolume(music_playing->data.mp3,(int)(((float)music_volume/(float)MIX_MAX_VOLUME)*100.0));
   3.514 -			break;
   3.515 -#endif
   3.516 -		default:
   3.517 -			/* Unknown music type?? */
   3.518 -			break;
   3.519 -		}
   3.520 +	SDL_LockAudio();
   3.521 +	if ( music_playing ) {
   3.522 +		music_internal_volume(music_volume);
   3.523  	}
   3.524 +	SDL_UnlockAudio();
   3.525  	return(prev_volume);
   3.526  }
   3.527  
   3.528 -static void lowlevel_halt(void)
   3.529 +/* Halt playing of music */
   3.530 +static void music_internal_halt(void)
   3.531  {
   3.532  	switch (music_playing->type) {
   3.533  #ifdef CMD_MUSIC
   3.534 -	case MUS_CMD:
   3.535 +	    case MUS_CMD:
   3.536  		MusicCMD_Stop(music_playing->data.cmd);
   3.537  		break;
   3.538  #endif
   3.539  #ifdef WAV_MUSIC
   3.540 -	case MUS_WAV:
   3.541 +	    case MUS_WAV:
   3.542  		WAVStream_Stop();
   3.543  		break;
   3.544  #endif
   3.545  #ifdef MOD_MUSIC
   3.546 -	case MUS_MOD:
   3.547 +	    case MUS_MOD:
   3.548  		Player_Stop();
   3.549  		break;
   3.550  #endif
   3.551  #ifdef MID_MUSIC
   3.552 -	case MUS_MID:
   3.553 +	    case MUS_MID:
   3.554  #ifdef USE_NATIVE_MIDI
   3.555  		if ( native_midi_ok ) {
   3.556  			native_midi_stop();
   3.557 @@ -831,113 +871,77 @@
   3.558  		break;
   3.559  #endif
   3.560  #ifdef OGG_MUSIC
   3.561 -	case MUS_OGG:
   3.562 +	    case MUS_OGG:
   3.563  		OGG_stop(music_playing->data.ogg);
   3.564  		break;
   3.565  #endif
   3.566  #ifdef MP3_MUSIC
   3.567 -	case MUS_MP3:
   3.568 +	    case MUS_MP3:
   3.569  		SMPEG_stop(music_playing->data.mp3);
   3.570  		break;
   3.571  #endif
   3.572 -	default:
   3.573 +	    default:
   3.574  		/* Unknown music type?? */
   3.575  		return;
   3.576  	}
   3.577 -	if ( music_playing->fading != MIX_NO_FADING ) /* Restore volume */
   3.578 -		music_volume = music_playing->fade_volume;
   3.579  	music_playing->fading = MIX_NO_FADING;
   3.580  	music_playing = NULL;
   3.581 -	music_active = 0;
   3.582 -	music_loops = 0;
   3.583 -	music_stopped = 0;
   3.584  }
   3.585 -
   3.586 -/* Halt playing of music */
   3.587  int Mix_HaltMusic(void)
   3.588  {
   3.589 -	if ( music_playing && !music_stopped ) {
   3.590 -		/* Mark the music to be stopped from the sound thread */
   3.591 -		music_stopped = 1;
   3.592 -		/* Wait for it to be actually stopped */
   3.593 -		while ( music_playing && music_active )
   3.594 -			SDL_Delay(10);
   3.595 +	SDL_LockAudio();
   3.596 +	if ( music_playing ) {
   3.597 +		music_internal_halt();
   3.598  	}
   3.599 +	SDL_UnlockAudio();
   3.600 +
   3.601  	return(0);
   3.602  }
   3.603  
   3.604  /* Progressively stop the music */
   3.605  int Mix_FadeOutMusic(int ms)
   3.606  {
   3.607 -	if ( music_playing && !music_stopped &&
   3.608 -	     (music_playing->fading == MIX_NO_FADING) ) {
   3.609 -		if ( music_volume > 0 ) {
   3.610 -			music_playing->fading = MIX_FADING_OUT;
   3.611 -			music_playing->fade_volume = music_volume;
   3.612 -			music_playing->fade_step = 0;
   3.613 -			music_playing->fade_steps = ms/ms_per_step;
   3.614 -			return(1);
   3.615 -		}
   3.616 +	int retval = 0;
   3.617 +
   3.618 +	SDL_LockAudio();
   3.619 +	if ( music_playing && (music_playing->fading == MIX_NO_FADING) ) {
   3.620 +		music_playing->fading = MIX_FADING_OUT;
   3.621 +		music_playing->fade_step = 0;
   3.622 +		music_playing->fade_steps = ms/ms_per_step;
   3.623 +		retval = 1;
   3.624  	}
   3.625 -	return(0);
   3.626 +	SDL_UnlockAudio();
   3.627 +
   3.628 +	return(retval);
   3.629  }
   3.630  
   3.631  Mix_Fading Mix_FadingMusic(void)
   3.632  {
   3.633 -	if( music_playing && !music_stopped )
   3.634 -		return music_playing->fading;
   3.635 -	return MIX_NO_FADING;
   3.636 +	Mix_Fading fading = MIX_NO_FADING;
   3.637 +
   3.638 +	SDL_LockAudio();
   3.639 +	if ( music_playing ) {
   3.640 +		fading = music_playing->fading;
   3.641 +	}
   3.642 +	SDL_UnlockAudio();
   3.643 +
   3.644 +	return(fading);
   3.645  }
   3.646  
   3.647  /* Pause/Resume the music stream */
   3.648  void Mix_PauseMusic(void)
   3.649  {
   3.650 -	if ( music_playing && !music_stopped ) {
   3.651 -		music_active = 0;
   3.652 -	}
   3.653 +	music_active = 0;
   3.654  }
   3.655  
   3.656  void Mix_ResumeMusic(void)
   3.657  {
   3.658 -	if ( music_playing && !music_stopped ) {
   3.659 -		music_active = 1;
   3.660 -	}
   3.661 +	music_active = 1;
   3.662  }
   3.663  
   3.664  void Mix_RewindMusic(void)
   3.665  {
   3.666 -	if ( music_playing && !music_stopped ) {
   3.667 -		switch ( music_playing->type ) {
   3.668 -#ifdef MOD_MUSIC
   3.669 -		case MUS_MOD:
   3.670 -			Player_Start(music_playing->data.module);
   3.671 -			Player_SetPosition(0);
   3.672 -			break;
   3.673 -#endif
   3.674 -#ifdef MP3_MUSIC
   3.675 -		case MUS_MP3:
   3.676 -			SMPEG_rewind(music_playing->data.mp3);
   3.677 -			break;
   3.678 -#endif
   3.679 -#ifdef OGG_MUSIC
   3.680 -		case MUS_OGG:
   3.681 -			OGG_jump_to_time(music_playing->data.ogg, 0);
   3.682 -			break;
   3.683 -#endif
   3.684 -#ifdef MID_MUSIC
   3.685 -		case MUS_MID:
   3.686 -#ifdef USE_NATIVE_MIDI
   3.687 -			if ( native_midi_ok ) {
   3.688 -				native_midi_stop();
   3.689 -			}
   3.690 -#endif
   3.691 -			break;
   3.692 -#endif
   3.693 -		default:
   3.694 -			/* TODO: Implement this for other music backends */
   3.695 -			break;
   3.696 -		}
   3.697 -	}
   3.698 +	Mix_SetMusicPosition(0.0);
   3.699  }
   3.700  
   3.701  int Mix_PausedMusic(void)
   3.702 @@ -946,66 +950,77 @@
   3.703  }
   3.704  
   3.705  /* Check the status of the music */
   3.706 +static int music_internal_playing()
   3.707 +{
   3.708 +	int playing = 1;
   3.709 +	switch (music_playing->type) {
   3.710 +#ifdef CMD_MUSIC
   3.711 +	    case MUS_CMD:
   3.712 +		if (!MusicCMD_Active(music_playing->data.cmd)) {
   3.713 +			playing = 0;
   3.714 +		}
   3.715 +		break;
   3.716 +#endif
   3.717 +#ifdef WAV_MUSIC
   3.718 +	    case MUS_WAV:
   3.719 +		if ( ! WAVStream_Active() ) {
   3.720 +			playing = 0;
   3.721 +		}
   3.722 +		break;
   3.723 +#endif
   3.724 +#ifdef MOD_MUSIC
   3.725 +	    case MUS_MOD:
   3.726 +		if ( ! Player_Active() ) {
   3.727 +			playing = 0;
   3.728 +		}
   3.729 +		break;
   3.730 +#endif
   3.731 +#ifdef MID_MUSIC
   3.732 +	    case MUS_MID:
   3.733 +#ifdef USE_NATIVE_MIDI
   3.734 +		if ( native_midi_ok ) {
   3.735 +			if ( ! native_midi_active() )
   3.736 +				playing = 0;
   3.737 +		} MIDI_ELSE
   3.738 +#endif
   3.739 +#ifdef USE_TIMIDITY_MIDI
   3.740 +		if ( timidity_ok ) {
   3.741 +			if ( ! Timidity_Active() )
   3.742 +				playing = 0;
   3.743 +		}
   3.744 +#endif
   3.745 +		break;
   3.746 +#endif
   3.747 +#ifdef OGG_MUSIC
   3.748 +	    case MUS_OGG:
   3.749 +		if ( ! OGG_playing(music_playing->data.ogg) ) {
   3.750 +			playing = 0;
   3.751 +		}
   3.752 +		break;
   3.753 +#endif
   3.754 +#ifdef MP3_MUSIC
   3.755 +	    case MUS_MP3:
   3.756 +		if ( SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING )
   3.757 +			playing = 0;
   3.758 +		break;
   3.759 +#endif
   3.760 +	    default:
   3.761 +		playing = 0;
   3.762 +		break;
   3.763 +	}
   3.764 +	return(playing);
   3.765 +}
   3.766  int Mix_PlayingMusic(void)
   3.767  {
   3.768 -	if ( music_playing && ! music_stopped ) {
   3.769 -		switch (music_playing->type) {
   3.770 -#ifdef CMD_MUSIC
   3.771 -			case MUS_CMD:
   3.772 -				if (!MusicCMD_Active(music_playing->data.cmd)) {
   3.773 -					return(0);
   3.774 -				}
   3.775 -				break;
   3.776 -#endif
   3.777 -#ifdef WAV_MUSIC
   3.778 -			case MUS_WAV:
   3.779 -				if ( ! WAVStream_Active() ) {
   3.780 -					return(0);
   3.781 -				}
   3.782 -				break;
   3.783 -#endif
   3.784 -#ifdef MOD_MUSIC
   3.785 -			case MUS_MOD:
   3.786 -				if ( ! Player_Active() ) {
   3.787 -					return(0);
   3.788 -				}
   3.789 -				break;
   3.790 -#endif
   3.791 -#ifdef MID_MUSIC
   3.792 -			case MUS_MID:
   3.793 -#ifdef USE_NATIVE_MIDI
   3.794 -				if ( native_midi_ok ) {
   3.795 -					if ( ! native_midi_active() )
   3.796 -						return(0);
   3.797 -				} MIDI_ELSE
   3.798 -#endif
   3.799 -#ifdef USE_TIMIDITY_MIDI
   3.800 -				if ( timidity_ok ) {
   3.801 -					if ( ! Timidity_Active() )
   3.802 -						return(0);
   3.803 -				}
   3.804 -#endif
   3.805 -				break;
   3.806 -#endif
   3.807 -#ifdef OGG_MUSIC
   3.808 -			case MUS_OGG:
   3.809 -				if ( ! OGG_playing(music_playing->data.ogg) ) {
   3.810 -					return(0);
   3.811 -				}
   3.812 -				break;
   3.813 -#endif
   3.814 -#ifdef MP3_MUSIC
   3.815 -			case MUS_MP3:
   3.816 -				if ( SMPEG_status(music_playing->data.mp3) != SMPEG_PLAYING )
   3.817 -					return(0);
   3.818 -				break;
   3.819 -#endif
   3.820 -			default:
   3.821 -				break;
   3.822 -		}
   3.823 -		return(1);
   3.824 +	int playing = 0;
   3.825 +
   3.826 +	SDL_LockAudio();
   3.827 +	if ( music_playing ) {
   3.828 +		playing = music_internal_playing();
   3.829  	}
   3.830 -	return(0);
   3.831 +	SDL_UnlockAudio();
   3.832 +
   3.833 +	return(playing);
   3.834  }
   3.835  
   3.836  /* Set the external music playback command */
   3.837 @@ -1031,17 +1046,17 @@
   3.838  	if ( music_playing && ! music_stopped ) {
   3.839  		switch (music_playing->type) {
   3.840  #ifdef MOD_MUSIC
   3.841 -			case MUS_MOD:
   3.842 -				if ( ! Player_Active() ) {
   3.843 -					return(-1);
   3.844 -				}
   3.845 -				Player_SetSynchroValue(i);
   3.846 -				return 0;
   3.847 -				break;
   3.848 +		    case MUS_MOD:
   3.849 +			if ( ! Player_Active() ) {
   3.850 +				return(-1);
   3.851 +			}
   3.852 +			Player_SetSynchroValue(i);
   3.853 +			return 0;
   3.854 +			break;
   3.855  #endif
   3.856 -			default:
   3.857 -				return(-1);
   3.858 -				break;
   3.859 +		    default:
   3.860 +			return(-1);
   3.861 +			break;
   3.862  		}
   3.863  		return(-1);
   3.864  	}
   3.865 @@ -1053,16 +1068,16 @@
   3.866  	if ( music_playing && ! music_stopped ) {
   3.867  		switch (music_playing->type) {
   3.868  #ifdef MOD_MUSIC
   3.869 -			case MUS_MOD:
   3.870 -				if ( ! Player_Active() ) {
   3.871 -					return(-1);
   3.872 -				}
   3.873 -				return Player_GetSynchroValue();
   3.874 -				break;
   3.875 +		    case MUS_MOD:
   3.876 +			if ( ! Player_Active() ) {
   3.877 +				return(-1);
   3.878 +			}
   3.879 +			return Player_GetSynchroValue();
   3.880 +			break;
   3.881  #endif
   3.882 -			default:
   3.883 -				return(-1);
   3.884 -				break;
   3.885 +		    default:
   3.886 +			return(-1);
   3.887 +			break;
   3.888  		}
   3.889  		return(-1);
   3.890  	}
     4.1 --- a/wavestream.c	Fri May 03 04:09:27 2002 +0000
     4.2 +++ b/wavestream.c	Thu May 16 18:28:06 2002 +0000
     4.3 @@ -88,10 +88,7 @@
     4.4  
     4.5  
     4.6  /* Currently we only support a single stream at a time */
     4.7 -static WAVStream *theWave = NULL;
     4.8 -
     4.9 -/* This is initialized by the music mixer */
    4.10 -static SDL_mutex *music_lock = NULL;
    4.11 +static WAVStream *music = NULL;
    4.12  
    4.13  /* This is the format of the audio mixer data */
    4.14  static SDL_AudioSpec mixer;
    4.15 @@ -107,13 +104,6 @@
    4.16   */
    4.17  int WAVStream_Init(SDL_AudioSpec *mixerfmt)
    4.18  {
    4.19 -	/* FIXME: clean up the mutex, or move it into music.c */
    4.20 -	music_lock = SDL_CreateMutex();
    4.21 -#ifndef macintosh /* Hmm.. */
    4.22 -	if ( music_lock == NULL ) {
    4.23 -		return(-1);
    4.24 -	}
    4.25 -#endif
    4.26  	mixer = *mixerfmt;
    4.27  	return(0);
    4.28  }
    4.29 @@ -160,84 +150,68 @@
    4.30  /* Start playback of a given WAV stream */
    4.31  extern void WAVStream_Start(WAVStream *wave)
    4.32  {
    4.33 -	SDL_mutexP(music_lock);
    4.34  	clearerr(wave->wavefp);
    4.35  	fseek(wave->wavefp, wave->start, SEEK_SET);
    4.36 -	theWave = wave;
    4.37 -	SDL_mutexV(music_lock);
    4.38 +	music = wave;
    4.39  }
    4.40  
    4.41 -/* Play some of a stream previously started with WAVStream_Start()
    4.42 -   The music_lock is held while this function is called.
    4.43 - */
    4.44 +/* Play some of a stream previously started with WAVStream_Start() */
    4.45  extern void WAVStream_PlaySome(Uint8 *stream, int len)
    4.46  {
    4.47  	long pos;
    4.48  
    4.49 -	SDL_mutexP(music_lock);
    4.50 -	if ( theWave && ((pos=ftell(theWave->wavefp)) < theWave->stop) ) {
    4.51 -		if ( theWave->cvt.needed ) {
    4.52 +	if ( music && ((pos=ftell(music->wavefp)) < music->stop) ) {
    4.53 +		if ( music->cvt.needed ) {
    4.54  			int original_len;
    4.55  
    4.56 -			original_len=(int)((double)len/theWave->cvt.len_ratio);
    4.57 -			if ( theWave->cvt.len != original_len ) {
    4.58 +			original_len=(int)((double)len/music->cvt.len_ratio);
    4.59 +			if ( music->cvt.len != original_len ) {
    4.60  				int worksize;
    4.61 -				if ( theWave->cvt.buf != NULL ) {
    4.62 -					free(theWave->cvt.buf);
    4.63 +				if ( music->cvt.buf != NULL ) {
    4.64 +					free(music->cvt.buf);
    4.65  				}
    4.66 -				worksize = original_len*theWave->cvt.len_mult;
    4.67 -				theWave->cvt.buf=(Uint8 *)malloc(worksize);
    4.68 -				if ( theWave->cvt.buf == NULL ) {
    4.69 -					SDL_mutexV(music_lock);
    4.70 +				worksize = original_len*music->cvt.len_mult;
    4.71 +				music->cvt.buf=(Uint8 *)malloc(worksize);
    4.72 +				if ( music->cvt.buf == NULL ) {
    4.73  					return;
    4.74  				}
    4.75 -				theWave->cvt.len = original_len;
    4.76 +				music->cvt.len = original_len;
    4.77  			}
    4.78 -			if ( (theWave->stop - pos) < original_len ) {
    4.79 -				original_len = (theWave->stop - pos);
    4.80 +			if ( (music->stop - pos) < original_len ) {
    4.81 +				original_len = (music->stop - pos);
    4.82  			}
    4.83 -			original_len = fread(theWave->cvt.buf,1,original_len,theWave->wavefp);
    4.84 +			original_len = fread(music->cvt.buf,1,original_len,music->wavefp);
    4.85  			/* At least at the time of writing, SDL_ConvertAudio()
    4.86  			   does byte-order swapping starting at the end of the
    4.87  			   buffer. Thus, if we are reading 16-bit samples, we
    4.88  			   had better make damn sure that we get an even
    4.89  			   number of bytes, or we'll get garbage.
    4.90  			 */
    4.91 -			if ( (theWave->cvt.src_format & 0x0010) && (original_len & 1) ) {
    4.92 +			if ( (music->cvt.src_format & 0x0010) && (original_len & 1) ) {
    4.93  				original_len--;
    4.94  			}
    4.95 -			theWave->cvt.len = original_len;
    4.96 -			SDL_ConvertAudio(&theWave->cvt);
    4.97 -			memcpy(stream, theWave->cvt.buf, theWave->cvt.len_cvt);
    4.98 +			music->cvt.len = original_len;
    4.99 +			SDL_ConvertAudio(&music->cvt);
   4.100 +			memcpy(stream, music->cvt.buf, music->cvt.len_cvt);
   4.101  		} else {
   4.102 -			if ( (theWave->stop - pos) < len ) {
   4.103 -				len = (theWave->stop - pos);
   4.104 +			if ( (music->stop - pos) < len ) {
   4.105 +				len = (music->stop - pos);
   4.106  			}
   4.107 -			fread(stream, len, 1, theWave->wavefp);
   4.108 +			fread(stream, len, 1, music->wavefp);
   4.109  		}
   4.110  	}
   4.111 -	SDL_mutexV(music_lock);
   4.112  }
   4.113  
   4.114  /* Stop playback of a stream previously started with WAVStream_Start() */
   4.115  extern void WAVStream_Stop(void)
   4.116  {
   4.117 -	SDL_mutexP(music_lock);
   4.118 -	theWave = NULL;
   4.119 -	SDL_mutexV(music_lock);
   4.120 +	music = NULL;
   4.121  }
   4.122  
   4.123  /* Close the given WAV stream */
   4.124  extern void WAVStream_FreeSong(WAVStream *wave)
   4.125  {
   4.126  	if ( wave ) {
   4.127 -		/* Remove song from the currently playing list */
   4.128 -		SDL_mutexP(music_lock);
   4.129 -		if ( wave == theWave ) {
   4.130 -			theWave = NULL;
   4.131 -		}
   4.132 -		SDL_mutexV(music_lock);
   4.133 -
   4.134  		/* Clean up associated data */
   4.135  		if ( wave->wavefp ) {
   4.136  			fclose(wave->wavefp);
   4.137 @@ -254,13 +228,10 @@
   4.138  {
   4.139  	int active;
   4.140  
   4.141 -	SDL_mutexP(music_lock);
   4.142  	active = 0;
   4.143 -	if ( theWave && (ftell(theWave->wavefp) < theWave->stop) ) {
   4.144 +	if ( music && (ftell(music->wavefp) < music->stop) ) {
   4.145  		active = 1;
   4.146  	}
   4.147 -	SDL_mutexV(music_lock);
   4.148 -
   4.149  	return(active);
   4.150  }
   4.151