music.c
changeset 839 7fa15b556953
parent 830 c292b484a95e
child 840 90e3ffcfea04
     1.1 --- a/music.c	Mon Oct 23 12:40:10 2017 -0700
     1.2 +++ b/music.c	Tue Oct 24 21:41:50 2017 -0700
     1.3 @@ -42,6 +42,9 @@
     1.4  #include "music_flac.h"
     1.5  #include "native_midi/native_midi.h"
     1.6  
     1.7 +/* Set this hint to true if you want verbose logging of music interfaces */
     1.8 +#define SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES \
     1.9 +    "SDL_MIXER_DEBUG_MUSIC_INTERFACES"
    1.10  
    1.11  char *music_cmd = NULL;
    1.12  static SDL_bool music_active = SDL_TRUE;
    1.13 @@ -135,7 +138,17 @@
    1.14  
    1.15  static void add_music_decoder(const char *decoder)
    1.16  {
    1.17 -    void *ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
    1.18 +    void *ptr;
    1.19 +    int i;
    1.20 +
    1.21 +    /* Check to see if we already have this decoder */
    1.22 +    for (i = 0; i < num_decoders; ++i) {
    1.23 +        if (SDL_strcmp(music_decoders[i], decoder) == 0) {
    1.24 +            return;
    1.25 +        }
    1.26 +    }
    1.27 +
    1.28 +    ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
    1.29      if (ptr == NULL) {
    1.30          return;  /* oh well, go on without it. */
    1.31      }
    1.32 @@ -252,28 +265,123 @@
    1.33      }
    1.34  }
    1.35  
    1.36 -/* Load the music interface libraries */
    1.37 -int load_music(void)
    1.38 +/* Load the music interface libraries for a given music type */
    1.39 +SDL_bool load_music_type(Mix_MusicType type)
    1.40  {
    1.41 -    char hint[128];
    1.42 -
    1.43 -    int i;
    1.44 +    int i, loaded = 0;
    1.45      for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
    1.46          Mix_MusicInterface *interface = s_music_interfaces[i];
    1.47 -        if (interface->loaded) {
    1.48 +        if (interface->type != type) {
    1.49 +            continue;
    1.50 +        }
    1.51 +        if (!interface->loaded) {
    1.52 +            char hint[64];
    1.53 +            SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
    1.54 +            if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
    1.55 +                continue;
    1.56 +            }
    1.57 +
    1.58 +            if (interface->Load && interface->Load() < 0) {
    1.59 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
    1.60 +                    SDL_Log("Couldn't load %s: %s\n", interface->tag, Mix_GetError());
    1.61 +                }
    1.62 +                continue;
    1.63 +            }
    1.64 +            interface->loaded = SDL_TRUE;
    1.65 +        }
    1.66 +        ++loaded;
    1.67 +    }
    1.68 +    return (loaded > 0) ? SDL_TRUE : SDL_FALSE;
    1.69 +}
    1.70 +
    1.71 +/* Open the music interfaces for a given music type */
    1.72 +SDL_bool open_music_type(Mix_MusicType type)
    1.73 +{
    1.74 +    int i, opened = 0;
    1.75 +    SDL_bool use_native_midi = SDL_FALSE;
    1.76 +
    1.77 +    if (!music_spec.format) {
    1.78 +        /* Music isn't opened yet */
    1.79 +        return SDL_FALSE;
    1.80 +    }
    1.81 +
    1.82 +#ifdef MUSIC_MID_NATIVE
    1.83 +    if (type == MUS_MID && SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
    1.84 +        use_native_midi = SDL_TRUE;
    1.85 +    }
    1.86 +#endif
    1.87 +
    1.88 +    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
    1.89 +        Mix_MusicInterface *interface = s_music_interfaces[i];
    1.90 +        if (!interface->loaded) {
    1.91 +            continue;
    1.92 +        }
    1.93 +        if (type != MUS_NONE && interface->type != type) {
    1.94              continue;
    1.95          }
    1.96  
    1.97 -        SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
    1.98 -        if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
    1.99 +        if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
   1.100              continue;
   1.101          }
   1.102  
   1.103 -        if (!interface->Load || interface->Load() == 0) {
   1.104 -            interface->loaded = SDL_TRUE;
   1.105 +        if (!interface->opened) {
   1.106 +            if (interface->Open && interface->Open(&music_spec) < 0) {
   1.107 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
   1.108 +                    SDL_Log("Couldn't open %s: %s\n", interface->tag, Mix_GetError());
   1.109 +                }
   1.110 +                continue;
   1.111 +            }
   1.112 +            interface->opened = SDL_TRUE;
   1.113 +            add_music_decoder(interface->tag);
   1.114          }
   1.115 +        ++opened;
   1.116      }
   1.117 -    return 0;
   1.118 +
   1.119 +    if (has_music(MUS_MOD)) {
   1.120 +        add_music_decoder("MOD");
   1.121 +        add_chunk_decoder("MOD");
   1.122 +    }
   1.123 +    if (has_music(MUS_MID)) {
   1.124 +        add_music_decoder("MIDI");
   1.125 +        add_chunk_decoder("MID");
   1.126 +    }
   1.127 +    if (has_music(MUS_OGG)) {
   1.128 +        add_music_decoder("OGG");
   1.129 +        add_chunk_decoder("OGG");
   1.130 +    }
   1.131 +    if (has_music(MUS_MP3)) {
   1.132 +        add_music_decoder("MP3");
   1.133 +        add_chunk_decoder("MP3");
   1.134 +    }
   1.135 +    if (has_music(MUS_FLAC)) {
   1.136 +        add_music_decoder("FLAC");
   1.137 +        add_chunk_decoder("FLAC");
   1.138 +    }
   1.139 +
   1.140 +    return (opened > 0) ? SDL_TRUE : SDL_FALSE;
   1.141 +}
   1.142 +
   1.143 +/* Initialize the music interfaces with a certain desired audio format */
   1.144 +void open_music(const SDL_AudioSpec *spec)
   1.145 +{
   1.146 +#ifdef MIX_INIT_SOUNDFONT_PATHS
   1.147 +    if (!soundfont_paths) {
   1.148 +        soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
   1.149 +    }
   1.150 +#endif
   1.151 +
   1.152 +    /* Load the music interfaces that don't have explicit initialization */
   1.153 +    load_music_type(MUS_CMD);
   1.154 +    load_music_type(MUS_WAV);
   1.155 +
   1.156 +    /* Open all the interfaces that are loaded */
   1.157 +    music_spec = *spec;
   1.158 +    open_music_type(MUS_NONE);
   1.159 +
   1.160 +    Mix_VolumeMusic(MIX_MAX_VOLUME);
   1.161 +
   1.162 +    /* Calculate the number of ms for each callback */
   1.163 +    ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
   1.164  }
   1.165  
   1.166  /* Return SDL_TRUE if the music type is available */
   1.167 @@ -292,60 +400,6 @@
   1.168      return SDL_FALSE;
   1.169  }
   1.170  
   1.171 -/* Initialize the music interfaces with a certain desired audio format */
   1.172 -int open_music(const SDL_AudioSpec *spec)
   1.173 -{
   1.174 -    int i;
   1.175 -    SDL_bool use_native_midi = SDL_FALSE;
   1.176 -
   1.177 -#ifdef MIX_INIT_SOUNDFONT_PATHS
   1.178 -    if (!soundfont_paths) {
   1.179 -        soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
   1.180 -    }
   1.181 -#endif
   1.182 -
   1.183 -
   1.184 -#ifdef MUSIC_MID_NATIVE
   1.185 -    if (SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
   1.186 -        use_native_midi = SDL_TRUE;
   1.187 -    }
   1.188 -#endif
   1.189 -
   1.190 -    music_spec = *spec;
   1.191 -    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   1.192 -        Mix_MusicInterface *interface = s_music_interfaces[i];
   1.193 -        if (!interface->loaded) {
   1.194 -            continue;
   1.195 -        }
   1.196 -
   1.197 -        if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
   1.198 -            continue;
   1.199 -        }
   1.200 -
   1.201 -        if (!interface->Open || interface->Open(spec) == 0) {
   1.202 -            interface->opened = SDL_TRUE;
   1.203 -            add_music_decoder(interface->tag);
   1.204 -        }
   1.205 -    }
   1.206 -
   1.207 -    if (has_music(MUS_MOD)) {
   1.208 -        add_music_decoder("MOD");
   1.209 -    }
   1.210 -    if (has_music(MUS_MID)) {
   1.211 -        add_music_decoder("MIDI");
   1.212 -    }
   1.213 -    if (has_music(MUS_MP3)) {
   1.214 -        add_music_decoder("MP3");
   1.215 -    }
   1.216 -
   1.217 -    Mix_VolumeMusic(MIX_MAX_VOLUME);
   1.218 -
   1.219 -    /* Calculate the number of ms for each callback */
   1.220 -    ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
   1.221 -
   1.222 -    return 0;
   1.223 -}
   1.224 -
   1.225  Mix_MusicType detect_music_type_from_magic(const Uint8 *magic)
   1.226  {
   1.227      /* Ogg Vorbis files have the magic four bytes "OggS" */
   1.228 @@ -509,32 +563,34 @@
   1.229  
   1.230      Mix_ClearError();
   1.231  
   1.232 -    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   1.233 -        Mix_MusicInterface *interface = s_music_interfaces[i];
   1.234 -        if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
   1.235 -            continue;
   1.236 +    if (load_music_type(type) && open_music_type(type)) {
   1.237 +        for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   1.238 +            Mix_MusicInterface *interface = s_music_interfaces[i];
   1.239 +            if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
   1.240 +                continue;
   1.241 +            }
   1.242 +
   1.243 +            context = interface->CreateFromRW(src, freesrc);
   1.244 +            if (context) {
   1.245 +                /* Allocate memory for the music structure */
   1.246 +                Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
   1.247 +                if (music == NULL) {
   1.248 +                    interface->Delete(context);
   1.249 +                    Mix_SetError("Out of memory");
   1.250 +                    return NULL;
   1.251 +                }
   1.252 +                music->interface = interface;
   1.253 +                music->context = context;
   1.254 +
   1.255 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
   1.256 +                    SDL_Log("Loaded music with %s\n", interface->tag);
   1.257 +                }
   1.258 +                return music;
   1.259 +            }
   1.260 +
   1.261 +            /* Reset the stream for the next decoder */
   1.262 +            SDL_RWseek(src, start, RW_SEEK_SET);
   1.263          }
   1.264 -
   1.265 -        context = interface->CreateFromRW(src, freesrc);
   1.266 -        if (context) {
   1.267 -            /* Allocate memory for the music structure */
   1.268 -            Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
   1.269 -            if (music == NULL) {
   1.270 -                interface->Delete(context);
   1.271 -                Mix_SetError("Out of memory");
   1.272 -                return NULL;
   1.273 -            }
   1.274 -            music->interface = interface;
   1.275 -            music->context = context;
   1.276 -#ifdef DEBUG_MUSIC
   1.277 -            /* This would be useful to expose via an API */
   1.278 -            SDL_Log("Music playing with %s\n", interface->tag);
   1.279 -#endif
   1.280 -            return music;
   1.281 -        }
   1.282 -
   1.283 -        /* Reset the stream for the next decoder */
   1.284 -        SDL_RWseek(src, start, RW_SEEK_SET);
   1.285      }
   1.286  
   1.287      if (!*Mix_GetError()) {