Simplified music interface library loading
authorSam Lantinga <slouken@libsdl.org>
Sat, 21 Oct 2017 00:53:21 -0700
changeset 7989b6d7d1b3a23
parent 797 b4b6adff699a
child 799 82dcc7ce6d20
Simplified music interface library loading
Also implemented SDL_AudioStream functionality for mikmod music loader
configure
configure.in
music_flac.c
music_fluidsynth.c
music_mikmod.c
music_modplug.c
music_mpg123.c
music_ogg.c
music_smpeg.c
     1.1 --- a/configure	Fri Oct 20 23:39:04 2017 -0700
     1.2 +++ b/configure	Sat Oct 21 00:53:21 2017 -0700
     1.3 @@ -12074,7 +12074,7 @@
     1.4          EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MOD_MIKMOD `$LIBMIKMOD_CONFIG --cflags`"
     1.5          if test x$enable_music_mod_mikmod_shared = xyes && test x$mikmod_lib != x; then
     1.6              echo "-- dynamic libmikmod -> $mikmod_lib"
     1.7 -            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMOD_DYNAMIC=\\\"$mikmod_lib\\\""
     1.8 +            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMIKMOD_DYNAMIC=\\\"$mikmod_lib\\\""
     1.9          else
    1.10              EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$LIBMIKMOD_CONFIG --libs`"
    1.11          fi
     2.1 --- a/configure.in	Fri Oct 20 23:39:04 2017 -0700
     2.2 +++ b/configure.in	Sat Oct 21 00:53:21 2017 -0700
     2.3 @@ -337,7 +337,7 @@
     2.4          EXTRA_CFLAGS="$EXTRA_CFLAGS -DMUSIC_MOD_MIKMOD `$LIBMIKMOD_CONFIG --cflags`"
     2.5          if test x$enable_music_mod_mikmod_shared = xyes && test x$mikmod_lib != x; then
     2.6              echo "-- dynamic libmikmod -> $mikmod_lib"
     2.7 -            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMOD_DYNAMIC=\\\"$mikmod_lib\\\""
     2.8 +            EXTRA_CFLAGS="$EXTRA_CFLAGS -DMIKMOD_DYNAMIC=\\\"$mikmod_lib\\\""
     2.9          else
    2.10              EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$LIBMIKMOD_CONFIG --libs`"
    2.11          fi
     3.1 --- a/music_flac.c	Fri Oct 20 23:39:04 2017 -0700
     3.2 +++ b/music_flac.c	Sat Oct 21 00:53:21 2017 -0700
     3.3 @@ -68,30 +68,35 @@
     3.4  };
     3.5  
     3.6  #ifdef FLAC_DYNAMIC
     3.7 +#define FUNCTION_LOADER(FUNC, SIG) \
     3.8 +    flac.FUNC = (SIG) SDL_LoadFunction(flac.handle, #FUNC); \
     3.9 +    if (flac.FUNC == NULL) { SDL_UnloadObject(flac.handle); return -1; }
    3.10 +#else
    3.11 +#define FUNCTION_LOADER(FUNC, SIG) \
    3.12 +    flac.FUNC = FUNC;
    3.13 +#endif
    3.14  
    3.15  static int FLAC_Load(void)
    3.16  {
    3.17      if (flac.loaded == 0) {
    3.18 +#ifdef FLAC_DYNAMIC
    3.19          flac.handle = SDL_LoadObject(FLAC_DYNAMIC);
    3.20          if (flac.handle == NULL) {
    3.21              return -1;
    3.22          }
    3.23 -        flac.FLAC__stream_decoder_new =
    3.24 -            (FLAC__StreamDecoder *(*)(void))
    3.25 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_new");
    3.26 -        if (flac.FLAC__stream_decoder_new == NULL) {
    3.27 -            SDL_UnloadObject(flac.handle);
    3.28 +#elif defined(__MACOSX__)
    3.29 +        extern FLAC__StreamDecoder *FLAC__stream_decoder_new(void) __attribute__((weak_import));
    3.30 +        if (FLAC__stream_decoder_new == NULL)
    3.31 +        {
    3.32 +            /* Missing weakly linked framework */
    3.33 +            Mix_SetError("Missing FLAC.framework");
    3.34              return -1;
    3.35          }
    3.36 -        flac.FLAC__stream_decoder_delete =
    3.37 -            (void (*)(FLAC__StreamDecoder *))
    3.38 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_delete");
    3.39 -        if (flac.FLAC__stream_decoder_delete == NULL) {
    3.40 -            SDL_UnloadObject(flac.handle);
    3.41 -            return -1;
    3.42 -        }
    3.43 -        flac.FLAC__stream_decoder_init_stream =
    3.44 -            (FLAC__StreamDecoderInitStatus (*)(
    3.45 +#endif
    3.46 +
    3.47 +        FUNCTION_LOADER(FLAC__stream_decoder_new, FLAC__StreamDecoder *(*)(void))
    3.48 +        FUNCTION_LOADER(FLAC__stream_decoder_delete, void (*)(FLAC__StreamDecoder *))
    3.49 +        FUNCTION_LOADER(FLAC__stream_decoder_init_stream, FLAC__StreamDecoderInitStatus (*)(
    3.50                          FLAC__StreamDecoder *,
    3.51                          FLAC__StreamDecoderReadCallback,
    3.52                          FLAC__StreamDecoderSeekCallback,
    3.53 @@ -102,63 +107,13 @@
    3.54                          FLAC__StreamDecoderMetadataCallback,
    3.55                          FLAC__StreamDecoderErrorCallback,
    3.56                          void *))
    3.57 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_init_stream");
    3.58 -        if (flac.FLAC__stream_decoder_init_stream == NULL) {
    3.59 -            SDL_UnloadObject(flac.handle);
    3.60 -            return -1;
    3.61 -        }
    3.62 -        flac.FLAC__stream_decoder_finish =
    3.63 -            (FLAC__bool (*)(FLAC__StreamDecoder *))
    3.64 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_finish");
    3.65 -        if (flac.FLAC__stream_decoder_finish == NULL) {
    3.66 -            SDL_UnloadObject(flac.handle);
    3.67 -            return -1;
    3.68 -        }
    3.69 -        flac.FLAC__stream_decoder_flush =
    3.70 -            (FLAC__bool (*)(FLAC__StreamDecoder *))
    3.71 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_flush");
    3.72 -        if (flac.FLAC__stream_decoder_flush == NULL) {
    3.73 -            SDL_UnloadObject(flac.handle);
    3.74 -            return -1;
    3.75 -        }
    3.76 -        flac.FLAC__stream_decoder_process_single =
    3.77 -            (FLAC__bool (*)(FLAC__StreamDecoder *))
    3.78 -            SDL_LoadFunction(flac.handle,
    3.79 -                        "FLAC__stream_decoder_process_single");
    3.80 -        if (flac.FLAC__stream_decoder_process_single == NULL) {
    3.81 -            SDL_UnloadObject(flac.handle);
    3.82 -            return -1;
    3.83 -        }
    3.84 -        flac.FLAC__stream_decoder_process_until_end_of_metadata =
    3.85 -            (FLAC__bool (*)(FLAC__StreamDecoder *))
    3.86 -            SDL_LoadFunction(flac.handle,
    3.87 -                        "FLAC__stream_decoder_process_until_end_of_metadata");
    3.88 -        if (flac.FLAC__stream_decoder_process_until_end_of_metadata == NULL) {
    3.89 -            SDL_UnloadObject(flac.handle);
    3.90 -            return -1;
    3.91 -        }
    3.92 -        flac.FLAC__stream_decoder_process_until_end_of_stream =
    3.93 -            (FLAC__bool (*)(FLAC__StreamDecoder *))
    3.94 -            SDL_LoadFunction(flac.handle,
    3.95 -                        "FLAC__stream_decoder_process_until_end_of_stream");
    3.96 -        if (flac.FLAC__stream_decoder_process_until_end_of_stream == NULL) {
    3.97 -            SDL_UnloadObject(flac.handle);
    3.98 -            return -1;
    3.99 -        }
   3.100 -        flac.FLAC__stream_decoder_seek_absolute =
   3.101 -            (FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
   3.102 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_seek_absolute");
   3.103 -        if (flac.FLAC__stream_decoder_seek_absolute == NULL) {
   3.104 -            SDL_UnloadObject(flac.handle);
   3.105 -            return -1;
   3.106 -        }
   3.107 -        flac.FLAC__stream_decoder_get_state =
   3.108 -            (FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
   3.109 -            SDL_LoadFunction(flac.handle, "FLAC__stream_decoder_get_state");
   3.110 -        if (flac.FLAC__stream_decoder_get_state == NULL) {
   3.111 -            SDL_UnloadObject(flac.handle);
   3.112 -            return -1;
   3.113 -        }
   3.114 +        FUNCTION_LOADER(FLAC__stream_decoder_finish, FLAC__bool (*)(FLAC__StreamDecoder *))
   3.115 +        FUNCTION_LOADER(FLAC__stream_decoder_flush, FLAC__bool (*)(FLAC__StreamDecoder *))
   3.116 +        FUNCTION_LOADER(FLAC__stream_decoder_process_single, FLAC__bool (*)(FLAC__StreamDecoder *))
   3.117 +        FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_metadata, FLAC__bool (*)(FLAC__StreamDecoder *))
   3.118 +        FUNCTION_LOADER(FLAC__stream_decoder_process_until_end_of_stream, FLAC__bool (*)(FLAC__StreamDecoder *))
   3.119 +        FUNCTION_LOADER(FLAC__stream_decoder_seek_absolute, FLAC__bool (*)(FLAC__StreamDecoder *, FLAC__uint64))
   3.120 +        FUNCTION_LOADER(FLAC__stream_decoder_get_state, FLAC__StreamDecoderState (*)(const FLAC__StreamDecoder *decoder))
   3.121      }
   3.122      ++flac.loaded;
   3.123  
   3.124 @@ -171,60 +126,13 @@
   3.125          return;
   3.126      }
   3.127      if (flac.loaded == 1) {
   3.128 +#ifdef FLAC_DYNAMIC
   3.129          SDL_UnloadObject(flac.handle);
   3.130 +#endif
   3.131      }
   3.132      --flac.loaded;
   3.133  }
   3.134  
   3.135 -#else /* !FLAC_DYNAMIC */
   3.136 -
   3.137 -static int FLAC_Load(void)
   3.138 -{
   3.139 -    if (flac.loaded == 0) {
   3.140 -#ifdef __MACOSX__
   3.141 -        extern FLAC__StreamDecoder *FLAC__stream_decoder_new(void) __attribute__((weak_import));
   3.142 -        if (FLAC__stream_decoder_new == NULL)
   3.143 -        {
   3.144 -            /* Missing weakly linked framework */
   3.145 -            Mix_SetError("Missing FLAC.framework");
   3.146 -            return -1;
   3.147 -        }
   3.148 -#endif /* __MACOSX__ */
   3.149 -
   3.150 -        flac.FLAC__stream_decoder_new = FLAC__stream_decoder_new;
   3.151 -        flac.FLAC__stream_decoder_delete = FLAC__stream_decoder_delete;
   3.152 -        flac.FLAC__stream_decoder_init_stream =
   3.153 -                            FLAC__stream_decoder_init_stream;
   3.154 -        flac.FLAC__stream_decoder_finish = FLAC__stream_decoder_finish;
   3.155 -        flac.FLAC__stream_decoder_flush = FLAC__stream_decoder_flush;
   3.156 -        flac.FLAC__stream_decoder_process_single =
   3.157 -                            FLAC__stream_decoder_process_single;
   3.158 -        flac.FLAC__stream_decoder_process_until_end_of_metadata =
   3.159 -                            FLAC__stream_decoder_process_until_end_of_metadata;
   3.160 -        flac.FLAC__stream_decoder_process_until_end_of_stream =
   3.161 -                            FLAC__stream_decoder_process_until_end_of_stream;
   3.162 -        flac.FLAC__stream_decoder_seek_absolute =
   3.163 -                            FLAC__stream_decoder_seek_absolute;
   3.164 -        flac.FLAC__stream_decoder_get_state =
   3.165 -                            FLAC__stream_decoder_get_state;
   3.166 -    }
   3.167 -    ++flac.loaded;
   3.168 -
   3.169 -    return 0;
   3.170 -}
   3.171 -
   3.172 -static void FLAC_Unload(void)
   3.173 -{
   3.174 -    if (flac.loaded == 0) {
   3.175 -        return;
   3.176 -    }
   3.177 -    if (flac.loaded == 1) {
   3.178 -    }
   3.179 -    --flac.loaded;
   3.180 -}
   3.181 -
   3.182 -#endif /* FLAC_DYNAMIC */
   3.183 -
   3.184  
   3.185  typedef struct {
   3.186      int volume;
     4.1 --- a/music_fluidsynth.c	Fri Oct 20 23:39:04 2017 -0700
     4.2 +++ b/music_fluidsynth.c	Sat Oct 21 00:53:21 2017 -0700
     4.3 @@ -78,7 +78,6 @@
     4.4              return -1;
     4.5          }
     4.6  #endif
     4.7 -
     4.8          FUNCTION_LOADER(delete_fluid_player, int (*)(fluid_player_t*))
     4.9          FUNCTION_LOADER(delete_fluid_settings, void (*)(fluid_settings_t*))
    4.10          FUNCTION_LOADER(delete_fluid_synth, int (*)(fluid_synth_t*))
     5.1 --- a/music_mikmod.c	Fri Oct 20 23:39:04 2017 -0700
     5.2 +++ b/music_mikmod.c	Sat Oct 21 00:53:21 2017 -0700
     5.3 @@ -20,7 +20,6 @@
     5.4  */
     5.5  
     5.6  #ifdef MUSIC_MOD_MIKMOD
     5.7 -#error Implement play_count and audio stream conversion
     5.8  
     5.9  /* This file supports MOD tracker music streams */
    5.10  
    5.11 @@ -31,8 +30,6 @@
    5.12  #include "mikmod.h"
    5.13  
    5.14  
    5.15 -#define MAX_OUTPUT_CHANNELS 6
    5.16 -
    5.17  /* libmikmod >= 3.3.2 constified several funcs */
    5.18  #if (LIBMIKMOD_VERSION < 0x030302)
    5.19  #define MIKMOD3_CONST
    5.20 @@ -76,197 +73,75 @@
    5.21      0, NULL
    5.22  };
    5.23  
    5.24 -#ifdef MOD_DYNAMIC
    5.25 +#ifdef MIKMOD_DYNAMIC
    5.26 +#define FUNCTION_LOADER(FUNC, SIG) \
    5.27 +    mikmod.FUNC = (SIG) SDL_LoadFunction(mikmod.handle, #FUNC); \
    5.28 +    if (mikmod.FUNC == NULL) { SDL_UnloadObject(mikmod.handle); return -1; }
    5.29 +#define VARIABLE_LOADER(NAME, SIG) \
    5.30 +    mikmod.NAME = (SIG) SDL_LoadFunction(mikmod.handle, #NAME); \
    5.31 +    if (mikmod.NAME == NULL) { SDL_UnloadObject(mikmod.handle); return -1; }
    5.32 +#else
    5.33 +#define FUNCTION_LOADER(FUNC, SIG) \
    5.34 +    mikmod.FUNC = FUNC;
    5.35 +#define VARIABLE_LOADER(NAME, SIG) \
    5.36 +    mikmod.NAME = &NAME;
    5.37 +#endif
    5.38  
    5.39  static int MIKMOD_Load()
    5.40  {
    5.41      if (mikmod.loaded == 0) {
    5.42 -        mikmod.handle = SDL_LoadObject(MOD_DYNAMIC);
    5.43 +#ifdef MIKMOD_DYNAMIC
    5.44 +        mikmod.handle = SDL_LoadObject(MIKMOD_DYNAMIC);
    5.45          if (mikmod.handle == NULL) {
    5.46              return -1;
    5.47          }
    5.48 -        mikmod.MikMod_Exit =
    5.49 -            (void (*)(void))
    5.50 -            SDL_LoadFunction(mikmod.handle, "MikMod_Exit");
    5.51 -        if (mikmod.MikMod_Exit == NULL) {
    5.52 -            SDL_UnloadObject(mikmod.handle);
    5.53 +#elif defined(__MACOSX__)
    5.54 +        extern void Player_Start(MODULE*) __attribute__((weak_import));
    5.55 +        if (Player_Start == NULL)
    5.56 +        {
    5.57 +            /* Missing weakly linked framework */
    5.58 +            Mix_SetError("Missing mikmod.framework");
    5.59              return -1;
    5.60          }
    5.61 -        mikmod.MikMod_InfoDriver =
    5.62 -            (CHAR* (*)(void))
    5.63 -            SDL_LoadFunction(mikmod.handle, "MikMod_InfoDriver");
    5.64 -        if (mikmod.MikMod_InfoDriver == NULL) {
    5.65 -            SDL_UnloadObject(mikmod.handle);
    5.66 -            return -1;
    5.67 -        }
    5.68 -        mikmod.MikMod_InfoLoader =
    5.69 -            (CHAR* (*)(void))
    5.70 -            SDL_LoadFunction(mikmod.handle, "MikMod_InfoLoader");
    5.71 -        if (mikmod.MikMod_InfoLoader == NULL) {
    5.72 -            SDL_UnloadObject(mikmod.handle);
    5.73 -            return -1;
    5.74 -        }
    5.75 -        mikmod.MikMod_Init =
    5.76 -            (int (*)(MIKMOD3_CONST CHAR*))
    5.77 -            SDL_LoadFunction(mikmod.handle, "MikMod_Init");
    5.78 -        if (mikmod.MikMod_Init == NULL) {
    5.79 -            SDL_UnloadObject(mikmod.handle);
    5.80 -            return -1;
    5.81 -        }
    5.82 -        mikmod.MikMod_RegisterAllLoaders =
    5.83 -            (void (*)(void))
    5.84 -            SDL_LoadFunction(mikmod.handle, "MikMod_RegisterAllLoaders");
    5.85 -        if (mikmod.MikMod_RegisterAllLoaders == NULL) {
    5.86 -            SDL_UnloadObject(mikmod.handle);
    5.87 -            return -1;
    5.88 -        }
    5.89 -        mikmod.MikMod_RegisterDriver =
    5.90 -            (void (*)(struct MDRIVER*))
    5.91 -            SDL_LoadFunction(mikmod.handle, "MikMod_RegisterDriver");
    5.92 -        if (mikmod.MikMod_RegisterDriver == NULL) {
    5.93 -            SDL_UnloadObject(mikmod.handle);
    5.94 -            return -1;
    5.95 -        }
    5.96 -        mikmod.MikMod_errno =
    5.97 -            (int*)
    5.98 -            SDL_LoadFunction(mikmod.handle, "MikMod_errno");
    5.99 -        if (mikmod.MikMod_errno == NULL) {
   5.100 -            SDL_UnloadObject(mikmod.handle);
   5.101 -            return -1;
   5.102 -        }
   5.103 -        mikmod.MikMod_strerror =
   5.104 -            (MIKMOD3_CONST char* (*)(int))
   5.105 -            SDL_LoadFunction(mikmod.handle, "MikMod_strerror");
   5.106 -        if (mikmod.MikMod_strerror == NULL) {
   5.107 -            SDL_UnloadObject(mikmod.handle);
   5.108 -            return -1;
   5.109 -        }
   5.110 -        mikmod.MikMod_free =
   5.111 -            (void (*)(void*))
   5.112 -            SDL_LoadFunction(mikmod.handle, "MikMod_free");
   5.113 -        if (mikmod.MikMod_free == NULL) {
   5.114 +#endif
   5.115 +        FUNCTION_LOADER(MikMod_Exit, void (*)(void))
   5.116 +        FUNCTION_LOADER(MikMod_InfoDriver, CHAR* (*)(void))
   5.117 +        FUNCTION_LOADER(MikMod_InfoLoader, CHAR* (*)(void))
   5.118 +        FUNCTION_LOADER(MikMod_Init, int (*)(MIKMOD3_CONST CHAR*))
   5.119 +        FUNCTION_LOADER(MikMod_RegisterAllLoaders, void (*)(void))
   5.120 +        FUNCTION_LOADER(MikMod_RegisterDriver, void (*)(struct MDRIVER*))
   5.121 +        VARIABLE_LOADER(MikMod_errno, int*)
   5.122 +        FUNCTION_LOADER(MikMod_strerror, MIKMOD3_CONST char* (*)(int))
   5.123 +#ifdef MIKMOD_DYNAMIC
   5.124 +        mikmod.MikMod_free = (void (*)(void*)) SDL_LoadFunction(mikmod.handle, "MikMod_free");
   5.125 +        if (!mikmod.MikMod_free) {
   5.126              /* libmikmod 3.1 and earlier doesn't have it */
   5.127              mikmod.MikMod_free = free;
   5.128          }
   5.129 -        mikmod.Player_Active =
   5.130 -            (BOOL (*)(void))
   5.131 -            SDL_LoadFunction(mikmod.handle, "Player_Active");
   5.132 -        if (mikmod.Player_Active == NULL) {
   5.133 -            SDL_UnloadObject(mikmod.handle);
   5.134 -            return -1;
   5.135 -        }
   5.136 -        mikmod.Player_Free =
   5.137 -            (void (*)(MODULE*))
   5.138 -            SDL_LoadFunction(mikmod.handle, "Player_Free");
   5.139 -        if (mikmod.Player_Free == NULL) {
   5.140 -            SDL_UnloadObject(mikmod.handle);
   5.141 -            return -1;
   5.142 -        }
   5.143 -        mikmod.Player_LoadGeneric =
   5.144 -            (MODULE* (*)(MREADER*,int,BOOL))
   5.145 -            SDL_LoadFunction(mikmod.handle, "Player_LoadGeneric");
   5.146 -        if (mikmod.Player_LoadGeneric == NULL) {
   5.147 -            SDL_UnloadObject(mikmod.handle);
   5.148 -            return -1;
   5.149 -        }
   5.150 -        mikmod.Player_SetPosition =
   5.151 -            (void (*)(UWORD))
   5.152 -            SDL_LoadFunction(mikmod.handle, "Player_SetPosition");
   5.153 -        if (mikmod.Player_SetPosition == NULL) {
   5.154 -            SDL_UnloadObject(mikmod.handle);
   5.155 -            return -1;
   5.156 -        }
   5.157 -        mikmod.Player_SetVolume =
   5.158 -            (void (*)(SWORD))
   5.159 -            SDL_LoadFunction(mikmod.handle, "Player_SetVolume");
   5.160 -        if (mikmod.Player_SetVolume == NULL) {
   5.161 -            SDL_UnloadObject(mikmod.handle);
   5.162 -            return -1;
   5.163 -        }
   5.164 -        mikmod.Player_Start =
   5.165 -            (void (*)(MODULE*))
   5.166 -            SDL_LoadFunction(mikmod.handle, "Player_Start");
   5.167 -        if (mikmod.Player_Start == NULL) {
   5.168 -            SDL_UnloadObject(mikmod.handle);
   5.169 -            return -1;
   5.170 -        }
   5.171 -        mikmod.Player_Stop =
   5.172 -            (void (*)(void))
   5.173 -            SDL_LoadFunction(mikmod.handle, "Player_Stop");
   5.174 -        if (mikmod.Player_Stop == NULL) {
   5.175 -            SDL_UnloadObject(mikmod.handle);
   5.176 -            return -1;
   5.177 -        }
   5.178 -        mikmod.VC_WriteBytes =
   5.179 -            (ULONG (*)(SBYTE*,ULONG))
   5.180 -            SDL_LoadFunction(mikmod.handle, "VC_WriteBytes");
   5.181 -        if (mikmod.VC_WriteBytes == NULL) {
   5.182 -            SDL_UnloadObject(mikmod.handle);
   5.183 -            return -1;
   5.184 -        }
   5.185 -        mikmod.drv_nos =
   5.186 -            (MDRIVER*)
   5.187 -            SDL_LoadFunction(mikmod.handle, "drv_nos");
   5.188 -        if (mikmod.drv_nos == NULL) {
   5.189 -            SDL_UnloadObject(mikmod.handle);
   5.190 -            return -1;
   5.191 -        }
   5.192 -        mikmod.md_device =
   5.193 -            (UWORD*)
   5.194 -            SDL_LoadFunction(mikmod.handle, "md_device");
   5.195 -        if (mikmod.md_device == NULL) {
   5.196 -            SDL_UnloadObject(mikmod.handle);
   5.197 -            return -1;
   5.198 -        }
   5.199 -        mikmod.md_mixfreq =
   5.200 -            (UWORD*)
   5.201 -            SDL_LoadFunction(mikmod.handle, "md_mixfreq");
   5.202 -        if (mikmod.md_mixfreq == NULL) {
   5.203 -            SDL_UnloadObject(mikmod.handle);
   5.204 -            return -1;
   5.205 -        }
   5.206 -        mikmod.md_mode =
   5.207 -            (UWORD*)
   5.208 -            SDL_LoadFunction(mikmod.handle, "md_mode");
   5.209 -        if (mikmod.md_mode == NULL) {
   5.210 -            SDL_UnloadObject(mikmod.handle);
   5.211 -            return -1;
   5.212 -        }
   5.213 -        mikmod.md_musicvolume =
   5.214 -            (UBYTE*)
   5.215 -            SDL_LoadFunction(mikmod.handle, "md_musicvolume");
   5.216 -        if (mikmod.md_musicvolume == NULL) {
   5.217 -            SDL_UnloadObject(mikmod.handle);
   5.218 -            return -1;
   5.219 -        }
   5.220 -        mikmod.md_pansep =
   5.221 -            (UBYTE*)
   5.222 -            SDL_LoadFunction(mikmod.handle, "md_pansep");
   5.223 -        if (mikmod.md_pansep == NULL) {
   5.224 -            SDL_UnloadObject(mikmod.handle);
   5.225 -            return -1;
   5.226 -        }
   5.227 -        mikmod.md_reverb =
   5.228 -            (UBYTE*)
   5.229 -            SDL_LoadFunction(mikmod.handle, "md_reverb");
   5.230 -        if (mikmod.md_reverb == NULL) {
   5.231 -            SDL_UnloadObject(mikmod.handle);
   5.232 -            return -1;
   5.233 -        }
   5.234 -        mikmod.md_sndfxvolume =
   5.235 -            (UBYTE*)
   5.236 -            SDL_LoadFunction(mikmod.handle, "md_sndfxvolume");
   5.237 -        if (mikmod.md_sndfxvolume == NULL) {
   5.238 -            SDL_UnloadObject(mikmod.handle);
   5.239 -            return -1;
   5.240 -        }
   5.241 -        mikmod.md_volume =
   5.242 -            (UBYTE*)
   5.243 -            SDL_LoadFunction(mikmod.handle, "md_volume");
   5.244 -        if (mikmod.md_volume == NULL) {
   5.245 -            SDL_UnloadObject(mikmod.handle);
   5.246 -            return -1;
   5.247 -        }
   5.248 +#else
   5.249 +#if LIBMIKMOD_VERSION < ((3<<16)|(2<<8))
   5.250 +        mikmod.MikMod_free = free;
   5.251 +#else
   5.252 +        mikmod.MikMod_free = MikMod_free;
   5.253 +#endif
   5.254 +#endif /* MIKMOD_DYNAMIC */
   5.255 +        FUNCTION_LOADER(Player_Active, BOOL (*)(void))
   5.256 +        FUNCTION_LOADER(Player_Free, void (*)(MODULE*))
   5.257 +        FUNCTION_LOADER(Player_LoadGeneric, MODULE* (*)(MREADER*,int,BOOL))
   5.258 +        FUNCTION_LOADER(Player_SetPosition, void (*)(UWORD))
   5.259 +        FUNCTION_LOADER(Player_SetVolume, void (*)(SWORD))
   5.260 +        FUNCTION_LOADER(Player_Start, void (*)(MODULE*))
   5.261 +        FUNCTION_LOADER(Player_Stop, void (*)(void))
   5.262 +        FUNCTION_LOADER(VC_WriteBytes, ULONG (*)(SBYTE*,ULONG))
   5.263 +        VARIABLE_LOADER(drv_nos, MDRIVER*)
   5.264 +        VARIABLE_LOADER(md_device, UWORD*)
   5.265 +        VARIABLE_LOADER(md_mixfreq, UWORD*)
   5.266 +        VARIABLE_LOADER(md_mode, UWORD*)
   5.267 +        VARIABLE_LOADER(md_musicvolume, UBYTE*)
   5.268 +        VARIABLE_LOADER(md_pansep, UBYTE*)
   5.269 +        VARIABLE_LOADER(md_reverb, UBYTE*)
   5.270 +        VARIABLE_LOADER(md_sndfxvolume, UBYTE*)
   5.271 +        VARIABLE_LOADER(md_volume, UBYTE*)
   5.272      }
   5.273      ++mikmod.loaded;
   5.274  
   5.275 @@ -279,81 +154,27 @@
   5.276          return;
   5.277      }
   5.278      if (mikmod.loaded == 1) {
   5.279 +#ifdef MIKMOD_DYNAMIC
   5.280          SDL_UnloadObject(mikmod.handle);
   5.281 +#endif
   5.282      }
   5.283      --mikmod.loaded;
   5.284  }
   5.285  
   5.286 -#else /* !MOD_DYNAMIC */
   5.287  
   5.288 -static int MIKMOD_Load()
   5.289 +typedef struct
   5.290  {
   5.291 -    if (mikmod.loaded == 0) {
   5.292 -#ifdef __MACOSX__
   5.293 -        extern void Player_Start(MODULE*) __attribute__((weak_import));
   5.294 -        if (Player_Start == NULL)
   5.295 -        {
   5.296 -            /* Missing weakly linked framework */
   5.297 -            Mix_SetError("Missing mikmod.framework");
   5.298 -            return -1;
   5.299 -        }
   5.300 -#endif // __MACOSX__
   5.301 +    int play_count;
   5.302 +    int volume;
   5.303 +    MODULE *module;
   5.304 +    SDL_AudioStream *stream;
   5.305 +    SBYTE *buffer;
   5.306 +    ULONG buffer_size;
   5.307 +} MIKMOD_Music;
   5.308  
   5.309 -        mikmod.MikMod_Exit = MikMod_Exit;
   5.310 -        mikmod.MikMod_InfoDriver = MikMod_InfoDriver;
   5.311 -        mikmod.MikMod_InfoLoader = MikMod_InfoLoader;
   5.312 -        mikmod.MikMod_Init = MikMod_Init;
   5.313 -        mikmod.MikMod_RegisterAllLoaders = MikMod_RegisterAllLoaders;
   5.314 -        mikmod.MikMod_RegisterDriver = MikMod_RegisterDriver;
   5.315 -        mikmod.MikMod_errno = &MikMod_errno;
   5.316 -        mikmod.MikMod_strerror = MikMod_strerror;
   5.317 -#if LIBMIKMOD_VERSION < ((3<<16)|(2<<8))
   5.318 -        mikmod.MikMod_free = free;
   5.319 -#else
   5.320 -        mikmod.MikMod_free = MikMod_free;
   5.321 -#endif
   5.322 -        mikmod.Player_Active = Player_Active;
   5.323 -        mikmod.Player_Free = Player_Free;
   5.324 -        mikmod.Player_LoadGeneric = Player_LoadGeneric;
   5.325 -        mikmod.Player_SetPosition = Player_SetPosition;
   5.326 -        mikmod.Player_SetVolume = Player_SetVolume;
   5.327 -        mikmod.Player_Start = Player_Start;
   5.328 -        mikmod.Player_Stop = Player_Stop;
   5.329 -        mikmod.VC_WriteBytes = VC_WriteBytes;
   5.330 -        mikmod.drv_nos = &drv_nos;
   5.331 -        mikmod.md_device = &md_device;
   5.332 -        mikmod.md_mixfreq = &md_mixfreq;
   5.333 -        mikmod.md_mode = &md_mode;
   5.334 -        mikmod.md_musicvolume = &md_musicvolume;
   5.335 -        mikmod.md_pansep = &md_pansep;
   5.336 -        mikmod.md_reverb = &md_reverb;
   5.337 -        mikmod.md_sndfxvolume = &md_sndfxvolume;
   5.338 -        mikmod.md_volume = &md_volume;
   5.339 -    }
   5.340 -    ++mikmod.loaded;
   5.341  
   5.342 -    return 0;
   5.343 -}
   5.344 -
   5.345 -static void MIKMOD_Unload()
   5.346 -{
   5.347 -    if (mikmod.loaded == 0) {
   5.348 -        return;
   5.349 -    }
   5.350 -    if (mikmod.loaded == 1) {
   5.351 -    }
   5.352 -    --mikmod.loaded;
   5.353 -}
   5.354 -
   5.355 -#endif /* MOD_DYNAMIC */
   5.356 -
   5.357 -
   5.358 -/* Reference for converting mikmod output to 4/6 channels */
   5.359 -static int current_output_channels;
   5.360 -static Uint16 current_output_format;
   5.361 -
   5.362 -static int music_swap8;
   5.363 -static int music_swap16;
   5.364 +static int MIKMOD_Seek(void *context, double position);
   5.365 +static void MIKMOD_Delete(void *context);
   5.366  
   5.367  /* Initialize the MOD player, with the given mixer settings
   5.368     This function returns 0, or -1 if there was an error.
   5.369 @@ -363,45 +184,14 @@
   5.370      CHAR *list;
   5.371  
   5.372      /* Set the MikMod music format */
   5.373 -    music_swap8 = 0;
   5.374 -    music_swap16 = 0;
   5.375 -    switch (spec->format) {
   5.376 -
   5.377 -        case AUDIO_U8:
   5.378 -        case AUDIO_S8: {
   5.379 -            if (spec->format == AUDIO_S8) {
   5.380 -                music_swap8 = 1;
   5.381 -            }
   5.382 -            *mikmod.md_mode = 0;
   5.383 -        }
   5.384 -        break;
   5.385 -
   5.386 -        case AUDIO_S16LSB:
   5.387 -        case AUDIO_S16MSB: {
   5.388 -            /* See if we need to correct MikMod mixing */
   5.389 -#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   5.390 -            if (spec->format == AUDIO_S16MSB) {
   5.391 -#else
   5.392 -            if (spec->format == AUDIO_S16LSB) {
   5.393 -#endif
   5.394 -                music_swap16 = 1;
   5.395 -            }
   5.396 -            *mikmod.md_mode = DMODE_16BITS;
   5.397 -        }
   5.398 -        break;
   5.399 -
   5.400 -        default: {
   5.401 -            Mix_SetError("Unknown hardware audio format");
   5.402 -            return -1;
   5.403 -        }
   5.404 +    if (spec->format == AUDIO_S8 || spec->format == AUDIO_U8) {
   5.405 +        /* MIKMOD audio format is AUDIO_U8 */
   5.406 +        *mikmod.md_mode = 0;
   5.407 +    } else {
   5.408 +        /* MIKMOD audio format is AUDIO_S16SYS */
   5.409 +        *mikmod.md_mode = DMODE_16BITS;
   5.410      }
   5.411 -    current_output_channels = spec->channels;
   5.412 -    current_output_format = spec->format;
   5.413      if (spec->channels > 1) {
   5.414 -        if (spec->channels > MAX_OUTPUT_CHANNELS) {
   5.415 -            Mix_SetError("Hardware uses more channels than supported");
   5.416 -            return -1;
   5.417 -        }
   5.418          *mikmod.md_mode |= DMODE_STEREO;
   5.419      }
   5.420      *mikmod.md_mixfreq = spec->freq;
   5.421 @@ -414,22 +204,23 @@
   5.422      *mikmod.md_mode    |= DMODE_HQMIXER|DMODE_SOFT_MUSIC|DMODE_SURROUND;
   5.423  
   5.424      list = mikmod.MikMod_InfoDriver();
   5.425 -    if (list)
   5.426 +    if (list) {
   5.427        mikmod.MikMod_free(list);
   5.428 -    else
   5.429 +    } else {
   5.430        mikmod.MikMod_RegisterDriver(mikmod.drv_nos);
   5.431 +    }
   5.432  
   5.433      list = mikmod.MikMod_InfoLoader();
   5.434 -    if (list)
   5.435 +    if (list) {
   5.436        mikmod.MikMod_free(list);
   5.437 -    else
   5.438 +    } else {
   5.439        mikmod.MikMod_RegisterAllLoaders();
   5.440 +    }
   5.441  
   5.442      if (mikmod.MikMod_Init(NULL)) {
   5.443          Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno));
   5.444          return -1;
   5.445      }
   5.446 -
   5.447      return 0;
   5.448  }
   5.449  
   5.450 @@ -510,43 +301,81 @@
   5.451  /* Load a MOD stream from an SDL_RWops object */
   5.452  void *MIKMOD_CreateFromRW(SDL_RWops *src, int freesrc)
   5.453  {
   5.454 -    MODULE *module;
   5.455 +    MIKMOD_Music *music;
   5.456 +    SDL_AudioFormat format;
   5.457 +    Uint8 channels;
   5.458  
   5.459 -    module = MikMod_LoadSongRW(src, 64);
   5.460 -    if (!module) {
   5.461 +    music = (MIKMOD_Music *)SDL_calloc(1, sizeof(*music));
   5.462 +    if (!music) {
   5.463 +        SDL_OutOfMemory();
   5.464 +        return NULL;
   5.465 +    }
   5.466 +    music->volume = MIX_MAX_VOLUME;
   5.467 +
   5.468 +    music->module = MikMod_LoadSongRW(src, 64);
   5.469 +    if (!music->module) {
   5.470          Mix_SetError("%s", mikmod.MikMod_strerror(*mikmod.MikMod_errno));
   5.471 +        MIKMOD_Delete(music);
   5.472          return NULL;
   5.473      }
   5.474  
   5.475      /* Stop implicit looping, fade out and other flags. */
   5.476 -    module->extspd  = 1;
   5.477 -    module->panflag = 1;
   5.478 -    module->wrap    = 0;
   5.479 -    module->loop    = 0;
   5.480 +    music->module->extspd  = 1;
   5.481 +    music->module->panflag = 1;
   5.482 +    music->module->wrap    = 0;
   5.483 +    music->module->loop    = 0;
   5.484  #if 0 /* Don't set fade out by default - unfortunately there's no real way
   5.485  to query the status of the song or set trigger actions.  Hum. */
   5.486 -    module->fadeout = 1;
   5.487 +    music->module->fadeout = 1;
   5.488  #endif
   5.489  
   5.490 +    if ((*mikmod.md_mode & DMODE_16BITS) == DMODE_16BITS) {
   5.491 +        format = AUDIO_S16SYS;
   5.492 +    } else {
   5.493 +        format = AUDIO_U8;
   5.494 +    }
   5.495 +    if ((*mikmod.md_mode & DMODE_STEREO) == DMODE_STEREO) {
   5.496 +        channels = 2;
   5.497 +    } else {
   5.498 +        channels = 1;
   5.499 +    }
   5.500 +    music->stream = SDL_NewAudioStream(format, channels, *mikmod.md_mixfreq,
   5.501 +                                       music_spec.format, music_spec.channels, music_spec.freq);
   5.502 +    if (!music->stream) {
   5.503 +        MIKMOD_Delete(music);
   5.504 +        return NULL;
   5.505 +    }
   5.506 +
   5.507 +    music->buffer_size = music_spec.samples * (SDL_AUDIO_BITSIZE(format) / 8) * channels;
   5.508 +    music->buffer = (SBYTE *)SDL_malloc(music->buffer_size);
   5.509 +    if (!music->buffer) {
   5.510 +        SDL_OutOfMemory();
   5.511 +        MIKMOD_Delete(music);
   5.512 +        return NULL;
   5.513 +    }
   5.514 +        
   5.515      if (freesrc) {
   5.516          SDL_RWclose(src);
   5.517      }
   5.518 -    return module;
   5.519 +    return music;
   5.520  }
   5.521  
   5.522  /* Set the volume for a MOD stream */
   5.523  static void MIKMOD_SetVolume(void *context, int volume)
   5.524  {
   5.525 +    MIKMOD_Music *music = (MIKMOD_Music *)context;
   5.526 +    music->volume = volume;
   5.527      mikmod.Player_SetVolume((SWORD)volume);
   5.528  }
   5.529  
   5.530  /* Start playback of a given MOD stream */
   5.531 -static int MIKMOD_Play(void *context)
   5.532 +static int MIKMOD_Play(void *context, int play_count)
   5.533  {
   5.534 -    MODULE *music = (MODULE *)context;
   5.535 -    mikmod.Player_Start(music);
   5.536 -    mikmod.Player_SetVolume((SWORD)music_volume);
   5.537 -    return 0;
   5.538 +    MIKMOD_Music *music = (MIKMOD_Music *)context;
   5.539 +    music->play_count = play_count;
   5.540 +    mikmod.Player_Start(music->module);
   5.541 +    mikmod.Player_SetVolume((SWORD)music->volume);
   5.542 +    return MIKMOD_Seek(music, 0.0);
   5.543  }
   5.544  
   5.545  /* Return non-zero if a stream is currently playing */
   5.546 @@ -556,84 +385,50 @@
   5.547  }
   5.548  
   5.549  /* Play some of a stream previously started with MOD_play() */
   5.550 -static int MIKMOD_GetAudio(void *context, void *data, int bytes)
   5.551 +static int MIKMOD_GetSome(void *context, void *data, int bytes, SDL_bool *done)
   5.552  {
   5.553 -    MODULE *music = (MODULE *)context;
   5.554 -    Uint8 *stream = (Uint8 *)data;
   5.555 -    int len = bytes;
   5.556 +    MIKMOD_Music *music = (MIKMOD_Music *)context;
   5.557 +    int filled;
   5.558  
   5.559 -    if (current_output_channels > 2) {
   5.560 -        int small_len = 2 * len / current_output_channels;
   5.561 -        int i;
   5.562 -        Uint8 *src, *dst;
   5.563 +    filled = SDL_AudioStreamGet(music->stream, data, bytes);
   5.564 +    if (filled != 0) {
   5.565 +        return filled;
   5.566 +    }
   5.567  
   5.568 -        mikmod.VC_WriteBytes((SBYTE *)stream, small_len);
   5.569 -        /* and extend to len by copying channels */
   5.570 -        src = stream + small_len;
   5.571 -        dst = stream + len;
   5.572 +    if (!music->play_count) {
   5.573 +        /* All done */
   5.574 +        *done = SDL_TRUE;
   5.575 +        return 0;
   5.576 +    }
   5.577  
   5.578 -        switch (current_output_format & 0xFF) {
   5.579 -            case 8:
   5.580 -                for (i=small_len/2; i; --i) {
   5.581 -                    src -= 2;
   5.582 -                    dst -= current_output_channels;
   5.583 -                    dst[0] = src[0];
   5.584 -                    dst[1] = src[1];
   5.585 -                    dst[2] = src[0];
   5.586 -                    dst[3] = src[1];
   5.587 -                    if (current_output_channels == 6) {
   5.588 -                        dst[4] = src[0];
   5.589 -                        dst[5] = src[1];
   5.590 -                    }
   5.591 -                }
   5.592 -                break;
   5.593 -            case 16:
   5.594 -                for (i=small_len/4; i; --i) {
   5.595 -                    src -= 4;
   5.596 -                    dst -= 2 * current_output_channels;
   5.597 -                    dst[0] = src[0];
   5.598 -                    dst[1] = src[1];
   5.599 -                    dst[2] = src[2];
   5.600 -                    dst[3] = src[3];
   5.601 -                    dst[4] = src[0];
   5.602 -                    dst[5] = src[1];
   5.603 -                    dst[6] = src[2];
   5.604 -                    dst[7] = src[3];
   5.605 -                    if (current_output_channels == 6) {
   5.606 -                        dst[8] = src[0];
   5.607 -                        dst[9] = src[1];
   5.608 -                        dst[10] = src[2];
   5.609 -                        dst[11] = src[3];
   5.610 -                    }
   5.611 -                }
   5.612 -                break;
   5.613 -        }
   5.614 -    } else {
   5.615 -        mikmod.VC_WriteBytes((SBYTE *)stream, len);
   5.616 +    /* This never fails, and always writes a full buffer */
   5.617 +    mikmod.VC_WriteBytes(music->buffer, music->buffer_size);
   5.618 +
   5.619 +    if (SDL_AudioStreamPut(music->stream, music->buffer, music->buffer_size) < 0) {
   5.620 +        return -1;
   5.621      }
   5.622 -    if (music_swap8) {
   5.623 -        Uint8 *dst;
   5.624 -        int i;
   5.625  
   5.626 -        dst = stream;
   5.627 -        for (i=len; i; --i) {
   5.628 -            *dst++ ^= 0x80;
   5.629 -        }
   5.630 -    } else
   5.631 -    if (music_swap16) {
   5.632 -        Uint8 *dst, tmp;
   5.633 -        int i;
   5.634 -
   5.635 -        dst = stream;
   5.636 -        for (i=(len/2); i; --i) {
   5.637 -            tmp = dst[0];
   5.638 -            dst[0] = dst[1];
   5.639 -            dst[1] = tmp;
   5.640 -            dst += 2;
   5.641 +    /* Check to see if we're done now */
   5.642 +    if (!mikmod.Player_Active()) {
   5.643 +        if (music->play_count == 1) {
   5.644 +            music->play_count = 0;
   5.645 +            SDL_AudioStreamFlush(music->stream);
   5.646 +        } else {
   5.647 +            int play_count = -1;
   5.648 +            if (music->play_count > 0) {
   5.649 +                play_count = (music->play_count - 1);
   5.650 +            }
   5.651 +            if (MIKMOD_Play(music, play_count) < 0) {
   5.652 +                return -1;
   5.653 +            }
   5.654          }
   5.655      }
   5.656      return 0;
   5.657  }
   5.658 +static int MIKMOD_GetAudio(void *context, void *data, int bytes)
   5.659 +{
   5.660 +    return music_pcm_getaudio(context, data, bytes, MIX_MAX_VOLUME, MIKMOD_GetSome);
   5.661 +}
   5.662  
   5.663  /* Jump (seek) to a given position (time is in seconds) */
   5.664  static int MIKMOD_Seek(void *context, double position)
   5.665 @@ -651,8 +446,18 @@
   5.666  /* Close the given MOD stream */
   5.667  static void MIKMOD_Delete(void *context)
   5.668  {
   5.669 -    MODULE *music = (MODULE *)context;
   5.670 -    mikmod.Player_Free(music);
   5.671 +    MIKMOD_Music *music = (MIKMOD_Music *)context;
   5.672 +
   5.673 +    if (music->module) {
   5.674 +        mikmod.Player_Free(music->module);
   5.675 +    }
   5.676 +    if (music->stream) {
   5.677 +        SDL_FreeAudioStream(music->stream);
   5.678 +    }
   5.679 +    if (music->buffer) {
   5.680 +        SDL_free(music->buffer);
   5.681 +    }
   5.682 +    SDL_free(music);
   5.683  }
   5.684  
   5.685  Mix_MusicInterface Mix_MusicInterface_MIKMOD =
   5.686 @@ -674,7 +479,7 @@
   5.687      MIKMOD_Seek,
   5.688      NULL,   /* Pause */
   5.689      NULL,   /* Resume */
   5.690 -    NULL,   /* Stop */
   5.691 +    MIKMOD_Stop,
   5.692      MIKMOD_Delete,
   5.693      MIKMOD_Close,
   5.694      MIKMOD_Unload,
     6.1 --- a/music_modplug.c	Fri Oct 20 23:39:04 2017 -0700
     6.2 +++ b/music_modplug.c	Sat Oct 21 00:53:21 2017 -0700
     6.3 @@ -52,42 +52,38 @@
     6.4  static ModPlug_Settings settings;
     6.5  
     6.6  #ifdef MODPLUG_DYNAMIC
     6.7 +#define FUNCTION_LOADER(FUNC, SIG) \
     6.8 +    modplug.FUNC = (SIG) SDL_LoadFunction(modplug.handle, #FUNC); \
     6.9 +    if (modplug.FUNC == NULL) { SDL_UnloadObject(modplug.handle); return -1; }
    6.10 +#else
    6.11 +#define FUNCTION_LOADER(FUNC, SIG) \
    6.12 +    modplug.FUNC = FUNC;
    6.13 +#endif
    6.14  
    6.15  static int MODPLUG_Load(void)
    6.16  {
    6.17      if (modplug.loaded == 0) {
    6.18 +#ifdef MODPLUG_DYNAMIC
    6.19          modplug.handle = SDL_LoadObject(MODPLUG_DYNAMIC);
    6.20          if (modplug.handle == NULL) {
    6.21              return -1;
    6.22          }
    6.23 -
    6.24 -        modplug.ModPlug_Load =
    6.25 -            (ModPlugFile* (*)(const void* data, int size))
    6.26 -            SDL_LoadFunction(modplug.handle, "ModPlug_Load");
    6.27 -
    6.28 -        modplug.ModPlug_Unload =
    6.29 -            (void (*)(ModPlugFile* file))
    6.30 -            SDL_LoadFunction(modplug.handle, "ModPlug_Unload");
    6.31 -
    6.32 -        modplug.ModPlug_Read =
    6.33 -            (int  (*)(ModPlugFile* file, void* buffer, int size))
    6.34 -            SDL_LoadFunction(modplug.handle, "ModPlug_Read");
    6.35 -
    6.36 -        modplug.ModPlug_Seek =
    6.37 -            (void (*)(ModPlugFile* file, int millisecond))
    6.38 -            SDL_LoadFunction(modplug.handle, "ModPlug_Seek");
    6.39 -
    6.40 -        modplug.ModPlug_GetSettings =
    6.41 -            (void (*)(ModPlug_Settings* settings))
    6.42 -            SDL_LoadFunction(modplug.handle, "ModPlug_GetSettings");
    6.43 -
    6.44 -        modplug.ModPlug_SetSettings =
    6.45 -            (void (*)(const ModPlug_Settings* settings))
    6.46 -            SDL_LoadFunction(modplug.handle, "ModPlug_SetSettings");
    6.47 -
    6.48 -        modplug.ModPlug_SetMasterVolume =
    6.49 -            (void (*)(ModPlugFile* file,unsigned int cvol))
    6.50 -            SDL_LoadFunction(modplug.handle, "ModPlug_SetMasterVolume");
    6.51 +#elif defined(__MACOSX__)
    6.52 +        extern ModPlugFile* ModPlug_Load(const void* data, int size) __attribute__((weak_import));
    6.53 +        if (ModPlug_Load == NULL)
    6.54 +        {
    6.55 +            /* Missing weakly linked framework */
    6.56 +            Mix_SetError("Missing modplug.framework");
    6.57 +            return -1;
    6.58 +        }
    6.59 +#endif
    6.60 +        FUNCTION_LOADER(ModPlug_Load, ModPlugFile* (*)(const void* data, int size))
    6.61 +        FUNCTION_LOADER(ModPlug_Unload, void (*)(ModPlugFile* file))
    6.62 +        FUNCTION_LOADER(ModPlug_Read, int  (*)(ModPlugFile* file, void* buffer, int size))
    6.63 +        FUNCTION_LOADER(ModPlug_Seek, void (*)(ModPlugFile* file, int millisecond))
    6.64 +        FUNCTION_LOADER(ModPlug_GetSettings, void (*)(ModPlug_Settings* settings))
    6.65 +        FUNCTION_LOADER(ModPlug_SetSettings, void (*)(const ModPlug_Settings* settings))
    6.66 +        FUNCTION_LOADER(ModPlug_SetMasterVolume, void (*)(ModPlugFile* file,unsigned int cvol))
    6.67      }
    6.68      ++modplug.loaded;
    6.69  
    6.70 @@ -100,50 +96,13 @@
    6.71          return;
    6.72      }
    6.73      if (modplug.loaded == 1) {
    6.74 +#ifdef MODPLUG_DYNAMIC
    6.75          SDL_UnloadObject(modplug.handle);
    6.76 +#endif
    6.77      }
    6.78      --modplug.loaded;
    6.79  }
    6.80  
    6.81 -#else /* !MODPLUG_DYNAMIC */
    6.82 -
    6.83 -int MODPLUG_Load(void)
    6.84 -{
    6.85 -    if (modplug.loaded == 0) {
    6.86 -#ifdef __MACOSX__
    6.87 -        extern ModPlugFile* ModPlug_Load(const void* data, int size) __attribute__((weak_import));
    6.88 -        if (ModPlug_Load == NULL)
    6.89 -        {
    6.90 -            /* Missing weakly linked framework */
    6.91 -            Mix_SetError("Missing modplug.framework");
    6.92 -            return -1;
    6.93 -        }
    6.94 -#endif // __MACOSX__
    6.95 -
    6.96 -        modplug.ModPlug_Load = ModPlug_Load;
    6.97 -        modplug.ModPlug_Unload = ModPlug_Unload;
    6.98 -        modplug.ModPlug_Read = ModPlug_Read;
    6.99 -        modplug.ModPlug_Seek = ModPlug_Seek;
   6.100 -        modplug.ModPlug_GetSettings = ModPlug_GetSettings;
   6.101 -        modplug.ModPlug_SetSettings = ModPlug_SetSettings;
   6.102 -        modplug.ModPlug_SetMasterVolume = ModPlug_SetMasterVolume;
   6.103 -    }
   6.104 -    ++modplug.loaded;
   6.105 -
   6.106 -    return 0;
   6.107 -}
   6.108 -
   6.109 -static void MODPLUG_Unload(void)
   6.110 -{
   6.111 -    if (modplug.loaded == 0) {
   6.112 -        return;
   6.113 -    }
   6.114 -    if (modplug.loaded == 1) {
   6.115 -    }
   6.116 -    --modplug.loaded;
   6.117 -}
   6.118 -
   6.119 -#endif /* MODPLUG_DYNAMIC */
   6.120  
   6.121  typedef struct
   6.122  {
     7.1 --- a/music_mpg123.c	Fri Oct 20 23:39:04 2017 -0700
     7.2 +++ b/music_mpg123.c	Sat Oct 21 00:53:21 2017 -0700
     7.3 @@ -84,7 +84,6 @@
     7.4              return -1;
     7.5          }
     7.6  #endif
     7.7 -
     7.8          FUNCTION_LOADER(mpg123_close, int (*)(mpg123_handle *mh))
     7.9          FUNCTION_LOADER(mpg123_delete, void (*)(mpg123_handle *mh))
    7.10          FUNCTION_LOADER(mpg123_exit, void (*)(void))
     8.1 --- a/music_ogg.c	Fri Oct 20 23:39:04 2017 -0700
     8.2 +++ b/music_ogg.c	Sat Oct 21 00:53:21 2017 -0700
     8.3 @@ -62,85 +62,52 @@
     8.4  };
     8.5  
     8.6  #ifdef OGG_DYNAMIC
     8.7 +#define FUNCTION_LOADER(FUNC, SIG) \
     8.8 +    vorbis.FUNC = (SIG) SDL_LoadFunction(vorbis.handle, #FUNC); \
     8.9 +    if (vorbis.FUNC == NULL) { SDL_UnloadObject(vorbis.handle); return -1; }
    8.10 +#else
    8.11 +#define FUNCTION_LOADER(FUNC, SIG) \
    8.12 +    vorbis.FUNC = FUNC;
    8.13 +#endif
    8.14  
    8.15  static int OGG_Load(void)
    8.16  {
    8.17      if (vorbis.loaded == 0) {
    8.18 +#ifdef OGG_DYNAMIC
    8.19          vorbis.handle = SDL_LoadObject(OGG_DYNAMIC);
    8.20          if (vorbis.handle == NULL) {
    8.21              return -1;
    8.22          }
    8.23 -        vorbis.ov_clear =
    8.24 -            (int (*)(OggVorbis_File *))
    8.25 -            SDL_LoadFunction(vorbis.handle, "ov_clear");
    8.26 -        if (vorbis.ov_clear == NULL) {
    8.27 -            SDL_UnloadObject(vorbis.handle);
    8.28 +#elif defined(__MACOSX__)
    8.29 +        extern int ov_open_callbacks(void*, OggVorbis_File*, const char*, long, ov_callbacks) __attribute__((weak_import));
    8.30 +        if (ov_open_callbacks == NULL)
    8.31 +        {
    8.32 +            /* Missing weakly linked framework */
    8.33 +            Mix_SetError("Missing Vorbis.framework");
    8.34              return -1;
    8.35          }
    8.36 -        vorbis.ov_info =
    8.37 -            (vorbis_info *(*)(OggVorbis_File *,int))
    8.38 -            SDL_LoadFunction(vorbis.handle, "ov_info");
    8.39 -        if (vorbis.ov_info == NULL) {
    8.40 -            SDL_UnloadObject(vorbis.handle);
    8.41 -            return -1;
    8.42 -        }
    8.43 -        vorbis.ov_comment =
    8.44 -            (vorbis_comment *(*)(OggVorbis_File *,int))
    8.45 -            SDL_LoadFunction(vorbis.handle, "ov_comment");
    8.46 -        if (vorbis.ov_comment == NULL) {
    8.47 -            SDL_UnloadObject(vorbis.handle);
    8.48 -            return -1;
    8.49 -        }
    8.50 -        vorbis.ov_open_callbacks =
    8.51 -            (int (*)(void *, OggVorbis_File *, const char *, long, ov_callbacks))
    8.52 -            SDL_LoadFunction(vorbis.handle, "ov_open_callbacks");
    8.53 -        if (vorbis.ov_open_callbacks == NULL) {
    8.54 -            SDL_UnloadObject(vorbis.handle);
    8.55 -            return -1;
    8.56 -        }
    8.57 -        vorbis.ov_pcm_total =
    8.58 -            (ogg_int64_t (*)(OggVorbis_File *,int))
    8.59 -            SDL_LoadFunction(vorbis.handle, "ov_pcm_total");
    8.60 -        if (vorbis.ov_pcm_total == NULL) {
    8.61 -            SDL_UnloadObject(vorbis.handle);
    8.62 -            return -1;
    8.63 -        }
    8.64 -        vorbis.ov_read =
    8.65 +#endif
    8.66 +        FUNCTION_LOADER(ov_clear, int (*)(OggVorbis_File *))
    8.67 +        FUNCTION_LOADER(ov_info, vorbis_info *(*)(OggVorbis_File *,int))
    8.68 +        FUNCTION_LOADER(ov_comment, vorbis_comment *(*)(OggVorbis_File *,int))
    8.69 +        FUNCTION_LOADER(ov_open_callbacks, int (*)(void *, OggVorbis_File *, const char *, long, ov_callbacks))
    8.70 +        FUNCTION_LOADER(ov_pcm_total, ogg_int64_t (*)(OggVorbis_File *,int))
    8.71 +        FUNCTION_LOADER(ov_read,
    8.72  #ifdef OGG_USE_TREMOR
    8.73 -            (long (*)(OggVorbis_File *,char *,int,int *))
    8.74 +            long (*)(OggVorbis_File *,char *,int,int *)
    8.75  #else
    8.76 -            (long (*)(OggVorbis_File *,char *,int,int,int,int,int *))
    8.77 +            long (*)(OggVorbis_File *,char *,int,int,int,int,int *)
    8.78  #endif
    8.79 -            SDL_LoadFunction(vorbis.handle, "ov_read");
    8.80 -        if (vorbis.ov_read == NULL) {
    8.81 -            SDL_UnloadObject(vorbis.handle);
    8.82 -            return -1;
    8.83 -        }
    8.84 -        vorbis.ov_time_seek =
    8.85 +        )
    8.86 +        FUNCTION_LOADER(ov_time_seek,
    8.87  #ifdef OGG_USE_TREMOR
    8.88 -            (long (*)(OggVorbis_File *,ogg_int64_t))
    8.89 +            long (*)(OggVorbis_File *,ogg_int64_t)
    8.90  #else
    8.91 -            (int (*)(OggVorbis_File *,double))
    8.92 +            int (*)(OggVorbis_File *,double)
    8.93  #endif
    8.94 -            SDL_LoadFunction(vorbis.handle, "ov_time_seek");
    8.95 -        if (vorbis.ov_time_seek == NULL) {
    8.96 -            SDL_UnloadObject(vorbis.handle);
    8.97 -            return -1;
    8.98 -        }
    8.99 -        vorbis.ov_pcm_seek =
   8.100 -            (int (*)(OggVorbis_File *,ogg_int64_t))
   8.101 -            SDL_LoadFunction(vorbis.handle, "ov_pcm_seek");
   8.102 -        if (vorbis.ov_pcm_seek == NULL) {
   8.103 -            SDL_UnloadObject(vorbis.handle);
   8.104 -            return -1;
   8.105 -        }
   8.106 -        vorbis.ov_pcm_tell =
   8.107 -            (ogg_int64_t (*)(OggVorbis_File *))
   8.108 -            SDL_LoadFunction(vorbis.handle, "ov_pcm_tell");
   8.109 -        if (vorbis.ov_pcm_tell == NULL) {
   8.110 -            SDL_UnloadObject(vorbis.handle);
   8.111 -            return -1;
   8.112 -        }
   8.113 +        )
   8.114 +        FUNCTION_LOADER(ov_pcm_seek, int (*)(OggVorbis_File *,ogg_int64_t))
   8.115 +        FUNCTION_LOADER(ov_pcm_tell, ogg_int64_t (*)(OggVorbis_File *))
   8.116      }
   8.117      ++vorbis.loaded;
   8.118  
   8.119 @@ -153,53 +120,13 @@
   8.120          return;
   8.121      }
   8.122      if (vorbis.loaded == 1) {
   8.123 +#ifdef OGG_DYNAMIC
   8.124          SDL_UnloadObject(vorbis.handle);
   8.125 +#endif
   8.126      }
   8.127      --vorbis.loaded;
   8.128  }
   8.129  
   8.130 -#else /* !OGG_DYNAMIC */
   8.131 -
   8.132 -static int OGG_Load(void)
   8.133 -{
   8.134 -    if (vorbis.loaded == 0) {
   8.135 -#ifdef __MACOSX__
   8.136 -        extern int ov_open_callbacks(void*, OggVorbis_File*, const char*, long, ov_callbacks) __attribute__((weak_import));
   8.137 -        if (ov_open_callbacks == NULL)
   8.138 -        {
   8.139 -            /* Missing weakly linked framework */
   8.140 -            Mix_SetError("Missing Vorbis.framework");
   8.141 -            return -1;
   8.142 -        }
   8.143 -#endif // __MACOSX__
   8.144 -
   8.145 -        vorbis.ov_clear = ov_clear;
   8.146 -        vorbis.ov_info = ov_info;
   8.147 -        vorbis.ov_comment = ov_comment;
   8.148 -        vorbis.ov_open_callbacks = ov_open_callbacks;
   8.149 -        vorbis.ov_pcm_total = ov_pcm_total;
   8.150 -        vorbis.ov_read = ov_read;
   8.151 -        vorbis.ov_time_seek = ov_time_seek;
   8.152 -        vorbis.ov_pcm_seek = ov_pcm_seek;
   8.153 -        vorbis.ov_pcm_tell = ov_pcm_tell;
   8.154 -    }
   8.155 -    ++vorbis.loaded;
   8.156 -
   8.157 -    return 0;
   8.158 -}
   8.159 -
   8.160 -static void OGG_Unload(void)
   8.161 -{
   8.162 -    if (vorbis.loaded == 0) {
   8.163 -        return;
   8.164 -    }
   8.165 -    if (vorbis.loaded == 1) {
   8.166 -    }
   8.167 -    --vorbis.loaded;
   8.168 -}
   8.169 -
   8.170 -#endif /* OGG_DYNAMIC */
   8.171 -
   8.172  
   8.173  typedef struct {
   8.174      SDL_RWops *src;
     9.1 --- a/music_smpeg.c	Fri Oct 20 23:39:04 2017 -0700
     9.2 +++ b/music_smpeg.c	Sat Oct 21 00:53:21 2017 -0700
     9.3 @@ -55,98 +55,43 @@
     9.4  };
     9.5  
     9.6  #ifdef SMPEG_DYNAMIC
     9.7 +#define FUNCTION_LOADER(FUNC, SIG) \
     9.8 +    smpeg.FUNC = (SIG) SDL_LoadFunction(smpeg.handle, #FUNC); \
     9.9 +    if (smpeg.FUNC == NULL) { SDL_UnloadObject(smpeg.handle); return -1; }
    9.10 +#else
    9.11 +#define FUNCTION_LOADER(FUNC, SIG) \
    9.12 +    smpeg.FUNC = FUNC;
    9.13 +#endif
    9.14  
    9.15  static int SMPEG_Load(void)
    9.16  {
    9.17      if (smpeg.loaded == 0) {
    9.18 +#ifdef SMPEG_DYNAMIC
    9.19          smpeg.handle = SDL_LoadObject(SMPEG_DYNAMIC);
    9.20          if (smpeg.handle == NULL) {
    9.21              return -1;
    9.22          }
    9.23 -        smpeg.SMPEG_actualSpec =
    9.24 -            (void (*)(SMPEG *, SDL_AudioSpec *))
    9.25 -            SDL_LoadFunction(smpeg.handle, "SMPEG_actualSpec");
    9.26 -        if (smpeg.SMPEG_actualSpec == NULL) {
    9.27 -            SDL_UnloadObject(smpeg.handle);
    9.28 +#elif defined(__MACOSX__)
    9.29 +        extern SMPEG* SMPEG_new_rwops(SDL_RWops*, SMPEG_Info*, int, int) __attribute__((weak_import));
    9.30 +        if (SMPEG_new_rwops == NULL)
    9.31 +        {
    9.32 +            /* Missing weakly linked framework */
    9.33 +            Mix_SetError("Missing smpeg2.framework");
    9.34              return -1;
    9.35          }
    9.36 -        smpeg.SMPEG_delete =
    9.37 -            (void (*)(SMPEG*))
    9.38 -            SDL_LoadFunction(smpeg.handle, "SMPEG_delete");
    9.39 -        if (smpeg.SMPEG_delete == NULL) {
    9.40 -            SDL_UnloadObject(smpeg.handle);
    9.41 -            return -1;
    9.42 -        }
    9.43 -        smpeg.SMPEG_enableaudio =
    9.44 -            (void (*)(SMPEG*, int))
    9.45 -            SDL_LoadFunction(smpeg.handle, "SMPEG_enableaudio");
    9.46 -        if (smpeg.SMPEG_enableaudio == NULL) {
    9.47 -            SDL_UnloadObject(smpeg.handle);
    9.48 -            return -1;
    9.49 -        }
    9.50 -        smpeg.SMPEG_enablevideo =
    9.51 -            (void (*)(SMPEG*, int))
    9.52 -            SDL_LoadFunction(smpeg.handle, "SMPEG_enablevideo");
    9.53 -        if (smpeg.SMPEG_enablevideo == NULL) {
    9.54 -            SDL_UnloadObject(smpeg.handle);
    9.55 -            return -1;
    9.56 -        }
    9.57 -        smpeg.SMPEG_new_rwops =
    9.58 -            (SMPEG* (*)(SDL_RWops *, SMPEG_Info*, int, int))
    9.59 -            SDL_LoadFunction(smpeg.handle, "SMPEG_new_rwops");
    9.60 -        if (smpeg.SMPEG_new_rwops == NULL) {
    9.61 -            SDL_UnloadObject(smpeg.handle);
    9.62 -            return -1;
    9.63 -        }
    9.64 -        smpeg.SMPEG_play =
    9.65 -            (void (*)(SMPEG*))
    9.66 -            SDL_LoadFunction(smpeg.handle, "SMPEG_play");
    9.67 -        if (smpeg.SMPEG_play == NULL) {
    9.68 -            SDL_UnloadObject(smpeg.handle);
    9.69 -            return -1;
    9.70 -        }
    9.71 -        smpeg.SMPEG_playAudio =
    9.72 -            (int (*)(SMPEG *, Uint8 *, int))
    9.73 -            SDL_LoadFunction(smpeg.handle, "SMPEG_playAudio");
    9.74 -        if (smpeg.SMPEG_playAudio == NULL) {
    9.75 -            SDL_UnloadObject(smpeg.handle);
    9.76 -            return -1;
    9.77 -        }
    9.78 -        smpeg.SMPEG_rewind =
    9.79 -            (void (*)(SMPEG*))
    9.80 -            SDL_LoadFunction(smpeg.handle, "SMPEG_rewind");
    9.81 -        if (smpeg.SMPEG_rewind == NULL) {
    9.82 -            SDL_UnloadObject(smpeg.handle);
    9.83 -            return -1;
    9.84 -        }
    9.85 -        smpeg.SMPEG_setvolume =
    9.86 -            (void (*)(SMPEG*, int))
    9.87 -            SDL_LoadFunction(smpeg.handle, "SMPEG_setvolume");
    9.88 -        if (smpeg.SMPEG_setvolume == NULL) {
    9.89 -            SDL_UnloadObject(smpeg.handle);
    9.90 -            return -1;
    9.91 -        }
    9.92 -        smpeg.SMPEG_skip =
    9.93 -            (void (*)(SMPEG*, float))
    9.94 -            SDL_LoadFunction(smpeg.handle, "SMPEG_skip");
    9.95 -        if (smpeg.SMPEG_skip == NULL) {
    9.96 -            SDL_UnloadObject(smpeg.handle);
    9.97 -            return -1;
    9.98 -        }
    9.99 -        smpeg.SMPEG_status =
   9.100 -            (SMPEGstatus (*)(SMPEG*))
   9.101 -            SDL_LoadFunction(smpeg.handle, "SMPEG_status");
   9.102 -        if (smpeg.SMPEG_status == NULL) {
   9.103 -            SDL_UnloadObject(smpeg.handle);
   9.104 -            return -1;
   9.105 -        }
   9.106 -        smpeg.SMPEG_stop =
   9.107 -            (void (*)(SMPEG*))
   9.108 -            SDL_LoadFunction(smpeg.handle, "SMPEG_stop");
   9.109 -        if (smpeg.SMPEG_stop == NULL) {
   9.110 -            SDL_UnloadObject(smpeg.handle);
   9.111 -            return -1;
   9.112 -        }
   9.113 +#endif
   9.114 +        FUNCTION_LOADER(SMPEG_actualSpec, void (*)(SMPEG *, SDL_AudioSpec *))
   9.115 +        FUNCTION_LOADER(SMPEG_delete, void (*)(SMPEG*))
   9.116 +        FUNCTION_LOADER(SMPEG_enableaudio, void (*)(SMPEG*, int))
   9.117 +        FUNCTION_LOADER(SMPEG_enablevideo, void (*)(SMPEG*, int))
   9.118 +        FUNCTION_LOADER(SMPEG_new_rwops, SMPEG* (*)(SDL_RWops *, SMPEG_Info*, int, int))
   9.119 +        FUNCTION_LOADER(SMPEG_play, void (*)(SMPEG*))
   9.120 +        FUNCTION_LOADER(SMPEG_playAudio, int (*)(SMPEG *, Uint8 *, int))
   9.121 +        FUNCTION_LOADER(SMPEG_rewind, void (*)(SMPEG*))
   9.122 +        FUNCTION_LOADER(SMPEG_setvolume, void (*)(SMPEG*, int))
   9.123 +        FUNCTION_LOADER(SMPEG_skip, void (*)(SMPEG*, float))
   9.124 +        FUNCTION_LOADER(SMPEG_status, SMPEGstatus (*)(SMPEG*))
   9.125 +        FUNCTION_LOADER(SMPEG_stop, void (*)(SMPEG*))
   9.126      }
   9.127      ++smpeg.loaded;
   9.128  
   9.129 @@ -159,56 +104,13 @@
   9.130          return;
   9.131      }
   9.132      if (smpeg.loaded == 1) {
   9.133 +#ifdef SMPEG_DYNAMIC
   9.134          SDL_UnloadObject(smpeg.handle);
   9.135 +#endif
   9.136      }
   9.137      --smpeg.loaded;
   9.138  }
   9.139  
   9.140 -#else /* !SMPEG_DYNAMIC */
   9.141 -
   9.142 -static int SMPEG_Load(void)
   9.143 -{
   9.144 -    if (smpeg.loaded == 0) {
   9.145 -#ifdef __MACOSX__
   9.146 -        extern SMPEG* SMPEG_new_rwops(SDL_RWops*, SMPEG_Info*, int, int) __attribute__((weak_import));
   9.147 -        if (SMPEG_new_rwops == NULL)
   9.148 -        {
   9.149 -            /* Missing weakly linked framework */
   9.150 -            Mix_SetError("Missing smpeg2.framework");
   9.151 -            return -1;
   9.152 -        }
   9.153 -#endif // __MACOSX__
   9.154 -
   9.155 -        smpeg.SMPEG_actualSpec = SMPEG_actualSpec;
   9.156 -        smpeg.SMPEG_delete = SMPEG_delete;
   9.157 -        smpeg.SMPEG_enableaudio = SMPEG_enableaudio;
   9.158 -        smpeg.SMPEG_enablevideo = SMPEG_enablevideo;
   9.159 -        smpeg.SMPEG_new_rwops = SMPEG_new_rwops;
   9.160 -        smpeg.SMPEG_play = SMPEG_play;
   9.161 -        smpeg.SMPEG_playAudio = SMPEG_playAudio;
   9.162 -        smpeg.SMPEG_rewind = SMPEG_rewind;
   9.163 -        smpeg.SMPEG_setvolume = SMPEG_setvolume;
   9.164 -        smpeg.SMPEG_skip = SMPEG_skip;
   9.165 -        smpeg.SMPEG_status = SMPEG_status;
   9.166 -        smpeg.SMPEG_stop = SMPEG_stop;
   9.167 -    }
   9.168 -    ++smpeg.loaded;
   9.169 -
   9.170 -    return 0;
   9.171 -}
   9.172 -
   9.173 -static void SMPEG_Unload(void)
   9.174 -{
   9.175 -    if (smpeg.loaded == 0) {
   9.176 -        return;
   9.177 -    }
   9.178 -    if (smpeg.loaded == 1) {
   9.179 -    }
   9.180 -    --smpeg.loaded;
   9.181 -}
   9.182 -
   9.183 -#endif /* SMPEG_DYNAMIC */
   9.184 -
   9.185  
   9.186  typedef struct
   9.187  {