Only load music interfaces that are explicitly initialized or needed for audio content
authorSam Lantinga <slouken@libsdl.org>
Tue, 24 Oct 2017 21:41:50 -0700
changeset 8397fa15b556953
parent 838 7d6df0a13bd0
child 840 90e3ffcfea04
Only load music interfaces that are explicitly initialized or needed for audio content
mixer.c
mixer.h
music.c
music.h
     1.1 --- a/mixer.c	Mon Oct 23 12:40:10 2017 -0700
     1.2 +++ b/mixer.c	Tue Oct 24 21:41:50 2017 -0700
     1.3 @@ -118,9 +118,19 @@
     1.4      return SDL_FALSE;
     1.5  }
     1.6  
     1.7 -static void add_chunk_decoder(const char *decoder)
     1.8 +void add_chunk_decoder(const char *decoder)
     1.9  {
    1.10 -    void *ptr = SDL_realloc((void *)chunk_decoders, (num_decoders + 1) * sizeof (const char *));
    1.11 +    int i;
    1.12 +    void *ptr;
    1.13 +
    1.14 +    /* Check to see if we already have this decoder */
    1.15 +    for (i = 0; i < num_decoders; ++i) {
    1.16 +        if (SDL_strcmp(chunk_decoders[i], decoder) == 0) {
    1.17 +            return;
    1.18 +        }
    1.19 +    }
    1.20 +
    1.21 +    ptr = SDL_realloc((void *)chunk_decoders, (num_decoders + 1) * sizeof (const char *));
    1.22      if (ptr == NULL) {
    1.23          return;  /* oh well, go on without it. */
    1.24      }
    1.25 @@ -140,44 +150,47 @@
    1.26  {
    1.27      int result = 0;
    1.28  
    1.29 -    load_music();
    1.30 -
    1.31      if (flags & MIX_INIT_FLAC) {
    1.32 -        if (has_music(MUS_FLAC)) {
    1.33 +        if (load_music_type(MUS_FLAC)) {
    1.34 +            open_music_type(MUS_FLAC);
    1.35              result |= MIX_INIT_FLAC;
    1.36          } else {
    1.37              Mix_SetError("FLAC support not available");
    1.38          }
    1.39      }
    1.40      if (flags & MIX_INIT_MOD) {
    1.41 -        if (has_music(MUS_MOD)) {
    1.42 +        if (load_music_type(MUS_MOD)) {
    1.43 +            open_music_type(MUS_MOD);
    1.44              result |= MIX_INIT_MOD;
    1.45          } else {
    1.46              Mix_SetError("MOD support not available");
    1.47          }
    1.48      }
    1.49      if (flags & MIX_INIT_MP3) {
    1.50 -        if (has_music(MUS_MP3)) {
    1.51 +        if (load_music_type(MUS_MP3)) {
    1.52 +            open_music_type(MUS_MP3);
    1.53              result |= MIX_INIT_MP3;
    1.54          } else {
    1.55              Mix_SetError("MP3 support not available");
    1.56          }
    1.57      }
    1.58      if (flags & MIX_INIT_OGG) {
    1.59 -        if (has_music(MUS_OGG)) {
    1.60 +        if (load_music_type(MUS_OGG)) {
    1.61 +            open_music_type(MUS_OGG);
    1.62              result |= MIX_INIT_OGG;
    1.63          } else {
    1.64              Mix_SetError("OGG support not available");
    1.65          }
    1.66      }
    1.67      if (flags & MIX_INIT_MID) {
    1.68 -        if (has_music(MUS_MID)) {
    1.69 +        if (load_music_type(MUS_MID)) {
    1.70 +            open_music_type(MUS_MID);
    1.71              result |= MIX_INIT_MID;
    1.72          } else {
    1.73              Mix_SetError("MIDI support not available");
    1.74          }
    1.75      }
    1.76 -    return (result);
    1.77 +    return result;
    1.78  }
    1.79  
    1.80  void Mix_Quit()
    1.81 @@ -400,13 +413,6 @@
    1.82      PrintFormat("Audio device", &mixer);
    1.83  #endif
    1.84  
    1.85 -    /* Initialize the music players */
    1.86 -    load_music();
    1.87 -    if (open_music(&mixer) < 0) {
    1.88 -        SDL_CloseAudioDevice(audio_device);
    1.89 -        return(-1);
    1.90 -    }
    1.91 -
    1.92      num_channels = MIX_CHANNELS;
    1.93      mix_channel = (struct _Mix_Channel *) SDL_malloc(num_channels * sizeof(struct _Mix_Channel));
    1.94  
    1.95 @@ -431,21 +437,9 @@
    1.96      add_chunk_decoder("WAVE");
    1.97      add_chunk_decoder("AIFF");
    1.98      add_chunk_decoder("VOC");
    1.99 -    if (has_music(MUS_MOD)) {
   1.100 -        add_chunk_decoder("MOD");
   1.101 -    }
   1.102 -    if (has_music(MUS_MID)) {
   1.103 -        add_chunk_decoder("MID");
   1.104 -    }
   1.105 -    if (has_music(MUS_OGG)) {
   1.106 -        add_chunk_decoder("OGG");
   1.107 -    }
   1.108 -    if (has_music(MUS_MP3)) {
   1.109 -        add_chunk_decoder("MP3");
   1.110 -    }
   1.111 -    if (has_music(MUS_FLAC)) {
   1.112 -        add_chunk_decoder("FLAC");
   1.113 -    }
   1.114 +
   1.115 +    /* Initialize the music players */
   1.116 +    open_music(&mixer);
   1.117  
   1.118      audio_opened = 1;
   1.119      SDL_PauseAudioDevice(audio_device, 0);
   1.120 @@ -536,6 +530,10 @@
   1.121      int count = 0;
   1.122      int fragment_size;
   1.123  
   1.124 +    if (!load_music_type(music_type) || !open_music_type(music_type)) {
   1.125 +        return NULL;
   1.126 +    }
   1.127 +
   1.128      *spec = mixer;
   1.129  
   1.130      /* Use fragments sized on full audio frame boundaries - this'll do */
   1.131 @@ -544,6 +542,9 @@
   1.132      start = SDL_RWtell(src);
   1.133      for (i = 0; i < get_num_music_interfaces(); ++i) {
   1.134          interface = get_music_interface(i);
   1.135 +        if (!interface->opened) {
   1.136 +            continue;
   1.137 +        }
   1.138          if (interface->type != music_type) {
   1.139              continue;
   1.140          }
     2.1 --- a/mixer.h	Mon Oct 23 12:40:10 2017 -0700
     2.2 +++ b/mixer.h	Tue Oct 24 21:41:50 2017 -0700
     2.3 @@ -23,4 +23,6 @@
     2.4  extern void Mix_LockAudio(void);
     2.5  extern void Mix_UnlockAudio(void);
     2.6  
     2.7 +extern void add_chunk_decoder(const char *decoder);
     2.8 +
     2.9  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/music.c	Mon Oct 23 12:40:10 2017 -0700
     3.2 +++ b/music.c	Tue Oct 24 21:41:50 2017 -0700
     3.3 @@ -42,6 +42,9 @@
     3.4  #include "music_flac.h"
     3.5  #include "native_midi/native_midi.h"
     3.6  
     3.7 +/* Set this hint to true if you want verbose logging of music interfaces */
     3.8 +#define SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES \
     3.9 +    "SDL_MIXER_DEBUG_MUSIC_INTERFACES"
    3.10  
    3.11  char *music_cmd = NULL;
    3.12  static SDL_bool music_active = SDL_TRUE;
    3.13 @@ -135,7 +138,17 @@
    3.14  
    3.15  static void add_music_decoder(const char *decoder)
    3.16  {
    3.17 -    void *ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
    3.18 +    void *ptr;
    3.19 +    int i;
    3.20 +
    3.21 +    /* Check to see if we already have this decoder */
    3.22 +    for (i = 0; i < num_decoders; ++i) {
    3.23 +        if (SDL_strcmp(music_decoders[i], decoder) == 0) {
    3.24 +            return;
    3.25 +        }
    3.26 +    }
    3.27 +
    3.28 +    ptr = SDL_realloc((void *)music_decoders, (num_decoders + 1) * sizeof (const char *));
    3.29      if (ptr == NULL) {
    3.30          return;  /* oh well, go on without it. */
    3.31      }
    3.32 @@ -252,28 +265,123 @@
    3.33      }
    3.34  }
    3.35  
    3.36 -/* Load the music interface libraries */
    3.37 -int load_music(void)
    3.38 +/* Load the music interface libraries for a given music type */
    3.39 +SDL_bool load_music_type(Mix_MusicType type)
    3.40  {
    3.41 -    char hint[128];
    3.42 -
    3.43 -    int i;
    3.44 +    int i, loaded = 0;
    3.45      for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
    3.46          Mix_MusicInterface *interface = s_music_interfaces[i];
    3.47 -        if (interface->loaded) {
    3.48 +        if (interface->type != type) {
    3.49 +            continue;
    3.50 +        }
    3.51 +        if (!interface->loaded) {
    3.52 +            char hint[64];
    3.53 +            SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
    3.54 +            if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
    3.55 +                continue;
    3.56 +            }
    3.57 +
    3.58 +            if (interface->Load && interface->Load() < 0) {
    3.59 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
    3.60 +                    SDL_Log("Couldn't load %s: %s\n", interface->tag, Mix_GetError());
    3.61 +                }
    3.62 +                continue;
    3.63 +            }
    3.64 +            interface->loaded = SDL_TRUE;
    3.65 +        }
    3.66 +        ++loaded;
    3.67 +    }
    3.68 +    return (loaded > 0) ? SDL_TRUE : SDL_FALSE;
    3.69 +}
    3.70 +
    3.71 +/* Open the music interfaces for a given music type */
    3.72 +SDL_bool open_music_type(Mix_MusicType type)
    3.73 +{
    3.74 +    int i, opened = 0;
    3.75 +    SDL_bool use_native_midi = SDL_FALSE;
    3.76 +
    3.77 +    if (!music_spec.format) {
    3.78 +        /* Music isn't opened yet */
    3.79 +        return SDL_FALSE;
    3.80 +    }
    3.81 +
    3.82 +#ifdef MUSIC_MID_NATIVE
    3.83 +    if (type == MUS_MID && SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
    3.84 +        use_native_midi = SDL_TRUE;
    3.85 +    }
    3.86 +#endif
    3.87 +
    3.88 +    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
    3.89 +        Mix_MusicInterface *interface = s_music_interfaces[i];
    3.90 +        if (!interface->loaded) {
    3.91 +            continue;
    3.92 +        }
    3.93 +        if (type != MUS_NONE && interface->type != type) {
    3.94              continue;
    3.95          }
    3.96  
    3.97 -        SDL_snprintf(hint, sizeof(hint), "SDL_MIXER_DISABLE_%s", interface->tag);
    3.98 -        if (SDL_GetHintBoolean(hint, SDL_FALSE)) {
    3.99 +        if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
   3.100              continue;
   3.101          }
   3.102  
   3.103 -        if (!interface->Load || interface->Load() == 0) {
   3.104 -            interface->loaded = SDL_TRUE;
   3.105 +        if (!interface->opened) {
   3.106 +            if (interface->Open && interface->Open(&music_spec) < 0) {
   3.107 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
   3.108 +                    SDL_Log("Couldn't open %s: %s\n", interface->tag, Mix_GetError());
   3.109 +                }
   3.110 +                continue;
   3.111 +            }
   3.112 +            interface->opened = SDL_TRUE;
   3.113 +            add_music_decoder(interface->tag);
   3.114          }
   3.115 +        ++opened;
   3.116      }
   3.117 -    return 0;
   3.118 +
   3.119 +    if (has_music(MUS_MOD)) {
   3.120 +        add_music_decoder("MOD");
   3.121 +        add_chunk_decoder("MOD");
   3.122 +    }
   3.123 +    if (has_music(MUS_MID)) {
   3.124 +        add_music_decoder("MIDI");
   3.125 +        add_chunk_decoder("MID");
   3.126 +    }
   3.127 +    if (has_music(MUS_OGG)) {
   3.128 +        add_music_decoder("OGG");
   3.129 +        add_chunk_decoder("OGG");
   3.130 +    }
   3.131 +    if (has_music(MUS_MP3)) {
   3.132 +        add_music_decoder("MP3");
   3.133 +        add_chunk_decoder("MP3");
   3.134 +    }
   3.135 +    if (has_music(MUS_FLAC)) {
   3.136 +        add_music_decoder("FLAC");
   3.137 +        add_chunk_decoder("FLAC");
   3.138 +    }
   3.139 +
   3.140 +    return (opened > 0) ? SDL_TRUE : SDL_FALSE;
   3.141 +}
   3.142 +
   3.143 +/* Initialize the music interfaces with a certain desired audio format */
   3.144 +void open_music(const SDL_AudioSpec *spec)
   3.145 +{
   3.146 +#ifdef MIX_INIT_SOUNDFONT_PATHS
   3.147 +    if (!soundfont_paths) {
   3.148 +        soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
   3.149 +    }
   3.150 +#endif
   3.151 +
   3.152 +    /* Load the music interfaces that don't have explicit initialization */
   3.153 +    load_music_type(MUS_CMD);
   3.154 +    load_music_type(MUS_WAV);
   3.155 +
   3.156 +    /* Open all the interfaces that are loaded */
   3.157 +    music_spec = *spec;
   3.158 +    open_music_type(MUS_NONE);
   3.159 +
   3.160 +    Mix_VolumeMusic(MIX_MAX_VOLUME);
   3.161 +
   3.162 +    /* Calculate the number of ms for each callback */
   3.163 +    ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
   3.164  }
   3.165  
   3.166  /* Return SDL_TRUE if the music type is available */
   3.167 @@ -292,60 +400,6 @@
   3.168      return SDL_FALSE;
   3.169  }
   3.170  
   3.171 -/* Initialize the music interfaces with a certain desired audio format */
   3.172 -int open_music(const SDL_AudioSpec *spec)
   3.173 -{
   3.174 -    int i;
   3.175 -    SDL_bool use_native_midi = SDL_FALSE;
   3.176 -
   3.177 -#ifdef MIX_INIT_SOUNDFONT_PATHS
   3.178 -    if (!soundfont_paths) {
   3.179 -        soundfont_paths = SDL_strdup(MIX_INIT_SOUNDFONT_PATHS);
   3.180 -    }
   3.181 -#endif
   3.182 -
   3.183 -
   3.184 -#ifdef MUSIC_MID_NATIVE
   3.185 -    if (SDL_GetHintBoolean("SDL_NATIVE_MUSIC", SDL_FALSE) && native_midi_detect()) {
   3.186 -        use_native_midi = SDL_TRUE;
   3.187 -    }
   3.188 -#endif
   3.189 -
   3.190 -    music_spec = *spec;
   3.191 -    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   3.192 -        Mix_MusicInterface *interface = s_music_interfaces[i];
   3.193 -        if (!interface->loaded) {
   3.194 -            continue;
   3.195 -        }
   3.196 -
   3.197 -        if (interface->type == MUS_MID && use_native_midi && interface->api != MIX_MUSIC_NATIVEMIDI) {
   3.198 -            continue;
   3.199 -        }
   3.200 -
   3.201 -        if (!interface->Open || interface->Open(spec) == 0) {
   3.202 -            interface->opened = SDL_TRUE;
   3.203 -            add_music_decoder(interface->tag);
   3.204 -        }
   3.205 -    }
   3.206 -
   3.207 -    if (has_music(MUS_MOD)) {
   3.208 -        add_music_decoder("MOD");
   3.209 -    }
   3.210 -    if (has_music(MUS_MID)) {
   3.211 -        add_music_decoder("MIDI");
   3.212 -    }
   3.213 -    if (has_music(MUS_MP3)) {
   3.214 -        add_music_decoder("MP3");
   3.215 -    }
   3.216 -
   3.217 -    Mix_VolumeMusic(MIX_MAX_VOLUME);
   3.218 -
   3.219 -    /* Calculate the number of ms for each callback */
   3.220 -    ms_per_step = (int) (((float)spec->samples * 1000.0) / spec->freq);
   3.221 -
   3.222 -    return 0;
   3.223 -}
   3.224 -
   3.225  Mix_MusicType detect_music_type_from_magic(const Uint8 *magic)
   3.226  {
   3.227      /* Ogg Vorbis files have the magic four bytes "OggS" */
   3.228 @@ -509,32 +563,34 @@
   3.229  
   3.230      Mix_ClearError();
   3.231  
   3.232 -    for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   3.233 -        Mix_MusicInterface *interface = s_music_interfaces[i];
   3.234 -        if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
   3.235 -            continue;
   3.236 +    if (load_music_type(type) && open_music_type(type)) {
   3.237 +        for (i = 0; i < SDL_arraysize(s_music_interfaces); ++i) {
   3.238 +            Mix_MusicInterface *interface = s_music_interfaces[i];
   3.239 +            if (!interface->opened || type != interface->type || !interface->CreateFromRW) {
   3.240 +                continue;
   3.241 +            }
   3.242 +
   3.243 +            context = interface->CreateFromRW(src, freesrc);
   3.244 +            if (context) {
   3.245 +                /* Allocate memory for the music structure */
   3.246 +                Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
   3.247 +                if (music == NULL) {
   3.248 +                    interface->Delete(context);
   3.249 +                    Mix_SetError("Out of memory");
   3.250 +                    return NULL;
   3.251 +                }
   3.252 +                music->interface = interface;
   3.253 +                music->context = context;
   3.254 +
   3.255 +                if (SDL_GetHintBoolean(SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES, SDL_FALSE)) {
   3.256 +                    SDL_Log("Loaded music with %s\n", interface->tag);
   3.257 +                }
   3.258 +                return music;
   3.259 +            }
   3.260 +
   3.261 +            /* Reset the stream for the next decoder */
   3.262 +            SDL_RWseek(src, start, RW_SEEK_SET);
   3.263          }
   3.264 -
   3.265 -        context = interface->CreateFromRW(src, freesrc);
   3.266 -        if (context) {
   3.267 -            /* Allocate memory for the music structure */
   3.268 -            Mix_Music *music = (Mix_Music *)SDL_calloc(1, sizeof(Mix_Music));
   3.269 -            if (music == NULL) {
   3.270 -                interface->Delete(context);
   3.271 -                Mix_SetError("Out of memory");
   3.272 -                return NULL;
   3.273 -            }
   3.274 -            music->interface = interface;
   3.275 -            music->context = context;
   3.276 -#ifdef DEBUG_MUSIC
   3.277 -            /* This would be useful to expose via an API */
   3.278 -            SDL_Log("Music playing with %s\n", interface->tag);
   3.279 -#endif
   3.280 -            return music;
   3.281 -        }
   3.282 -
   3.283 -        /* Reset the stream for the next decoder */
   3.284 -        SDL_RWseek(src, start, RW_SEEK_SET);
   3.285      }
   3.286  
   3.287      if (!*Mix_GetError()) {
     4.1 --- a/music.h	Mon Oct 23 12:40:10 2017 -0700
     4.2 +++ b/music.h	Tue Oct 24 21:41:50 2017 -0700
     4.3 @@ -103,12 +103,13 @@
     4.4  } Mix_MusicInterface;
     4.5  
     4.6  
     4.7 -extern int load_music(void);
     4.8 -extern Mix_MusicType detect_music_type_from_magic(const Uint8 *magic);
     4.9  extern int get_num_music_interfaces(void);
    4.10  extern Mix_MusicInterface *get_music_interface(int index);
    4.11 +extern Mix_MusicType detect_music_type_from_magic(const Uint8 *magic);
    4.12 +extern SDL_bool load_music_type(Mix_MusicType type);
    4.13 +extern SDL_bool open_music_type(Mix_MusicType type);
    4.14  extern SDL_bool has_music(Mix_MusicType type);
    4.15 -extern int open_music(const SDL_AudioSpec *spec);
    4.16 +extern void open_music(const SDL_AudioSpec *spec);
    4.17  extern int music_pcm_getaudio(void *context, void *data, int bytes, int volume,
    4.18                                int (*GetSome)(void *context, void *data, int bytes, SDL_bool *done));
    4.19  extern void SDLCALL music_mixer(void *udata, Uint8 *stream, int len);