Delegate managing SDL_RWops to SDL_mixer when possible

SDL_mixer 2 offers the option to have the library free the SDL_RWops.
Add macros to use this feature when available.

References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/82>
This commit is contained in:
Kp 2018-07-05 04:03:34 +00:00
parent d97afc2ad5
commit 9ea09107d1

View file

@ -29,8 +29,23 @@ namespace dcx {
namespace {
#if SDL_MIXER_MAJOR_VERSION == 2
#define DXX_SDL_MIXER_MANAGES_RWOPS 1
#else
#define DXX_SDL_MIXER_MANAGES_RWOPS 0
#endif
#if DXX_SDL_MIXER_MANAGES_RWOPS
#define DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS , SDL_TRUE
#define DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw)
#else
#define DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS
#define DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw) , rw
#endif
class current_music_t
{
#if !DXX_SDL_MIXER_MANAGES_RWOPS
struct RWops_delete
{
void operator()(SDL_RWops *o)
@ -38,30 +53,38 @@ class current_music_t
SDL_RWclose(o);
}
};
using rwops_pointer = std::unique_ptr<SDL_RWops, RWops_delete>;
rwops_pointer m_ops;
#endif
struct Music_delete
{
void operator()(Mix_Music *m) { Mix_FreeMusic(m); }
};
typedef SDL_RWops *rpointer;
typedef Mix_Music *mpointer;
std::unique_ptr<SDL_RWops, RWops_delete> m_ops;
std::unique_ptr<Mix_Music, Music_delete> m_music;
using music_pointer = std::unique_ptr<Mix_Music, Music_delete>;
music_pointer m_music;
public:
void reset(mpointer m = mpointer(), rpointer r = rpointer()) noexcept(noexcept(m_music.reset(m)) && noexcept(m_ops.reset(r)))
void reset(
Mix_Music *const music = nullptr
#if !DXX_SDL_MIXER_MANAGES_RWOPS
, SDL_RWops *const rwops = nullptr
#endif
) noexcept
{
/* Clear music first in case it needs the old ops
* Clear old ops
* If no new music, clear new ops immediately. This only
* happens if the new music fails to load.
*/
m_music.reset(m);
m_ops.reset(r);
if (!m)
m_music.reset(music);
#if !DXX_SDL_MIXER_MANAGES_RWOPS
m_ops.reset(rwops);
if (!music)
m_ops.reset();
#endif
}
bool operator!() const { return !m_music; }
explicit operator bool() const { return static_cast<bool>(m_music); }
mpointer get() { return m_music.get(); }
typename music_pointer::pointer get() { return m_music.get(); }
};
}
@ -92,7 +115,7 @@ int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
{
hmp2mid(filename, current_music_hndlbuf);
rw = SDL_RWFromConstMem(&current_music_hndlbuf[0], current_music_hndlbuf.size()*sizeof(char));
current_music.reset(Mix_LoadMUS_RW(rw), rw);
current_music.reset(Mix_LoadMUS_RW(rw DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS) DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw));
}
// try loading music via given filename
@ -133,7 +156,7 @@ int mix_play_file(const char *filename, int loop, void (*hook_finished_track)())
current_music_hndlbuf.resize(len);
bufsize = PHYSFS_read(filehandle, &current_music_hndlbuf[0], sizeof(char), len);
rw = SDL_RWFromConstMem(&current_music_hndlbuf[0], bufsize*sizeof(char));
current_music.reset(Mix_LoadMUS_RW(rw), rw);
current_music.reset(Mix_LoadMUS_RW(rw DXX_SDL_MIXER_Mix_LoadMUS_MANAGE_RWOPS) DXX_SDL_MIXER_Mix_LoadMUS_PASS_RWOPS(rw));
}
}