- ZMusic interface refactoring.

Use global functions instead of the class interface which exposed too many implementation details.
This commit is contained in:
Christoph Oelckers 2019-10-15 00:23:03 +02:00
parent 30f2ac1e89
commit dc32c2148a
9 changed files with 173 additions and 97 deletions

View file

@ -454,8 +454,11 @@ bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo *currSong, int value,
return false; return false;
case snd_mididevice: case snd_mididevice:
{
bool change = miscConfig.snd_mididevice != value;
miscConfig.snd_mididevice = value; miscConfig.snd_mididevice = value;
return false; return change;
}
case snd_outputrate: case snd_outputrate:
miscConfig.snd_outputrate = value; miscConfig.snd_outputrate = value;

View file

@ -37,5 +37,4 @@ public:
STATE_Paused STATE_Paused
} m_Status = STATE_Stopped; } m_Status = STATE_Stopped;
bool m_Looping = false; bool m_Looping = false;
bool m_NotStartedYet = false; // Song has been created but not yet played
}; };

View file

@ -306,3 +306,102 @@ MusInfo *ZMusic_OpenCDSong (int track, int id)
return info; return info;
} }
//==========================================================================
//
// streaming callback
//
//==========================================================================
bool ZMusic_FillStream(MusInfo* stream, void* buff, int len)
{
if (stream == nullptr) return false;
return stream->ServiceStream(buff, len);
}
//==========================================================================
//
// starts playback
//
//==========================================================================
void ZMusic_Start(MusInfo *song, int subsong, bool loop)
{
if (!song) return;
song->Play(loop, subsong);
}
//==========================================================================
//
// Utilities
//
//==========================================================================
void ZMusic_Pause(MusInfo *song)
{
if (!song) return;
song->Pause();
}
void ZMusic_Resume(MusInfo *song)
{
if (!song) return;
song->Resume();
}
void ZMusic_Update(MusInfo *song)
{
if (!song) return;
song->Update();
}
bool ZMusic_IsPlaying(MusInfo *song)
{
if (!song) return false;
return song->IsPlaying();
}
void ZMusic_Stop(MusInfo *song)
{
if (!song) return;
song->Stop();
}
bool ZMusic_SetSubsong(MusInfo *song, int subsong)
{
if (!song) return false;
return song->SetSubsong(subsong);
}
bool ZMusic_IsLooping(MusInfo *song)
{
if (!song) return false;
return song->m_Looping;
}
bool ZMusic_IsMIDI(MusInfo *song)
{
if (!song) return false;
return song->IsMIDI();
}
SoundStreamInfo ZMusic_GetStreamInfo(MusInfo *song)
{
if (!song) return {};
return song->GetStreamInfo();
}
void ZMusic_Close(MusInfo *song)
{
if (song) delete song;
}
void ZMusic_VolumeChanged(MusInfo *song)
{
if (song) song->MusicVolumeChanged();
}
std::string ZMusic_GetStats(MusInfo *song)
{
if (!song) return "";
return song->GetStats();
}

View file

@ -159,7 +159,21 @@ void MIDIDumpWave(MIDISource* source, EMidiDevice devtype, const char* devarg, c
MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, const char *Args); MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, const char *Args);
MusInfo *ZMusic_OpenCDSong (int track, int cdid = 0); MusInfo *ZMusic_OpenCDSong (int track, int cdid = 0);
class MusInfo; bool ZMusic_FillStream(MusInfo* stream, void* buff, int len);
void ZMusic_Start(MusInfo *song, int subsong, bool loop);
void ZMusic_Pause(MusInfo *song);
void ZMusic_Resume(MusInfo *song);
void ZMusic_Update(MusInfo *song);
bool ZMusic_IsPlaying(MusInfo *song);
void ZMusic_Stop(MusInfo *song);
void ZMusic_Close(MusInfo *song);
bool ZMusic_SetSubsong(MusInfo *song, int subsong);
bool ZMusic_IsLooping(MusInfo *song);
bool ZMusic_IsMIDI(MusInfo *song);
void ZMusic_VolumeChanged(MusInfo *song);
SoundStreamInfo ZMusic_GetStreamInfo(MusInfo *song);
std::string ZMusic_GetStats(MusInfo *song);
// Configuration interface. The return value specifies if a music restart is needed. // Configuration interface. The return value specifies if a music restart is needed.
// RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state. // RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state.
bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo *song, int value, int *pRealValue = nullptr); bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo *song, int value, int *pRealValue = nullptr);

View file

@ -53,7 +53,6 @@
#include "s_music.h" #include "s_music.h"
#include "doomstat.h" #include "doomstat.h"
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
#include "zmusic/musinfo.h"
#include "streamsources/streamsource.h" #include "streamsources/streamsource.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
#include "../libraries/zmusic/midisources/midisource.h" #include "../libraries/zmusic/midisources/midisource.h"
@ -133,7 +132,7 @@ CUSTOM_CVAR (Float, snd_musicvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
// let them know about the change. // let them know about the change.
if (mus_playing.handle != nullptr) if (mus_playing.handle != nullptr)
{ {
mus_playing.handle->MusicVolumeChanged(); ZMusic_VolumeChanged(mus_playing.handle);
} }
else else
{ // If the music was stopped because volume was 0, start it now. { // If the music was stopped because volume was 0, start it now.
@ -274,6 +273,7 @@ void I_InitMusic (void)
#ifdef _WIN32 #ifdef _WIN32
I_InitMusicWin32 (); I_InitMusicWin32 ();
#endif // _WIN32 #endif // _WIN32
snd_mididevice.Callback();
Callbacks callbacks; Callbacks callbacks;
@ -342,7 +342,7 @@ ADD_STAT(music)
{ {
if (mus_playing.handle != nullptr) if (mus_playing.handle != nullptr)
{ {
return FString(mus_playing.handle->GetStats().c_str()); return FString(ZMusic_GetStats(mus_playing.handle).c_str());
} }
return "No song playing"; return "No song playing";
} }

View file

@ -50,17 +50,17 @@
decltype(*self) newval; \ decltype(*self) newval; \
auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \
self = (decltype(*self))newval; \ self = (decltype(*self))newval; \
if (ret) S_MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1);
#define FORWARD_BOOL_CVAR(key) \ #define FORWARD_BOOL_CVAR(key) \
int newval; \ int newval; \
auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \
self = !!newval; \ self = !!newval; \
if (ret) S_MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1);
#define FORWARD_STRING_CVAR(key) \ #define FORWARD_STRING_CVAR(key) \
auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self); \ auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self); \
if (ret) S_MIDIDeviceChanged(-1, true); if (ret) S_MIDIDeviceChanged(-1);
CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)

View file

@ -45,8 +45,10 @@
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
#include "s_music.h" #include "s_music.h"
#define DEF_MIDIDEV -5
EXTERN_CVAR(Int, snd_mididevice)
static uint32_t nummididevices; static uint32_t nummididevices;
static bool nummididevicesset;
#define NUM_DEF_DEVICES 7 #define NUM_DEF_DEVICES 7
@ -70,39 +72,11 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
} }
#define DEF_MIDIDEV -5
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (!nummididevicesset)
return;
if ((self >= (signed)nummididevices) || (self < -8))
{
// Don't do repeated message spam if there is no valid device.
if (self != 0)
{
Printf("ID out of range. Using default device.\n");
self = DEF_MIDIDEV;
}
return;
}
else if (self == -1) self = DEF_MIDIDEV;
ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self);
S_MIDIDeviceChanged(self, false);
}
void I_InitMusicWin32 () void I_InitMusicWin32 ()
{ {
nummididevices = midiOutGetNumDevs (); nummididevices = midiOutGetNumDevs ();
nummididevicesset = true;
snd_mididevice.Callback ();
} }
void I_BuildMIDIMenuList (FOptionValues *opt) void I_BuildMIDIMenuList (FOptionValues *opt)
@ -196,21 +170,6 @@ CCMD (snd_listmididevices)
#else #else
// Everything but Windows uses this code.
CUSTOM_CVAR(Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < -8)
self = -8;
else if (self > -2)
self = -2;
else
{
ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self);
S_MIDIDeviceChanged(self, false);
}
}
void I_BuildMIDIMenuList (FOptionValues *opt) void I_BuildMIDIMenuList (FOptionValues *opt)
{ {
AddDefaultMidiDevices(opt); AddDefaultMidiDevices(opt);
@ -227,3 +186,25 @@ CCMD (snd_listmididevices)
Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "");
} }
#endif #endif
CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if ((self >= (signed)nummididevices) || (self < -8))
{
// Don't do repeated message spam if there is no valid device.
if (self != 0)
{
Printf("ID out of range. Using default device.\n");
}
self = DEF_MIDIDEV;
return;
}
else if (self == -1)
{
self = DEF_MIDIDEV;
return;
}
bool change = ChangeMusicSetting(ZMusic::snd_mididevice, nullptr, self);
if (change) S_MIDIDeviceChanged(self);
}

View file

@ -86,7 +86,6 @@
#include "g_game.h" #include "g_game.h"
#include "s_music.h" #include "s_music.h"
#include "filereadermusicinterface.h" #include "filereadermusicinterface.h"
#include "zmusic/musinfo.h"
#include "zmusic/zmusic.h" #include "zmusic/zmusic.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -126,7 +125,8 @@ static std::unique_ptr<SoundStream> musicStream;
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
{ {
bool written = mus_playing.handle? mus_playing.handle->ServiceStream(buff, len) : 0; bool written = ZMusic_FillStream(mus_playing.handle, buff, len);
if (!written) if (!written)
{ {
memset((char*)buff, 0, len); memset((char*)buff, 0, len);
@ -139,7 +139,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
void S_CreateStream() void S_CreateStream()
{ {
if (!mus_playing.handle) return; if (!mus_playing.handle) return;
auto fmt = mus_playing.handle->GetStreamInfo(); auto fmt = ZMusic_GetStreamInfo(mus_playing.handle);
if (fmt.mBufferSize > 0) if (fmt.mBufferSize > 0)
{ {
int flags = fmt.mNumChannels < 0 ? 0 : SoundStream::Float; int flags = fmt.mNumChannels < 0 ? 0 : SoundStream::Float;
@ -179,9 +179,8 @@ static void S_StartMusicPlaying(MusInfo* song, bool loop, float rel_vol, int sub
saved_relative_volume = rel_vol; saved_relative_volume = rel_vol;
I_SetRelativeVolume(saved_relative_volume * factor); I_SetRelativeVolume(saved_relative_volume * factor);
} }
song->Stop(); ZMusic_Stop(song);
song->Play(loop, subsong); ZMusic_Start(song, subsong, loop);
song->m_NotStartedYet = false;
// Notify the sound system of the changed relative volume // Notify the sound system of the changed relative volume
snd_musicvolume.Callback(); snd_musicvolume.Callback();
@ -199,7 +198,7 @@ void S_PauseMusic ()
{ {
if (mus_playing.handle && !MusicPaused) if (mus_playing.handle && !MusicPaused)
{ {
mus_playing.handle->Pause(); ZMusic_Pause(mus_playing.handle);
S_PauseStream(true); S_PauseStream(true);
MusicPaused = true; MusicPaused = true;
} }
@ -216,7 +215,7 @@ void S_ResumeMusic ()
{ {
if (mus_playing.handle && MusicPaused) if (mus_playing.handle && MusicPaused)
{ {
mus_playing.handle->Resume(); ZMusic_Resume(mus_playing.handle);
S_PauseStream(false); S_PauseStream(false);
MusicPaused = false; MusicPaused = false;
} }
@ -232,12 +231,12 @@ void S_UpdateMusic ()
{ {
if (mus_playing.handle != nullptr) if (mus_playing.handle != nullptr)
{ {
mus_playing.handle->Update(); ZMusic_Update(mus_playing.handle);
// [RH] Update music and/or playlist. IsPlaying() must be called // [RH] Update music and/or playlist. IsPlaying() must be called
// to attempt to reconnect to broken net streams and to advance the // to attempt to reconnect to broken net streams and to advance the
// playlist when the current song finishes. // playlist when the current song finishes.
if (!mus_playing.handle->IsPlaying()) if (!ZMusic_IsPlaying(mus_playing.handle))
{ {
if (PlayList.GetNumSongs()) if (PlayList.GetNumSongs())
{ {
@ -408,20 +407,20 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
if (!mus_playing.name.IsEmpty() && if (!mus_playing.name.IsEmpty() &&
mus_playing.handle != nullptr && mus_playing.handle != nullptr &&
stricmp (mus_playing.name, musicname) == 0 && stricmp (mus_playing.name, musicname) == 0 &&
mus_playing.handle->m_Looping == looping) ZMusic_IsLooping(mus_playing.handle) == looping)
{ {
if (order != mus_playing.baseorder) if (order != mus_playing.baseorder)
{ {
if (mus_playing.handle->SetSubsong(order)) if (ZMusic_SetSubsong(mus_playing.handle, order))
{ {
mus_playing.baseorder = order; mus_playing.baseorder = order;
} }
} }
else if (!mus_playing.handle->IsPlaying()) else if (!ZMusic_IsPlaying(mus_playing.handle))
{ {
try try
{ {
mus_playing.handle->Play(looping, order); ZMusic_Start(mus_playing.handle, looping, order);
S_CreateStream(); S_CreateStream();
} }
catch (const std::runtime_error& err) catch (const std::runtime_error& err)
@ -574,35 +573,16 @@ void S_RestartMusic ()
//========================================================================== //==========================================================================
void S_MIDIDeviceChanged(int newdev, bool force) void S_MIDIDeviceChanged(int newdev)
{ {
static int oldmididev = INT_MIN; MusInfo* song = mus_playing.handle;
if (song != nullptr && ZMusic_IsMIDI(song) && ZMusic_IsPlaying(song))
// If a song is playing, move it to the new device.
if (oldmididev != newdev || force)
{ {
if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI()) // Reload the song to change the device
{ auto mi = mus_playing;
MusInfo* song = mus_playing.handle; S_StopMusic(true);
if (song->m_Status == MusInfo::STATE_Playing) S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
{
if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force)
{
// FluidSynth must reload the song to change the patch set.
auto mi = mus_playing;
S_StopMusic(true);
S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
}
else
{
song->Stop();
S_StartMusicPlaying(song, song->m_Looping, -1, 0);
}
}
}
} }
// 'force'
if (!force) oldmididev = newdev;
} }
//========================================================================== //==========================================================================
@ -645,8 +625,8 @@ void S_StopMusic (bool force)
{ {
S_ResumeMusic(); S_ResumeMusic();
S_StopStream(); S_StopStream();
mus_playing.handle->Stop(); ZMusic_Stop(mus_playing.handle);
delete mus_playing.handle; ZMusic_Close(mus_playing.handle);
mus_playing.handle = nullptr; mus_playing.handle = nullptr;
} }
mus_playing.LastSong = std::move(mus_playing.name); mus_playing.LastSong = std::move(mus_playing.name);
@ -657,7 +637,7 @@ void S_StopMusic (bool force)
//Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what()); //Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what());
if (mus_playing.handle != nullptr) if (mus_playing.handle != nullptr)
{ {
delete mus_playing.handle; ZMusic_Close(mus_playing.handle);
mus_playing.handle = nullptr; mus_playing.handle = nullptr;
} }
mus_playing.name = ""; mus_playing.name = "";

View file

@ -50,7 +50,7 @@ bool S_ChangeMusic (const char *music_name, int order=0, bool looping=true, bool
bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true); bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true);
void S_RestartMusic (); void S_RestartMusic ();
void S_MIDIDeviceChanged(int newdev, bool force); void S_MIDIDeviceChanged(int newdev);
int S_GetMusic (const char **name); int S_GetMusic (const char **name);