Add FluidSynth backend and generic SoundFont functions. No FluidSynth DLL or headers for MSVC in this commit.
authorJames Le Cuirot <chewi@aura-online.co.uk>
Sun, 20 Mar 2011 14:34:18 +0000
changeset 506586ae09f8176
parent 505 5b24d089d9f5
child 507 4b699c9a269d
Add FluidSynth backend and generic SoundFont functions. No FluidSynth DLL or headers for MSVC in this commit.
Makefile.in
SDL_mixer.h
VisualC/SDL_mixer.dsp
VisualC/SDL_mixer.vcproj
configure.in
dynamic_fluidsynth.c
dynamic_fluidsynth.h
fluidsynth.c
fluidsynth.h
mixer.c
music.c
     1.1 --- a/Makefile.in	Tue Mar 15 23:11:29 2011 -0700
     1.2 +++ b/Makefile.in	Sun Mar 20 14:34:18 2011 +0000
     1.3 @@ -39,7 +39,7 @@
     1.4  PLAYWAVE_OBJECTS = @PLAYWAVE_OBJECTS@
     1.5  PLAYMUS_OBJECTS = @PLAYMUS_OBJECTS@
     1.6  
     1.7 -DIST = Android.mk CHANGES COPYING CWProjects.sea.bin MPWmake.sea.bin Makefile.in SDL_mixer.pc.in README SDL_mixer.h SDL_mixer.qpg.in SDL_mixer.spec SDL_mixer.spec.in VisualC.zip Watcom-OS2.zip Xcode.tar.gz acinclude autogen.sh build-scripts configure configure.in dynamic_flac.c dynamic_flac.h dynamic_mod.c dynamic_mod.h dynamic_mp3.c dynamic_mp3.h dynamic_ogg.c dynamic_ogg.h effect_position.c effect_stereoreverse.c effects_internal.c effects_internal.h gcc-fat.sh libmikmod-3.1.12.zip load_aiff.c load_aiff.h load_flac.c load_flac.h load_ogg.c load_ogg.h load_voc.c load_voc.h mixer.c music.c music_cmd.c music_cmd.h music_flac.c music_flac.h music_mad.c music_mad.h music_mod.c music_mod.h music_modplug.c music_modplug.h music_ogg.c music_ogg.h native_midi native_midi_gpl playmus.c playwave.c timidity wavestream.c wavestream.h version.rc
     1.8 +DIST = Android.mk CHANGES COPYING CWProjects.sea.bin MPWmake.sea.bin Makefile.in SDL_mixer.pc.in README SDL_mixer.h SDL_mixer.qpg.in SDL_mixer.spec SDL_mixer.spec.in VisualC.zip Watcom-OS2.zip Xcode.tar.gz acinclude autogen.sh build-scripts configure configure.in dynamic_flac.c dynamic_flac.h dynamic_fluidsynth.c dynamic_fluidsynth.h dynamic_mod.c dynamic_mod.h dynamic_mp3.c dynamic_mp3.h dynamic_ogg.c dynamic_ogg.h effect_position.c effect_stereoreverse.c effects_internal.c effects_internal.h fluidsynth.c fluidsynth.h gcc-fat.sh libmikmod-3.1.12.zip load_aiff.c load_aiff.h load_flac.c load_flac.h load_ogg.c load_ogg.h load_voc.c load_voc.h mixer.c music.c music_cmd.c music_cmd.h music_flac.c music_flac.h music_mad.c music_mad.h music_mod.c music_mod.h music_modplug.c music_modplug.h music_ogg.c music_ogg.h native_midi native_midi_gpl playmus.c playwave.c timidity wavestream.c wavestream.h version.rc
     1.9  
    1.10  LT_AGE      = @LT_AGE@
    1.11  LT_CURRENT  = @LT_CURRENT@
     2.1 --- a/SDL_mixer.h	Tue Mar 15 23:11:29 2011 -0700
     2.2 +++ b/SDL_mixer.h	Sun Mar 20 14:34:18 2011 +0000
     2.3 @@ -67,10 +67,11 @@
     2.4  
     2.5  typedef enum
     2.6  {
     2.7 -    MIX_INIT_FLAC = 0x00000001,
     2.8 -    MIX_INIT_MOD  = 0x00000002,
     2.9 -    MIX_INIT_MP3  = 0x00000004,
    2.10 -    MIX_INIT_OGG  = 0x00000008
    2.11 +    MIX_INIT_FLAC        = 0x00000001,
    2.12 +    MIX_INIT_MOD         = 0x00000002,
    2.13 +    MIX_INIT_MP3         = 0x00000004,
    2.14 +    MIX_INIT_OGG         = 0x00000008,
    2.15 +    MIX_INIT_FLUIDSYNTH  = 0x00000016
    2.16  } MIX_InitFlags;
    2.17  
    2.18  /* Loads dynamic libraries and prepares them for use.  Flags should be
    2.19 @@ -605,6 +606,11 @@
    2.20  extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value);
    2.21  extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void);
    2.22  
    2.23 +/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */
    2.24 +extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths);
    2.25 +extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts();
    2.26 +extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (*function)(const char*, void*), void *data);
    2.27 +
    2.28  /* Get the Mix_Chunk currently associated with a mixer channel
    2.29      Returns NULL if it's an invalid channel, or there's no chunk associated.
    2.30  */
     3.1 --- a/VisualC/SDL_mixer.dsp	Tue Mar 15 23:11:29 2011 -0700
     3.2 +++ b/VisualC/SDL_mixer.dsp	Sun Mar 20 14:34:18 2011 +0000
     3.3 @@ -44,7 +44,7 @@
     3.4  # PROP Ignore_Export_Lib 0
     3.5  # PROP Target_Dir ""
     3.6  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
     3.7 -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\mikmod" /I "..\timidity" /I "..\native_midi" /I "vorbis\include" /I "smpeg\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WAV_MUSIC" /D "MOD_MUSIC" /D MOD_DYNAMIC=\"mikmod.dll\" /D "MID_MUSIC" /D "USE_TIMIDITY_MIDI" /D "USE_NATIVE_MIDI" /D "OGG_MUSIC" /D OGG_DYNAMIC=\"libvorbisfile-3.dll\" /D "MP3_MUSIC" /D MP3_DYNAMIC=\"smpeg.dll\" /YX /FD /c
     3.8 +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\mikmod" /I "..\timidity" /I "..\native_midi" /I "fluidsynth\include" /I "vorbis\include" /I "smpeg\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WAV_MUSIC" /D "MOD_MUSIC" /D MOD_DYNAMIC=\"mikmod.dll\" /D "MID_MUSIC" /D "USE_TIMIDITY_MIDI" /D "USE_NATIVE_MIDI" /D "USE_FLUIDSYNTH_MIDI" /D FLUIDSYNTH_DYNAMIC=\"libfluidsynth.dll\" /D "OGG_MUSIC" /D OGG_DYNAMIC=\"libvorbisfile-3.dll\" /D "MP3_MUSIC" /D MP3_DYNAMIC=\"smpeg.dll\" /YX /FD /c
     3.9  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
    3.10  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
    3.11  # ADD BASE RSC /l 0x409 /d "NDEBUG"
    3.12 @@ -70,7 +70,7 @@
    3.13  # PROP Ignore_Export_Lib 0
    3.14  # PROP Target_Dir ""
    3.15  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
    3.16 -# ADD CPP /nologo /MD /W3 /Gm /GX /Zi /Od /I "..\mikmod" /I "..\timidity" /I "..\native_midi" /I "vorbis\include" /I "smpeg\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WAV_MUSIC" /D "MOD_MUSIC" /D MOD_DYNAMIC=\"mikmod.dll\" /D MOD_DYNAMIC=\"mikmod.dll\" /D "MID_MUSIC" /D "USE_TIMIDITY_MIDI" /D "USE_NATIVE_MIDI" /D "OGG_MUSIC" /D OGG_DYNAMIC=\"libvorbisfile-3.dll\" /D "MP3_MUSIC" /D MP3_DYNAMIC=\"smpeg.dll\" /YX /FD /c
    3.17 +# ADD CPP /nologo /MD /W3 /Gm /GX /Zi /Od /I "..\mikmod" /I "..\timidity" /I "..\native_midi" /I "fluidsynth\include" /I "vorbis\include" /I "smpeg\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WAV_MUSIC" /D "MOD_MUSIC" /D MOD_DYNAMIC=\"mikmod.dll\" /D MOD_DYNAMIC=\"mikmod.dll\" /D "MID_MUSIC" /D "USE_TIMIDITY_MIDI" /D "USE_NATIVE_MIDI" /D "USE_FLUIDSYNTH_MIDI" /D FLUIDSYNTH_DYNAMIC=\"libfluidsynth.dll\" /D "OGG_MUSIC" /D OGG_DYNAMIC=\"libvorbisfile-3.dll\" /D "MP3_MUSIC" /D MP3_DYNAMIC=\"smpeg.dll\" /YX /FD /c
    3.18  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
    3.19  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
    3.20  # ADD BASE RSC /l 0x409 /d "_DEBUG"
    3.21 @@ -98,6 +98,14 @@
    3.22  # End Source File
    3.23  # Begin Source File
    3.24  
    3.25 +SOURCE=..\dynamic_fluidsynth.c
    3.26 +# End Source File
    3.27 +# Begin Source File
    3.28 +
    3.29 +SOURCE=..\dynamic_fluidsynth.h
    3.30 +# End Source File
    3.31 +# Begin Source File
    3.32 +
    3.33  SOURCE=..\dynamic_mod.c
    3.34  # End Source File
    3.35  # Begin Source File
    3.36 @@ -138,6 +146,14 @@
    3.37  # End Source File
    3.38  # Begin Source File
    3.39  
    3.40 +SOURCE=..\fluidsynth.c
    3.41 +# End Source File
    3.42 +# Begin Source File
    3.43 +
    3.44 +SOURCE=..\fluidsynth.h
    3.45 +# End Source File
    3.46 +# Begin Source File
    3.47 +
    3.48  SOURCE=..\load_aiff.c
    3.49  # End Source File
    3.50  # Begin Source File
     4.1 --- a/VisualC/SDL_mixer.vcproj	Tue Mar 15 23:11:29 2011 -0700
     4.2 +++ b/VisualC/SDL_mixer.vcproj	Sun Mar 20 14:34:18 2011 +0000
     4.3 @@ -48,8 +48,8 @@
     4.4  				Name="VCCLCompilerTool"
     4.5  				AdditionalOptions="/D OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;"
     4.6  				Optimization="0"
     4.7 -				AdditionalIncludeDirectories="..\timidity;..\native_midi;mikmod\include;smpeg\include;vorbis\include"
     4.8 -				PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;WAV_MUSIC;MOD_MUSIC;MOD_DYNAMIC=\&quot;mikmod.dll\&quot;;MID_MUSIC;USE_TIMIDITY_MIDI;USE_NATIVE_MIDI;OGG_MUSIC;OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;;MP3_MUSIC;MP3_DYNAMIC=\&quot;smpeg.dll\&quot;"
     4.9 +				AdditionalIncludeDirectories="..\timidity;..\native_midi;fluidsynth\include;mikmod\include;smpeg\include;vorbis\include"
    4.10 +				PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;WAV_MUSIC;MOD_MUSIC;MOD_DYNAMIC=\&quot;mikmod.dll\&quot;;MID_MUSIC;USE_TIMIDITY_MIDI;USE_NATIVE_MIDI;USE_FLUIDSYNTH_MIDI;FLUIDSYNTH_DYNAMIC=\&quot;libfluidsynth.dll\&quot;;OGG_MUSIC;OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;;MP3_MUSIC;MP3_DYNAMIC=\&quot;smpeg.dll\&quot;"
    4.11  				MinimalRebuild="true"
    4.12  				RuntimeLibrary="2"
    4.13  				PrecompiledHeaderFile=".\Debug/SDL_mixer.pch"
    4.14 @@ -145,8 +145,8 @@
    4.15  				AdditionalOptions="/D OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;"
    4.16  				Optimization="2"
    4.17  				InlineFunctionExpansion="1"
    4.18 -				AdditionalIncludeDirectories="..\timidity;..\native_midi;mikmod\include;smpeg\include;vorbis\include"
    4.19 -				PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;WAV_MUSIC;MOD_MUSIC;MID_MUSIC;MOD_DYNAMIC=\&quot;mikmod.dll\&quot;;USE_TIMIDITY_MIDI;USE_NATIVE_MIDI;OGG_MUSIC;OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;;MP3_MUSIC;MP3_DYNAMIC=\&quot;smpeg.dll\&quot;"
    4.20 +				AdditionalIncludeDirectories="..\timidity;..\native_midi;fluidsynth/include;mikmod\include;smpeg\include;vorbis\include"
    4.21 +				PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;WAV_MUSIC;MOD_MUSIC;MID_MUSIC;MOD_DYNAMIC=\&quot;mikmod.dll\&quot;;USE_TIMIDITY_MIDI;USE_NATIVE_MIDI;USE_FLUIDSYNTH_MIDI;FLUIDSYNTH_DYNAMIC=\&quot;libfluidsynth.dll\&quot;;OGG_MUSIC;OGG_DYNAMIC=\&quot;libvorbisfile-3.dll\&quot;;MP3_MUSIC;MP3_DYNAMIC=\&quot;smpeg.dll\&quot;"
    4.22  				StringPooling="true"
    4.23  				RuntimeLibrary="2"
    4.24  				EnableFunctionLevelLinking="true"
    4.25 @@ -219,6 +219,14 @@
    4.26  			>
    4.27  		</File>
    4.28  		<File
    4.29 +			RelativePath="..\dynamic_fluidsynth.c"
    4.30 +			>
    4.31 +		</File>
    4.32 +		<File
    4.33 +			RelativePath="..\dynamic_fluidsynth.h"
    4.34 +			>
    4.35 +		</File>
    4.36 +		<File
    4.37  			RelativePath="..\dynamic_mod.c"
    4.38  			>
    4.39  		</File>
    4.40 @@ -349,6 +357,14 @@
    4.41  			>
    4.42  		</File>
    4.43  		<File
    4.44 +			RelativePath="..\fluidsynth.c"
    4.45 +			>
    4.46 +		</File>
    4.47 +		<File
    4.48 +			RelativePath="..\fluidsynth.h"
    4.49 +			>
    4.50 +		</File>
    4.51 +		<File
    4.52  			RelativePath="..\load_aiff.c"
    4.53  			>
    4.54  			<FileConfiguration
     5.1 --- a/configure.in	Tue Mar 15 23:11:29 2011 -0700
     5.2 +++ b/configure.in	Sun Mar 20 14:34:18 2011 +0000
     5.3 @@ -387,6 +387,49 @@
     5.4              SOURCES="$SOURCES $srcdir/native_midi_gpl/*.c"
     5.5          fi
     5.6      fi
     5.7 +    AC_ARG_ENABLE([music-fluidsynth-midi],
     5.8 +AC_HELP_STRING([--enable-music-fluidsynth-midi], [enable FluidSynth MIDI output [[default=yes]]]),
     5.9 +                  [], [enable_music_fluidsynth_midi=yes])
    5.10 +    AC_ARG_ENABLE([music-fluidsynth-shared],
    5.11 +AC_HELP_STRING([--enable-music-fluidsynth-shared], [dynamically load FluidSynth support [[default=yes]]]),
    5.12 +                  [], [enable_music_fluidsynth_shared=yes])
    5.13 +    if test x$enable_music_fluidsynth_midi = xyes; then
    5.14 +        AC_CHECK_HEADER([fluidsynth.h], [have_fluidsynth_hdr=yes])
    5.15 +        AC_CHECK_LIB([fluidsynth], [fluid_player_add_mem], [have_fluidsynth_lib=yes])
    5.16 +        if test x$have_fluidsynth_hdr = xyes -a x$have_fluidsynth_lib = xyes; then
    5.17 +            case "$host" in
    5.18 +                *-*-darwin*)
    5.19 +                    fluidsynth_lib=[`find_lib libfluidsynth.dylib`]
    5.20 +                    if test x$fluidsynth_lib = x; then
    5.21 +                        fluidsynth_lib=[`find_lib libfluidsynth.[0-9]`]
    5.22 +                    fi
    5.23 +                    if test x$fluidsynth_lib = x; then
    5.24 +                        fluidsynth_lib=[`find_lib libfluidsynth.[0-9]*`]
    5.25 +                    fi
    5.26 +                    ;;
    5.27 +                *-*-cygwin* | *-*-mingw32*)
    5.28 +                    fluidsynth_lib=[`find_lib "fluidsynth*.dll"`]
    5.29 +                    ;;
    5.30 +                *)
    5.31 +                    fluidsynth_lib=[`find_lib "libfluidsynth.so.[0-9]"`]
    5.32 +                    if test x$fluidsynth_lib = x; then
    5.33 +                        fluidsynth_lib=[`find_lib "libfluidsynth.so.[0-9]*"`]
    5.34 +                    fi
    5.35 +                    ;;
    5.36 +            esac
    5.37 +            SOURCES="$SOURCES $srcdir/dynamic_fluidsynth.c $srcdir/fluidsynth.c"
    5.38 +            EXTRA_CFLAGS="$EXTRA_CFLAGS -DUSE_FLUIDSYNTH_MIDI"
    5.39 +            if test x$enable_music_fluidsynth_shared = xyes && test x$fluidsynth_lib != x; then
    5.40 +                echo "-- dynamic libfluidsyth -> $fluidsynth_lib"
    5.41 +                EXTRA_CFLAGS="$EXTRA_CFLAGS -DFLUIDSYNTH_DYNAMIC=\\\"$fluidsynth_lib\\\""
    5.42 +            else
    5.43 +                EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lfluidsynth"
    5.44 +            fi
    5.45 +        else
    5.46 +            AC_MSG_WARN([*** Unable to find FluidSynth library (http://www.fluidsynth.org/)])
    5.47 +            AC_MSG_WARN([FluidSynth support disabled])
    5.48 +        fi
    5.49 +    fi
    5.50  fi
    5.51  
    5.52  AC_ARG_ENABLE([music-ogg],
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/dynamic_fluidsynth.c	Sun Mar 20 14:34:18 2011 +0000
     6.3 @@ -0,0 +1,85 @@
     6.4 +/*
     6.5 +    SDL_mixer:  An audio mixer library based on the SDL library
     6.6 +    Copyright (C) 1997-2011 Sam Lantinga
     6.7 +
     6.8 +    This library is free software; you can redistribute it and/or
     6.9 +    modify it under the terms of the GNU Library General Public
    6.10 +    License as published by the Free Software Foundation; either
    6.11 +    version 2 of the License, or (at your option) any later version.
    6.12 +
    6.13 +    This library is distributed in the hope that it will be useful,
    6.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    6.16 +    Library General Public License for more details.
    6.17 +
    6.18 +    You should have received a copy of the GNU Library General Public
    6.19 +    License along with this library; if not, write to the Free
    6.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.21 +
    6.22 +    James Le Cuirot
    6.23 +    chewi@aura-online.co.uk
    6.24 +*/
    6.25 +
    6.26 +#ifdef USE_FLUIDSYNTH_MIDI
    6.27 +
    6.28 +#include "SDL_loadso.h"
    6.29 +#include "dynamic_fluidsynth.h"
    6.30 +
    6.31 +fluidsynth_loader fluidsynth = {
    6.32 +	0, NULL
    6.33 +};
    6.34 +
    6.35 +#ifdef FLUIDSYNTH_DYNAMIC
    6.36 +#define FLUIDSYNTH_LOADER(FUNC, SIG) \
    6.37 +	fluidsynth.FUNC = (SIG) SDL_LoadFunction(fluidsynth.handle, #FUNC); \
    6.38 +	if (fluidsynth.FUNC == NULL) { SDL_UnloadObject(fluidsynth.handle); return -1; }
    6.39 +#else
    6.40 +#define FLUIDSYNTH_LOADER(FUNC, SIG) \
    6.41 +	fluidsynth.FUNC = FUNC;
    6.42 +#endif
    6.43 +
    6.44 +int Mix_InitFluidSynth()
    6.45 +{
    6.46 +	if ( fluidsynth.loaded == 0 ) {
    6.47 +#ifdef FLUIDSYNTH_DYNAMIC
    6.48 +		fluidsynth.handle = SDL_LoadObject(FLUIDSYNTH_DYNAMIC);
    6.49 +		if ( fluidsynth.handle == NULL ) return -1;
    6.50 +#endif
    6.51 +
    6.52 +		FLUIDSYNTH_LOADER(delete_fluid_player, int (*)(fluid_player_t*));
    6.53 +		FLUIDSYNTH_LOADER(delete_fluid_settings, void (*)(fluid_settings_t*));
    6.54 +		FLUIDSYNTH_LOADER(delete_fluid_synth, int (*)(fluid_synth_t*));
    6.55 +		FLUIDSYNTH_LOADER(fluid_player_add, int (*)(fluid_player_t*, const char*));
    6.56 +		FLUIDSYNTH_LOADER(fluid_player_add_mem, int (*)(fluid_player_t*, const void*, size_t));
    6.57 +		FLUIDSYNTH_LOADER(fluid_player_get_status, int (*)(fluid_player_t*));
    6.58 +		FLUIDSYNTH_LOADER(fluid_player_play, int (*)(fluid_player_t*));
    6.59 +		FLUIDSYNTH_LOADER(fluid_player_set_loop, int (*)(fluid_player_t*, int));
    6.60 +		FLUIDSYNTH_LOADER(fluid_player_stop, int (*)(fluid_player_t*));
    6.61 +		FLUIDSYNTH_LOADER(fluid_settings_setnum, int (*)(fluid_settings_t*, const char*, double));
    6.62 +		FLUIDSYNTH_LOADER(fluid_synth_get_settings, fluid_settings_t* (*)(fluid_synth_t*));
    6.63 +		FLUIDSYNTH_LOADER(fluid_synth_set_gain, void (*)(fluid_synth_t*, float));
    6.64 +		FLUIDSYNTH_LOADER(fluid_synth_sfload, int(*)(fluid_synth_t*, const char*, int));
    6.65 +		FLUIDSYNTH_LOADER(fluid_synth_write_s16, int(*)(fluid_synth_t*, int, void*, int, int, void*, int, int));
    6.66 +		FLUIDSYNTH_LOADER(new_fluid_player, fluid_player_t* (*)(fluid_synth_t*));
    6.67 +		FLUIDSYNTH_LOADER(new_fluid_settings, fluid_settings_t* (*)(void));
    6.68 +		FLUIDSYNTH_LOADER(new_fluid_synth, fluid_synth_t* (*)(fluid_settings_t*));
    6.69 +	}
    6.70 +	++fluidsynth.loaded;
    6.71 +
    6.72 +	return 0;
    6.73 +}
    6.74 +
    6.75 +void Mix_QuitFluidSynth()
    6.76 +{
    6.77 +	if ( fluidsynth.loaded == 0 ) {
    6.78 +		return;
    6.79 +	}
    6.80 +	if ( fluidsynth.loaded == 1 ) {
    6.81 +#ifdef FLUIDSYNTH_DYNAMIC
    6.82 +		SDL_UnloadObject(fluidsynth.handle);
    6.83 +#endif
    6.84 +	}
    6.85 +	--fluidsynth.loaded;
    6.86 +}
    6.87 +
    6.88 +#endif /* USE_FLUIDSYNTH_MIDI */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/dynamic_fluidsynth.h	Sun Mar 20 14:34:18 2011 +0000
     7.3 @@ -0,0 +1,55 @@
     7.4 +/*
     7.5 +    SDL_mixer:  An audio mixer library based on the SDL library
     7.6 +    Copyright (C) 1997-2011 Sam Lantinga
     7.7 +
     7.8 +    This library is free software; you can redistribute it and/or
     7.9 +    modify it under the terms of the GNU Library General Public
    7.10 +    License as published by the Free Software Foundation; either
    7.11 +    version 2 of the License, or (at your option) any later version.
    7.12 +
    7.13 +    This library is distributed in the hope that it will be useful,
    7.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    7.16 +    Library General Public License for more details.
    7.17 +
    7.18 +    You should have received a copy of the GNU Library General Public
    7.19 +    License along with this library; if not, write to the Free
    7.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.21 +
    7.22 +    James Le Cuirot
    7.23 +    chewi@aura-online.co.uk
    7.24 +*/
    7.25 +
    7.26 +#ifdef USE_FLUIDSYNTH_MIDI
    7.27 +
    7.28 +#include <fluidsynth.h>
    7.29 +
    7.30 +typedef struct {
    7.31 +	int loaded;
    7.32 +	void *handle;
    7.33 +
    7.34 +	int (*delete_fluid_player)(fluid_player_t*);
    7.35 +	void (*delete_fluid_settings)(fluid_settings_t*);
    7.36 +	int (*delete_fluid_synth)(fluid_synth_t*);
    7.37 +	int (*fluid_player_add)(fluid_player_t*, const char*);
    7.38 +	int (*fluid_player_add_mem)(fluid_player_t*, const void*, size_t);
    7.39 +	int (*fluid_player_get_status)(fluid_player_t*);
    7.40 +	int (*fluid_player_play)(fluid_player_t*);
    7.41 +	int (*fluid_player_set_loop)(fluid_player_t*, int);
    7.42 +	int (*fluid_player_stop)(fluid_player_t*);
    7.43 +	int (*fluid_settings_setnum)(fluid_settings_t*, const char*, double);
    7.44 +	fluid_settings_t* (*fluid_synth_get_settings)(fluid_synth_t*);
    7.45 +	void (*fluid_synth_set_gain)(fluid_synth_t*, float);
    7.46 +	int (*fluid_synth_sfload)(fluid_synth_t*, const char*, int);
    7.47 +	int (*fluid_synth_write_s16)(fluid_synth_t*, int, void*, int, int, void*, int, int);
    7.48 +	fluid_player_t* (*new_fluid_player)(fluid_synth_t*);
    7.49 +	fluid_settings_t* (*new_fluid_settings)(void);
    7.50 +	fluid_synth_t* (*new_fluid_synth)(fluid_settings_t*);
    7.51 +} fluidsynth_loader;
    7.52 +
    7.53 +extern fluidsynth_loader fluidsynth;
    7.54 +
    7.55 +#endif /* USE_FLUIDSYNTH_MIDI */
    7.56 +
    7.57 +extern int Mix_InitFluidSynth();
    7.58 +extern void Mix_QuitFluidSynth();
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/fluidsynth.c	Sun Mar 20 14:34:18 2011 +0000
     8.3 @@ -0,0 +1,222 @@
     8.4 +/*
     8.5 +    SDL_mixer:  An audio mixer library based on the SDL library
     8.6 +    Copyright (C) 1997-2011 Sam Lantinga
     8.7 +
     8.8 +    This library is free software; you can redistribute it and/or
     8.9 +    modify it under the terms of the GNU Library General Public
    8.10 +    License as published by the Free Software Foundation; either
    8.11 +    version 2 of the License, or (at your option) any later version.
    8.12 +
    8.13 +    This library is distributed in the hope that it will be useful,
    8.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    8.16 +    Library General Public License for more details.
    8.17 +
    8.18 +    You should have received a copy of the GNU Library General Public
    8.19 +    License along with this library; if not, write to the Free
    8.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.21 +
    8.22 +    James Le Cuirot
    8.23 +    chewi@aura-online.co.uk
    8.24 +*/
    8.25 +
    8.26 +#include "fluidsynth.h"
    8.27 +#include "SDL_mixer.h"
    8.28 +#include <stdio.h>
    8.29 +#include <sys/types.h>
    8.30 +
    8.31 +static Uint16 format;
    8.32 +static Uint8 channels;
    8.33 +static int freq;
    8.34 +
    8.35 +int fluidsynth_check_soundfont(const char *path, void *data)
    8.36 +{
    8.37 +	FILE *file = fopen(path, "r");
    8.38 +
    8.39 +	if (file) {
    8.40 +		fclose(file);
    8.41 +		return 1;
    8.42 +	} else {
    8.43 +		Mix_SetError("Failed to access the SoundFont %s", path);
    8.44 +		return 0;
    8.45 +	}
    8.46 +}
    8.47 +
    8.48 +int fluidsynth_load_soundfont(const char *path, void *data)
    8.49 +{
    8.50 +	/* If this fails, it's too late to try Timidity so pray that at least one works. */
    8.51 +	fluidsynth.fluid_synth_sfload((fluid_synth_t*) data, path, 1);
    8.52 +	return 1;
    8.53 +}
    8.54 +
    8.55 +int fluidsynth_init(SDL_AudioSpec *mixer)
    8.56 +{
    8.57 +	if (!Mix_EachSoundFont(fluidsynth_check_soundfont, NULL))
    8.58 +		return -1;
    8.59 +
    8.60 +	format = mixer->format;
    8.61 +	channels = mixer->channels;
    8.62 +	freq = mixer->freq;
    8.63 +
    8.64 +	return 0;
    8.65 +}
    8.66 +
    8.67 +FluidSynthMidiSong *fluidsynth_loadsong_common(int (*function)(FluidSynthMidiSong*, void*), void *data)
    8.68 +{
    8.69 +	FluidSynthMidiSong *song;
    8.70 +	fluid_settings_t *settings = NULL;
    8.71 +
    8.72 +	if ((song = malloc(sizeof(FluidSynthMidiSong)))) {
    8.73 +		memset(song, 0, sizeof(FluidSynthMidiSong));
    8.74 +
    8.75 +		if (SDL_BuildAudioCVT(&song->convert, AUDIO_S16, 2, freq, format, channels, freq) >= 0) {
    8.76 +			if ((settings = fluidsynth.new_fluid_settings())) {
    8.77 +				fluidsynth.fluid_settings_setnum(settings, "synth.sample-rate", (double) freq);
    8.78 +
    8.79 +				if ((song->synth = fluidsynth.new_fluid_synth(settings))) {
    8.80 +					if (Mix_EachSoundFont(fluidsynth_load_soundfont, (void*) song->synth)) {
    8.81 +						if ((song->player = fluidsynth.new_fluid_player(song->synth))) {
    8.82 +							if (function(song, data)) return song;
    8.83 +							fluidsynth.delete_fluid_player(song->player);
    8.84 +						} else {
    8.85 +							Mix_SetError("Failed to create FluidSynth player");
    8.86 +						}
    8.87 +					}
    8.88 +					fluidsynth.delete_fluid_synth(song->synth);
    8.89 +				} else {
    8.90 +					Mix_SetError("Failed to create FluidSynth synthesizer");
    8.91 +				}
    8.92 +				fluidsynth.delete_fluid_settings(settings);
    8.93 +			} else {
    8.94 +				Mix_SetError("Failed to create FluidSynth settings");
    8.95 +			}
    8.96 +		} else {
    8.97 +			Mix_SetError("Failed to set up audio conversion");
    8.98 +		}
    8.99 +		free(song);
   8.100 +	} else {
   8.101 +		Mix_SetError("Insufficient memory for song");
   8.102 +	}
   8.103 +	return NULL;
   8.104 +}
   8.105 +
   8.106 +int fluidsynth_loadsong_internal(FluidSynthMidiSong *song, void *data)
   8.107 +{
   8.108 +	const char* path = (const char*) data;
   8.109 +
   8.110 +	if (fluidsynth.fluid_player_add(song->player, path) == FLUID_OK) {
   8.111 +		return 1;
   8.112 +	} else {
   8.113 +		Mix_SetError("FluidSynth failed to load %s", path);
   8.114 +		return 0;
   8.115 +	}
   8.116 +}
   8.117 +
   8.118 +int fluidsynth_loadsong_RW_internal(FluidSynthMidiSong *song, void *data)
   8.119 +{
   8.120 +	off_t offset;
   8.121 +	size_t size;
   8.122 +	char *buffer;
   8.123 +	SDL_RWops *rw = (SDL_RWops*) data;
   8.124 +
   8.125 +	offset = SDL_RWtell(rw);
   8.126 +	SDL_RWseek(rw, 0, RW_SEEK_END);
   8.127 +	size = SDL_RWtell(rw) - offset;
   8.128 +	SDL_RWseek(rw, offset, RW_SEEK_SET);
   8.129 +
   8.130 +	if ((buffer = (char*) malloc(size))) {
   8.131 +		if(SDL_RWread(rw, buffer, size, 1) == 1) {
   8.132 +			if (fluidsynth.fluid_player_add_mem(song->player, buffer, size) == FLUID_OK) {
   8.133 +				return 1;
   8.134 +			} else {
   8.135 +				Mix_SetError("FluidSynth failed to load in-memory song");
   8.136 +			}
   8.137 +		} else {
   8.138 +			Mix_SetError("Failed to read in-memory song");
   8.139 +		}
   8.140 +		free(buffer);
   8.141 +	} else {
   8.142 +		Mix_SetError("Insufficient memory for song");
   8.143 +	}
   8.144 +	return 0;
   8.145 +}
   8.146 +
   8.147 +FluidSynthMidiSong *fluidsynth_loadsong(const char *midifile)
   8.148 +{
   8.149 +	return fluidsynth_loadsong_common(fluidsynth_loadsong_internal, (void*) midifile);
   8.150 +}
   8.151 +
   8.152 +FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw)
   8.153 +{
   8.154 +	return fluidsynth_loadsong_common(fluidsynth_loadsong_RW_internal, (void*) rw);
   8.155 +}
   8.156 +
   8.157 +void fluidsynth_freesong(FluidSynthMidiSong *song)
   8.158 +{
   8.159 +	if (!song) return;
   8.160 +	fluidsynth.delete_fluid_player(song->player);
   8.161 +	fluidsynth.delete_fluid_settings(fluidsynth.fluid_synth_get_settings(song->synth));
   8.162 +	fluidsynth.delete_fluid_synth(song->synth);
   8.163 +	free(song);
   8.164 +}
   8.165 +
   8.166 +void fluidsynth_start(FluidSynthMidiSong *song)
   8.167 +{
   8.168 +	fluidsynth.fluid_player_set_loop(song->player, 1);
   8.169 +	fluidsynth.fluid_player_play(song->player);
   8.170 +}
   8.171 +
   8.172 +void fluidsynth_stop(FluidSynthMidiSong *song)
   8.173 +{
   8.174 +	fluidsynth.fluid_player_stop(song->player);
   8.175 +}
   8.176 +
   8.177 +int fluidsynth_active(FluidSynthMidiSong *song)
   8.178 +{
   8.179 +	return fluidsynth.fluid_player_get_status(song->player) == FLUID_PLAYER_PLAYING ? 1 : 0;
   8.180 +}
   8.181 +
   8.182 +void fluidsynth_setvolume(FluidSynthMidiSong *song, int volume)
   8.183 +{
   8.184 +	/* FluidSynth's default is 0.2. Make 0.8 the maximum. */
   8.185 +	fluidsynth.fluid_synth_set_gain(song->synth, (float) (volume * 0.00625));
   8.186 +}
   8.187 +
   8.188 +int fluidsynth_playsome(FluidSynthMidiSong *song, void *dest, int dest_len)
   8.189 +{
   8.190 +	int result = -1;
   8.191 +	int frames = dest_len / channels / ((format & 0xFF) / 8);
   8.192 +	int src_len = frames * 4; /* 16-bit stereo */
   8.193 +	void *src = dest;
   8.194 +
   8.195 +	if (dest_len < src_len) {
   8.196 +		if (!(src = malloc(src_len))) {
   8.197 +			Mix_SetError("Insufficient memory for audio conversion");
   8.198 +			return result;
   8.199 +		}
   8.200 +	}
   8.201 +
   8.202 +	if (fluidsynth.fluid_synth_write_s16(song->synth, frames, src, 0, 2, src, 1, 2) != FLUID_OK) {
   8.203 +		Mix_SetError("Error generating FluidSynth audio");
   8.204 +		goto finish;
   8.205 +	}
   8.206 +
   8.207 +	song->convert.buf = src;
   8.208 +	song->convert.len = src_len;
   8.209 +
   8.210 +	if (SDL_ConvertAudio(&song->convert) < 0) {
   8.211 +		Mix_SetError("Error during audio conversion");
   8.212 +		goto finish;
   8.213 +	}
   8.214 +
   8.215 +	if (src != dest)
   8.216 +		memcpy(dest, src, dest_len);
   8.217 +
   8.218 +	result = 0;
   8.219 +
   8.220 +finish:
   8.221 +	if (src != dest)
   8.222 +		free(src);
   8.223 +
   8.224 +	return result;
   8.225 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/fluidsynth.h	Sun Mar 20 14:34:18 2011 +0000
     9.3 @@ -0,0 +1,46 @@
     9.4 +/*
     9.5 +    SDL_mixer:  An audio mixer library based on the SDL library
     9.6 +    Copyright (C) 1997-2011 Sam Lantinga
     9.7 +
     9.8 +    This library is free software; you can redistribute it and/or
     9.9 +    modify it under the terms of the GNU Library General Public
    9.10 +    License as published by the Free Software Foundation; either
    9.11 +    version 2 of the License, or (at your option) any later version.
    9.12 +
    9.13 +    This library is distributed in the hope that it will be useful,
    9.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    9.16 +    Library General Public License for more details.
    9.17 +
    9.18 +    You should have received a copy of the GNU Library General Public
    9.19 +    License along with this library; if not, write to the Free
    9.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.21 +
    9.22 +    James Le Cuirot
    9.23 +    chewi@aura-online.co.uk
    9.24 +*/
    9.25 +
    9.26 +#ifndef _FLUIDSYNTH_H_
    9.27 +#define _FLUIDSYNTH_H_
    9.28 +
    9.29 +#include "dynamic_fluidsynth.h"
    9.30 +#include <SDL_rwops.h>
    9.31 +#include <SDL_audio.h>
    9.32 +
    9.33 +typedef struct {
    9.34 +	SDL_AudioCVT convert;
    9.35 +	fluid_synth_t *synth;
    9.36 +	fluid_player_t* player;
    9.37 +} FluidSynthMidiSong;
    9.38 +
    9.39 +int fluidsynth_init(SDL_AudioSpec *mixer);
    9.40 +FluidSynthMidiSong *fluidsynth_loadsong(const char *midifile);
    9.41 +FluidSynthMidiSong *fluidsynth_loadsong_RW(SDL_RWops *rw);
    9.42 +void fluidsynth_freesong(FluidSynthMidiSong *song);
    9.43 +void fluidsynth_start(FluidSynthMidiSong *song);
    9.44 +void fluidsynth_stop(FluidSynthMidiSong *song);
    9.45 +int fluidsynth_active(FluidSynthMidiSong *song);
    9.46 +void fluidsynth_setvolume(FluidSynthMidiSong *song, int volume);
    9.47 +int fluidsynth_playsome(FluidSynthMidiSong *song, void *stream, int len);
    9.48 +
    9.49 +#endif /* _FLUIDSYNTH_H_ */
    10.1 --- a/mixer.c	Tue Mar 15 23:11:29 2011 -0700
    10.2 +++ b/mixer.c	Sun Mar 20 14:34:18 2011 +0000
    10.3 @@ -107,6 +107,11 @@
    10.4  static const char **chunk_decoders = NULL;
    10.5  static int num_decoders = 0;
    10.6  
    10.7 +/* Semicolon-separated SoundFont paths */
    10.8 +#ifdef MID_MUSIC
    10.9 +extern char* soundfont_paths;
   10.10 +#endif
   10.11 +
   10.12  int Mix_GetNumChunkDecoders(void)
   10.13  {
   10.14  	return(num_decoders);
   10.15 @@ -144,6 +149,15 @@
   10.16  {
   10.17  	int result = 0;
   10.18  
   10.19 +	if (flags & MIX_INIT_FLUIDSYNTH) {
   10.20 +#ifdef USE_FLUIDSYNTH_MIDI
   10.21 +		if ((initialized & MIX_INIT_FLUIDSYNTH) || Mix_InitFluidSynth() == 0) {
   10.22 +			result |= MIX_INIT_FLUIDSYNTH;
   10.23 +		}
   10.24 +#else
   10.25 +		Mix_SetError("Mixer not built with FluidSynth support");
   10.26 +#endif
   10.27 +	}
   10.28  	if (flags & MIX_INIT_FLAC) {
   10.29  #ifdef FLAC_MUSIC
   10.30  		if ((initialized & MIX_INIT_FLAC) || Mix_InitFLAC() == 0) {
   10.31 @@ -187,6 +201,11 @@
   10.32  
   10.33  void Mix_Quit()
   10.34  {
   10.35 +#ifdef USE_FLUIDSYNTH_MIDI
   10.36 +	if (initialized & MIX_INIT_FLUIDSYNTH) {
   10.37 +		Mix_QuitFluidSynth();
   10.38 +	}
   10.39 +#endif
   10.40  #ifdef FLAC_MUSIC
   10.41  	if (initialized & MIX_INIT_FLAC) {
   10.42  		Mix_QuitFLAC();
   10.43 @@ -207,6 +226,11 @@
   10.44  		Mix_QuitOgg();
   10.45  	}
   10.46  #endif
   10.47 +#ifdef MID_MUSIC
   10.48 +	if (soundfont_paths) {
   10.49 +		free(soundfont_paths);
   10.50 +	}
   10.51 +#endif
   10.52  	initialized = 0;
   10.53  }
   10.54  
    11.1 --- a/music.c	Tue Mar 15 23:11:29 2011 -0700
    11.2 +++ b/music.c	Sun Mar 20 14:34:18 2011 +0000
    11.3 @@ -48,14 +48,12 @@
    11.4  #  ifdef USE_TIMIDITY_MIDI
    11.5  #    include "timidity.h"
    11.6  #  endif
    11.7 +#  ifdef USE_FLUIDSYNTH_MIDI
    11.8 +#    include "fluidsynth.h"
    11.9 +#  endif
   11.10  #  ifdef USE_NATIVE_MIDI
   11.11  #    include "native_midi.h"
   11.12  #  endif
   11.13 -#  if defined(USE_TIMIDITY_MIDI) && defined(USE_NATIVE_MIDI)
   11.14 -#    define MIDI_ELSE	else
   11.15 -#  else
   11.16 -#    define MIDI_ELSE
   11.17 -#  endif
   11.18  #endif
   11.19  #ifdef OGG_MUSIC
   11.20  #include "music_ogg.h"
   11.21 @@ -101,6 +99,9 @@
   11.22  #ifdef USE_TIMIDITY_MIDI
   11.23  		MidiSong *midi;
   11.24  #endif
   11.25 +#ifdef USE_FLUIDSYNTH_MIDI
   11.26 +		FluidSynthMidiSong *fluidsynthmidi;
   11.27 +#endif
   11.28  #ifdef USE_NATIVE_MIDI
   11.29  		NativeMidiSong *nativemidi;
   11.30  #endif
   11.31 @@ -128,6 +129,9 @@
   11.32  static int timidity_ok;
   11.33  static int samplesize;
   11.34  #endif
   11.35 +#ifdef USE_FLUIDSYNTH_MIDI
   11.36 +static int fluidsynth_ok;
   11.37 +#endif
   11.38  #ifdef USE_NATIVE_MIDI
   11.39  static int native_midi_ok;
   11.40  #endif
   11.41 @@ -140,6 +144,11 @@
   11.42  static const char **music_decoders = NULL;
   11.43  static int num_decoders = 0;
   11.44  
   11.45 +/* Semicolon-separated SoundFont paths */
   11.46 +#ifdef MID_MUSIC
   11.47 +char* soundfont_paths = NULL;
   11.48 +#endif
   11.49 +
   11.50  int Mix_GetNumMusicDecoders(void)
   11.51  {
   11.52  	return(num_decoders);
   11.53 @@ -270,15 +279,22 @@
   11.54  				break;
   11.55  #endif
   11.56  #ifdef MID_MUSIC
   11.57 +			case MUS_MID:
   11.58 +#ifdef USE_FLUIDSYNTH_MIDI
   11.59 +				if ( fluidsynth_ok ) {
   11.60 +					fluidsynth_playsome(music_playing->data.fluidsynthmidi, stream, len);
   11.61 +					goto skip;
   11.62 +				}
   11.63 +#endif
   11.64  #ifdef USE_TIMIDITY_MIDI
   11.65 -			case MUS_MID:
   11.66  				if ( timidity_ok ) {
   11.67  					int samples = len / samplesize;
   11.68    					Timidity_PlaySome(stream, samples);
   11.69 +					goto skip;
   11.70  				}
   11.71 +#endif
   11.72  				break;
   11.73  #endif
   11.74 -#endif
   11.75  #ifdef OGG_MUSIC
   11.76  			case MUS_OGG:
   11.77  				
   11.78 @@ -306,6 +322,7 @@
   11.79  		}
   11.80  	}
   11.81  
   11.82 +skip:
   11.83  	/* Handle seamless music looping */
   11.84  	if (left > 0 && left < len && music_halt_or_loop()) {
   11.85  		music_mixer(udata, stream+(len-left), left);
   11.86 @@ -341,9 +358,21 @@
   11.87  		timidity_ok = 0;
   11.88  	}
   11.89  #endif
   11.90 +#ifdef USE_FLUIDSYNTH_MIDI
   11.91 +	if ( fluidsynth_init(mixer) == 0 ) {
   11.92 +		fluidsynth_ok = 1;
   11.93 +		add_music_decoder("FLUIDSYNTH");
   11.94 +	} else {
   11.95 +		fluidsynth_ok = 0;
   11.96 +	}
   11.97 +#endif
   11.98  #ifdef USE_NATIVE_MIDI
   11.99 +#ifdef USE_FLUIDSYNTH_MIDI
  11.100 +	native_midi_ok = !fluidsynth_ok;
  11.101 +	if ( native_midi_ok )
  11.102 +#endif
  11.103  #ifdef USE_TIMIDITY_MIDI
  11.104 -	native_midi_ok = !timidity_ok;
  11.105 +		native_midi_ok = !timidity_ok;
  11.106  	if ( !native_midi_ok ) {
  11.107  		native_midi_ok = (getenv("SDL_NATIVE_MUSIC") != NULL);
  11.108  	}
  11.109 @@ -469,7 +498,17 @@
  11.110  		  		Mix_SetError("%s", native_midi_error());
  11.111  			  	music->error = 1;
  11.112  			}
  11.113 -	  	} MIDI_ELSE
  11.114 +			goto skip;
  11.115 +	  	}
  11.116 +#endif
  11.117 +#ifdef USE_FLUIDSYNTH_MIDI
  11.118 +		if ( fluidsynth_ok ) {
  11.119 +			music->data.fluidsynthmidi = fluidsynth_loadsong(file);
  11.120 +			if ( music->data.fluidsynthmidi == NULL ) {
  11.121 +				music->error = 1;
  11.122 +			}
  11.123 +			goto skip;
  11.124 +		}
  11.125  #endif
  11.126  #ifdef USE_TIMIDITY_MIDI
  11.127  		if ( timidity_ok ) {
  11.128 @@ -565,6 +604,8 @@
  11.129  		Mix_SetError("Unrecognized music format");
  11.130  		music->error = 1;
  11.131  	}
  11.132 +
  11.133 +skip:
  11.134  	if ( music->error ) {
  11.135  		free(music);
  11.136  		music = NULL;
  11.137 @@ -616,11 +657,19 @@
  11.138  #ifdef USE_NATIVE_MIDI
  11.139    				if ( native_midi_ok ) {
  11.140  					native_midi_freesong(music->data.nativemidi);
  11.141 -				} MIDI_ELSE
  11.142 +					goto skip;
  11.143 +				}
  11.144 +#endif
  11.145 +#ifdef USE_FLUIDSYNTH_MIDI
  11.146 +				if ( fluidsynth_ok ) {
  11.147 +					fluidsynth_freesong(music->data.fluidsynthmidi);
  11.148 +					goto skip;
  11.149 +				}
  11.150  #endif
  11.151  #ifdef USE_TIMIDITY_MIDI
  11.152  				if ( timidity_ok ) {
  11.153  					Timidity_FreeSong(music->data.midi);
  11.154 +					goto skip;
  11.155  				}
  11.156  #endif
  11.157  				break;
  11.158 @@ -649,6 +698,8 @@
  11.159  				/* Unknown music type?? */
  11.160  				break;
  11.161  		}
  11.162 +
  11.163 +    skip:
  11.164  		free(music);
  11.165  	}
  11.166  }
  11.167 @@ -720,11 +771,19 @@
  11.168  #ifdef USE_NATIVE_MIDI
  11.169  		if ( native_midi_ok ) {
  11.170  			native_midi_start(music->data.nativemidi);
  11.171 -		} MIDI_ELSE
  11.172 +			goto skip;
  11.173 +		}
  11.174 +#endif
  11.175 +#ifdef USE_FLUIDSYNTH_MIDI
  11.176 +		if (fluidsynth_ok ) {
  11.177 +			fluidsynth_start(music->data.fluidsynthmidi);
  11.178 +			goto skip;
  11.179 +		}
  11.180  #endif
  11.181  #ifdef USE_TIMIDITY_MIDI
  11.182  		if ( timidity_ok ) {
  11.183  			Timidity_Start(music->data.midi);
  11.184 +			goto skip;
  11.185  		}
  11.186  #endif
  11.187  		break;
  11.188 @@ -757,6 +816,7 @@
  11.189  		break;
  11.190  	}
  11.191  
  11.192 +skip:
  11.193  	/* Set the playback position, note any errors if an offset is used */
  11.194  	if ( retval == 0 ) {
  11.195  		if ( position > 0.0 ) {
  11.196 @@ -929,11 +989,19 @@
  11.197  #ifdef USE_NATIVE_MIDI
  11.198  		if ( native_midi_ok ) {
  11.199  			native_midi_setvolume(volume);
  11.200 -		} MIDI_ELSE
  11.201 +			return;
  11.202 +		}
  11.203 +#endif
  11.204 +#ifdef USE_FLUIDSYNTH_MIDI
  11.205 +		if ( fluidsynth_ok ) {
  11.206 +			fluidsynth_setvolume(music_playing->data.fluidsynthmidi, volume);
  11.207 +			return;
  11.208 +		}
  11.209  #endif
  11.210  #ifdef USE_TIMIDITY_MIDI
  11.211  		if ( timidity_ok ) {
  11.212  			Timidity_SetVolume(volume);
  11.213 +			return;
  11.214  		}
  11.215  #endif
  11.216  		break;
  11.217 @@ -1012,11 +1080,19 @@
  11.218  #ifdef USE_NATIVE_MIDI
  11.219  		if ( native_midi_ok ) {
  11.220  			native_midi_stop();
  11.221 -		} MIDI_ELSE
  11.222 +			goto skip;
  11.223 +		}
  11.224 +#endif
  11.225 +#ifdef USE_FLUIDSYNTH_MIDI
  11.226 +		if ( fluidsynth_ok ) {
  11.227 +			fluidsynth_stop(music_playing->data.fluidsynthmidi);
  11.228 +			goto skip;
  11.229 +		}
  11.230  #endif
  11.231  #ifdef USE_TIMIDITY_MIDI
  11.232  		if ( timidity_ok ) {
  11.233  			Timidity_Stop();
  11.234 +			goto skip;
  11.235  		}
  11.236  #endif
  11.237  		break;
  11.238 @@ -1045,6 +1121,8 @@
  11.239  		/* Unknown music type?? */
  11.240  		return;
  11.241  	}
  11.242 +
  11.243 +skip:
  11.244  	music_playing->fading = MIX_NO_FADING;
  11.245  	music_playing = NULL;
  11.246  }
  11.247 @@ -1173,12 +1251,21 @@
  11.248  		if ( native_midi_ok ) {
  11.249  			if ( ! native_midi_active() )
  11.250  				playing = 0;
  11.251 -		} MIDI_ELSE
  11.252 +			goto skip;
  11.253 +		}
  11.254 +#endif
  11.255 +#ifdef USE_FLUIDSYNTH_MIDI
  11.256 +		if ( fluidsynth_ok ) {
  11.257 +			if ( ! fluidsynth_active(music_playing->data.fluidsynthmidi) )
  11.258 +				playing = 0;
  11.259 +			goto skip;
  11.260 +		}
  11.261  #endif
  11.262  #ifdef USE_TIMIDITY_MIDI
  11.263  		if ( timidity_ok ) {
  11.264  			if ( ! Timidity_Active() )
  11.265  				playing = 0;
  11.266 +			goto skip;
  11.267  		}
  11.268  #endif
  11.269  		break;
  11.270 @@ -1214,6 +1301,8 @@
  11.271  		playing = 0;
  11.272  		break;
  11.273  	}
  11.274 +
  11.275 +skip:
  11.276  	return(playing);
  11.277  }
  11.278  int Mix_PlayingMusic(void)
  11.279 @@ -1393,7 +1482,17 @@
  11.280  		  		Mix_SetError("%s", native_midi_error());
  11.281  			  	music->error = 1;
  11.282  			}
  11.283 -		} MIDI_ELSE
  11.284 +			goto skip;
  11.285 +		}
  11.286 +#endif
  11.287 +#ifdef USE_FLUIDSYNTH_MIDI
  11.288 +		if ( fluidsynth_ok ) {
  11.289 +			music->data.fluidsynthmidi = fluidsynth_loadsong_RW(rw);
  11.290 +			if ( music->data.fluidsynthmidi == NULL ) {
  11.291 +				music->error = 1;
  11.292 +			}
  11.293 +			goto skip;
  11.294 +		}
  11.295  #endif
  11.296  #ifdef USE_TIMIDITY_MIDI
  11.297  		if ( timidity_ok ) {
  11.298 @@ -1436,9 +1535,72 @@
  11.299  		Mix_SetError("Unrecognized music format");
  11.300  		music->error=1;
  11.301  	}
  11.302 +
  11.303 +skip:
  11.304  	if (music->error) {
  11.305  		free(music);
  11.306  		music=NULL;
  11.307  	}
  11.308  	return(music);
  11.309  }
  11.310 +
  11.311 +int Mix_SetSoundFonts(const char *paths)
  11.312 +{
  11.313 +#ifdef MID_MUSIC
  11.314 +	if (soundfont_paths) {
  11.315 +		free(soundfont_paths);
  11.316 +		soundfont_paths = NULL;
  11.317 +	}
  11.318 +
  11.319 +	if (paths) {
  11.320 +		if (!(soundfont_paths = strdup(paths))) {
  11.321 +			Mix_SetError("Insufficient memory to set SoundFonts");
  11.322 +			return 0;
  11.323 +		}
  11.324 +	}
  11.325 +#endif
  11.326 +	return 1;
  11.327 +}
  11.328 +
  11.329 +#ifdef MID_MUSIC
  11.330 +const char* Mix_GetSoundFonts()
  11.331 +{
  11.332 +	const char* force = getenv("SDL_FORCE_SOUNDFONTS");
  11.333 +
  11.334 +	if (!soundfont_paths || (force && force[0] == '1')) {
  11.335 +		return getenv("SDL_SOUNDFONTS");
  11.336 +	} else {
  11.337 +		return soundfont_paths;
  11.338 +	}
  11.339 +}
  11.340 +
  11.341 +int Mix_EachSoundFont(int (*function)(const char*, void*), void *data)
  11.342 +{
  11.343 +	char *context, *path, *paths;
  11.344 +	const char* cpaths = Mix_GetSoundFonts();
  11.345 +
  11.346 +	if (!cpaths) {
  11.347 +		Mix_SetError("No SoundFonts have been requested");
  11.348 +		return 0;
  11.349 +	}
  11.350 +
  11.351 +	if (!(paths = strdup(cpaths))) {
  11.352 +		Mix_SetError("Insufficient memory to iterate over SoundFonts");
  11.353 +		return 0;
  11.354 +	}
  11.355 +
  11.356 +#ifdef _WIN32
  11.357 +	for (path = strtok_s(paths, ";", &context); path; path = strtok_s(NULL, ";", &context)) {
  11.358 +#else
  11.359 +	for (path = strtok_r(paths, ":;", &context); path; path = strtok_r(NULL, ":;", &context)) {
  11.360 +#endif
  11.361 +		if (!function(path, data)) {
  11.362 +			free(paths);
  11.363 +			return 0;
  11.364 +		}
  11.365 +	}
  11.366 +
  11.367 +	free(paths);
  11.368 +	return 1;
  11.369 +}
  11.370 +#endif