music.c
changeset 506 586ae09f8176
parent 504 7a95f36a8bbf
child 508 de8e7a4f5936
     1.1 --- a/music.c	Tue Mar 15 23:11:29 2011 -0700
     1.2 +++ b/music.c	Sun Mar 20 14:34:18 2011 +0000
     1.3 @@ -48,14 +48,12 @@
     1.4  #  ifdef USE_TIMIDITY_MIDI
     1.5  #    include "timidity.h"
     1.6  #  endif
     1.7 +#  ifdef USE_FLUIDSYNTH_MIDI
     1.8 +#    include "fluidsynth.h"
     1.9 +#  endif
    1.10  #  ifdef USE_NATIVE_MIDI
    1.11  #    include "native_midi.h"
    1.12  #  endif
    1.13 -#  if defined(USE_TIMIDITY_MIDI) && defined(USE_NATIVE_MIDI)
    1.14 -#    define MIDI_ELSE	else
    1.15 -#  else
    1.16 -#    define MIDI_ELSE
    1.17 -#  endif
    1.18  #endif
    1.19  #ifdef OGG_MUSIC
    1.20  #include "music_ogg.h"
    1.21 @@ -101,6 +99,9 @@
    1.22  #ifdef USE_TIMIDITY_MIDI
    1.23  		MidiSong *midi;
    1.24  #endif
    1.25 +#ifdef USE_FLUIDSYNTH_MIDI
    1.26 +		FluidSynthMidiSong *fluidsynthmidi;
    1.27 +#endif
    1.28  #ifdef USE_NATIVE_MIDI
    1.29  		NativeMidiSong *nativemidi;
    1.30  #endif
    1.31 @@ -128,6 +129,9 @@
    1.32  static int timidity_ok;
    1.33  static int samplesize;
    1.34  #endif
    1.35 +#ifdef USE_FLUIDSYNTH_MIDI
    1.36 +static int fluidsynth_ok;
    1.37 +#endif
    1.38  #ifdef USE_NATIVE_MIDI
    1.39  static int native_midi_ok;
    1.40  #endif
    1.41 @@ -140,6 +144,11 @@
    1.42  static const char **music_decoders = NULL;
    1.43  static int num_decoders = 0;
    1.44  
    1.45 +/* Semicolon-separated SoundFont paths */
    1.46 +#ifdef MID_MUSIC
    1.47 +char* soundfont_paths = NULL;
    1.48 +#endif
    1.49 +
    1.50  int Mix_GetNumMusicDecoders(void)
    1.51  {
    1.52  	return(num_decoders);
    1.53 @@ -270,15 +279,22 @@
    1.54  				break;
    1.55  #endif
    1.56  #ifdef MID_MUSIC
    1.57 +			case MUS_MID:
    1.58 +#ifdef USE_FLUIDSYNTH_MIDI
    1.59 +				if ( fluidsynth_ok ) {
    1.60 +					fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
    1.61 +					goto skip;
    1.62 +				}
    1.63 +#endif
    1.64  #ifdef USE_TIMIDITY_MIDI
    1.65 -			case MUS_MID:
    1.66  				if ( timidity_ok ) {
    1.67  					int samples = len / samplesize;
    1.68    					Timidity_PlaySome(stream, samples);
    1.69 +					goto skip;
    1.70  				}
    1.71 +#endif
    1.72  				break;
    1.73  #endif
    1.74 -#endif
    1.75  #ifdef OGG_MUSIC
    1.76  			case MUS_OGG:
    1.77  				
    1.78 @@ -306,6 +322,7 @@
    1.79  		}
    1.80  	}
    1.81  
    1.82 +skip:
    1.83  	/* Handle seamless music looping */
    1.84  	if (left > 0 && left < len && music_halt_or_loop()) {
    1.85  		music_mixer(udata, stream+(len-left), left);
    1.86 @@ -341,9 +358,21 @@
    1.87  		timidity_ok = 0;
    1.88  	}
    1.89  #endif
    1.90 +#ifdef USE_FLUIDSYNTH_MIDI
    1.91 +	if ( fluidsynth_init(mixer) == 0 ) {
    1.92 +		fluidsynth_ok = 1;
    1.93 +		add_music_decoder("FLUIDSYNTH");
    1.94 +	} else {
    1.95 +		fluidsynth_ok = 0;
    1.96 +	}
    1.97 +#endif
    1.98  #ifdef USE_NATIVE_MIDI
    1.99 +#ifdef USE_FLUIDSYNTH_MIDI
   1.100 +	native_midi_ok = !fluidsynth_ok;
   1.101 +	if ( native_midi_ok )
   1.102 +#endif
   1.103  #ifdef USE_TIMIDITY_MIDI
   1.104 -	native_midi_ok = !timidity_ok;
   1.105 +		native_midi_ok = !timidity_ok;
   1.106  	if ( !native_midi_ok ) {
   1.107  		native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
   1.108  	}
   1.109 @@ -469,7 +498,17 @@
   1.110  		  		Mix_SetError("%s", native_midi_error());
   1.111  			  	music->error = 1;
   1.112  			}
   1.113 -	  	} MIDI_ELSE
   1.114 +			goto skip;
   1.115 +	  	}
   1.116 +#endif
   1.117 +#ifdef USE_FLUIDSYNTH_MIDI
   1.118 +		if ( fluidsynth_ok ) {
   1.119 +			music->data.fluidsynthmidi = fluidsynth_loadsong(file);
   1.120 +			if ( music->data.fluidsynthmidi == NULL ) {
   1.121 +				music->error = 1;
   1.122 +			}
   1.123 +			goto skip;
   1.124 +		}
   1.125  #endif
   1.126  #ifdef USE_TIMIDITY_MIDI
   1.127  		if ( timidity_ok ) {
   1.128 @@ -565,6 +604,8 @@
   1.129  		Mix_SetError("Unrecognized music format");
   1.130  		music->error = 1;
   1.131  	}
   1.132 +
   1.133 +skip:
   1.134  	if ( music->error ) {
   1.135  		free(music);
   1.136  		music = NULL;
   1.137 @@ -616,11 +657,19 @@
   1.138  #ifdef USE_NATIVE_MIDI
   1.139    				if ( native_midi_ok ) {
   1.140  					native_midi_freesong(music->data.nativemidi);
   1.141 -				} MIDI_ELSE
   1.142 +					goto skip;
   1.143 +				}
   1.144 +#endif
   1.145 +#ifdef USE_FLUIDSYNTH_MIDI
   1.146 +				if ( fluidsynth_ok ) {
   1.147 +					fluidsynth_freesong(music->data.fluidsynthmidi);
   1.148 +					goto skip;
   1.149 +				}
   1.150  #endif
   1.151  #ifdef USE_TIMIDITY_MIDI
   1.152  				if ( timidity_ok ) {
   1.153  					Timidity_FreeSong(music->data.midi);
   1.154 +					goto skip;
   1.155  				}
   1.156  #endif
   1.157  				break;
   1.158 @@ -649,6 +698,8 @@
   1.159  				/* Unknown music type?? */
   1.160  				break;
   1.161  		}
   1.162 +
   1.163 +    skip:
   1.164  		free(music);
   1.165  	}
   1.166  }
   1.167 @@ -720,11 +771,19 @@
   1.168  #ifdef USE_NATIVE_MIDI
   1.169  		if ( native_midi_ok ) {
   1.170  			native_midi_start(music->data.nativemidi);
   1.171 -		} MIDI_ELSE
   1.172 +			goto skip;
   1.173 +		}
   1.174 +#endif
   1.175 +#ifdef USE_FLUIDSYNTH_MIDI
   1.176 +		if (fluidsynth_ok ) {
   1.177 +			fluidsynth_start(music->data.fluidsynthmidi);
   1.178 +			goto skip;
   1.179 +		}
   1.180  #endif
   1.181  #ifdef USE_TIMIDITY_MIDI
   1.182  		if ( timidity_ok ) {
   1.183  			Timidity_Start(music->data.midi);
   1.184 +			goto skip;
   1.185  		}
   1.186  #endif
   1.187  		break;
   1.188 @@ -757,6 +816,7 @@
   1.189  		break;
   1.190  	}
   1.191  
   1.192 +skip:
   1.193  	/* Set the playback position, note any errors if an offset is used */
   1.194  	if ( retval == 0 ) {
   1.195  		if ( position > 0.0 ) {
   1.196 @@ -929,11 +989,19 @@
   1.197  #ifdef USE_NATIVE_MIDI
   1.198  		if ( native_midi_ok ) {
   1.199  			native_midi_setvolume(volume);
   1.200 -		} MIDI_ELSE
   1.201 +			return;
   1.202 +		}
   1.203 +#endif
   1.204 +#ifdef USE_FLUIDSYNTH_MIDI
   1.205 +		if ( fluidsynth_ok ) {
   1.206 +			fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
   1.207 +			return;
   1.208 +		}
   1.209  #endif
   1.210  #ifdef USE_TIMIDITY_MIDI
   1.211  		if ( timidity_ok ) {
   1.212  			Timidity_SetVolume(volume);
   1.213 +			return;
   1.214  		}
   1.215  #endif
   1.216  		break;
   1.217 @@ -1012,11 +1080,19 @@
   1.218  #ifdef USE_NATIVE_MIDI
   1.219  		if ( native_midi_ok ) {
   1.220  			native_midi_stop();
   1.221 -		} MIDI_ELSE
   1.222 +			goto skip;
   1.223 +		}
   1.224 +#endif
   1.225 +#ifdef USE_FLUIDSYNTH_MIDI
   1.226 +		if ( fluidsynth_ok ) {
   1.227 +			fluidsynth_stop(music_playing->data.fluidsynthmidi);
   1.228 +			goto skip;
   1.229 +		}
   1.230  #endif
   1.231  #ifdef USE_TIMIDITY_MIDI
   1.232  		if ( timidity_ok ) {
   1.233  			Timidity_Stop();
   1.234 +			goto skip;
   1.235  		}
   1.236  #endif
   1.237  		break;
   1.238 @@ -1045,6 +1121,8 @@
   1.239  		/* Unknown music type?? */
   1.240  		return;
   1.241  	}
   1.242 +
   1.243 +skip:
   1.244  	music_playing->fading = MIX_NO_FADING;
   1.245  	music_playing = NULL;
   1.246  }
   1.247 @@ -1173,12 +1251,21 @@
   1.248  		if ( native_midi_ok ) {
   1.249  			if ( ! native_midi_active() )
   1.250  				playing = 0;
   1.251 -		} MIDI_ELSE
   1.252 +			goto skip;
   1.253 +		}
   1.254 +#endif
   1.255 +#ifdef USE_FLUIDSYNTH_MIDI
   1.256 +		if ( fluidsynth_ok ) {
   1.257 +			if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) )
   1.258 +				playing = 0;
   1.259 +			goto skip;
   1.260 +		}
   1.261  #endif
   1.262  #ifdef USE_TIMIDITY_MIDI
   1.263  		if ( timidity_ok ) {
   1.264  			if ( ! Timidity_Active() )
   1.265  				playing = 0;
   1.266 +			goto skip;
   1.267  		}
   1.268  #endif
   1.269  		break;
   1.270 @@ -1214,6 +1301,8 @@
   1.271  		playing = 0;
   1.272  		break;
   1.273  	}
   1.274 +
   1.275 +skip:
   1.276  	return(playing);
   1.277  }
   1.278  int Mix_PlayingMusic(void)
   1.279 @@ -1393,7 +1482,17 @@
   1.280  		  		Mix_SetError("%s", native_midi_error());
   1.281  			  	music->error = 1;
   1.282  			}
   1.283 -		} MIDI_ELSE
   1.284 +			goto skip;
   1.285 +		}
   1.286 +#endif
   1.287 +#ifdef USE_FLUIDSYNTH_MIDI
   1.288 +		if ( fluidsynth_ok ) {
   1.289 +			music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw);
   1.290 +			if ( music->data.fluidsynthmidi == NULL ) {
   1.291 +				music->error = 1;
   1.292 +			}
   1.293 +			goto skip;
   1.294 +		}
   1.295  #endif
   1.296  #ifdef USE_TIMIDITY_MIDI
   1.297  		if ( timidity_ok ) {
   1.298 @@ -1436,9 +1535,72 @@
   1.299  		Mix_SetError("Unrecognized music format");
   1.300  		music->error=1;
   1.301  	}
   1.302 +
   1.303 +skip:
   1.304  	if (music->error) {
   1.305  		free(music);
   1.306  		music=NULL;
   1.307  	}
   1.308  	return(music);
   1.309  }
   1.310 +
   1.311 +int Mix_SetSoundFonts(const char *paths)
   1.312 +{
   1.313 +#ifdef MID_MUSIC
   1.314 +	if (soundfont_paths) {
   1.315 +		free(soundfont_paths);
   1.316 +		soundfont_paths = NULL;
   1.317 +	}
   1.318 +
   1.319 +	if (paths) {
   1.320 +		if (!(soundfont_paths = strdup(paths))) {
   1.321 +			Mix_SetError("Insufficient memory to set SoundFonts");
   1.322 +			return 0;
   1.323 +		}
   1.324 +	}
   1.325 +#endif
   1.326 +	return 1;
   1.327 +}
   1.328 +
   1.329 +#ifdef MID_MUSIC
   1.330 +const char* Mix_GetSoundFonts()
   1.331 +{
   1.332 +	const char* force = getenv("SDL_FORCE_SOUNDFONTS");
   1.333 +
   1.334 +	if (!soundfont_paths || (force && force[0] == '1')) {
   1.335 +		return getenv("SDL_SOUNDFONTS");
   1.336 +	} else {
   1.337 +		return soundfont_paths;
   1.338 +	}
   1.339 +}
   1.340 +
   1.341 +int Mix_EachSoundFont(int (*function)(const char*, void*), void *data)
   1.342 +{
   1.343 +	char *context, *path, *paths;
   1.344 +	const char* cpaths = Mix_GetSoundFonts();
   1.345 +
   1.346 +	if (!cpaths) {
   1.347 +		Mix_SetError("No SoundFonts have been requested");
   1.348 +		return 0;
   1.349 +	}
   1.350 +
   1.351 +	if (!(paths = strdup(cpaths))) {
   1.352 +		Mix_SetError("Insufficient memory to iterate over SoundFonts");
   1.353 +		return 0;
   1.354 +	}
   1.355 +
   1.356 +#ifdef _WIN32
   1.357 +	for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) {
   1.358 +#else
   1.359 +	for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) {
   1.360 +#endif
   1.361 +		if (!function(path, data)) {
   1.362 +			free(paths);
   1.363 +			return 0;
   1.364 +		}
   1.365 +	}
   1.366 +
   1.367 +	free(paths);
   1.368 +	return 1;
   1.369 +}
   1.370 +#endif