- 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;
case snd_mididevice:
{
bool change = miscConfig.snd_mididevice != value;
miscConfig.snd_mididevice = value;
return false;
return change;
}
case snd_outputrate:
miscConfig.snd_outputrate = value;

View file

@ -37,5 +37,4 @@ public:
STATE_Paused
} m_Status = STATE_Stopped;
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;
}
//==========================================================================
//
// 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_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.
// 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);

View file

@ -53,7 +53,6 @@
#include "s_music.h"
#include "doomstat.h"
#include "zmusic/zmusic.h"
#include "zmusic/musinfo.h"
#include "streamsources/streamsource.h"
#include "filereadermusicinterface.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.
if (mus_playing.handle != nullptr)
{
mus_playing.handle->MusicVolumeChanged();
ZMusic_VolumeChanged(mus_playing.handle);
}
else
{ // If the music was stopped because volume was 0, start it now.
@ -274,6 +273,7 @@ void I_InitMusic (void)
#ifdef _WIN32
I_InitMusicWin32 ();
#endif // _WIN32
snd_mididevice.Callback();
Callbacks callbacks;
@ -342,7 +342,7 @@ ADD_STAT(music)
{
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";
}

View file

@ -50,17 +50,17 @@
decltype(*self) newval; \
auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \
self = (decltype(*self))newval; \
if (ret) S_MIDIDeviceChanged(-1, true);
if (ret) S_MIDIDeviceChanged(-1);
#define FORWARD_BOOL_CVAR(key) \
int newval; \
auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \
self = !!newval; \
if (ret) S_MIDIDeviceChanged(-1, true);
if (ret) S_MIDIDeviceChanged(-1);
#define FORWARD_STRING_CVAR(key) \
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)

View file

@ -45,8 +45,10 @@
#include "zmusic/zmusic.h"
#include "s_music.h"
#define DEF_MIDIDEV -5
EXTERN_CVAR(Int, snd_mididevice)
static uint32_t nummididevices;
static bool nummididevicesset;
#define NUM_DEF_DEVICES 7
@ -70,39 +72,11 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
}
#define DEF_MIDIDEV -5
#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 ()
{
nummididevices = midiOutGetNumDevs ();
nummididevicesset = true;
snd_mididevice.Callback ();
}
void I_BuildMIDIMenuList (FOptionValues *opt)
@ -196,21 +170,6 @@ CCMD (snd_listmididevices)
#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)
{
AddDefaultMidiDevices(opt);
@ -227,3 +186,25 @@ CCMD (snd_listmididevices)
Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : "");
}
#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 "s_music.h"
#include "filereadermusicinterface.h"
#include "zmusic/musinfo.h"
#include "zmusic/zmusic.h"
// MACROS ------------------------------------------------------------------
@ -126,7 +125,8 @@ static std::unique_ptr<SoundStream> musicStream;
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)
{
memset((char*)buff, 0, len);
@ -139,7 +139,7 @@ static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata)
void S_CreateStream()
{
if (!mus_playing.handle) return;
auto fmt = mus_playing.handle->GetStreamInfo();
auto fmt = ZMusic_GetStreamInfo(mus_playing.handle);
if (fmt.mBufferSize > 0)
{
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;
I_SetRelativeVolume(saved_relative_volume * factor);
}
song->Stop();
song->Play(loop, subsong);
song->m_NotStartedYet = false;
ZMusic_Stop(song);
ZMusic_Start(song, subsong, loop);
// Notify the sound system of the changed relative volume
snd_musicvolume.Callback();
@ -199,7 +198,7 @@ void S_PauseMusic ()
{
if (mus_playing.handle && !MusicPaused)
{
mus_playing.handle->Pause();
ZMusic_Pause(mus_playing.handle);
S_PauseStream(true);
MusicPaused = true;
}
@ -216,7 +215,7 @@ void S_ResumeMusic ()
{
if (mus_playing.handle && MusicPaused)
{
mus_playing.handle->Resume();
ZMusic_Resume(mus_playing.handle);
S_PauseStream(false);
MusicPaused = false;
}
@ -232,12 +231,12 @@ void S_UpdateMusic ()
{
if (mus_playing.handle != nullptr)
{
mus_playing.handle->Update();
ZMusic_Update(mus_playing.handle);
// [RH] Update music and/or playlist. IsPlaying() must be called
// to attempt to reconnect to broken net streams and to advance the
// playlist when the current song finishes.
if (!mus_playing.handle->IsPlaying())
if (!ZMusic_IsPlaying(mus_playing.handle))
{
if (PlayList.GetNumSongs())
{
@ -408,20 +407,20 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
if (!mus_playing.name.IsEmpty() &&
mus_playing.handle != nullptr &&
stricmp (mus_playing.name, musicname) == 0 &&
mus_playing.handle->m_Looping == looping)
ZMusic_IsLooping(mus_playing.handle) == looping)
{
if (order != mus_playing.baseorder)
{
if (mus_playing.handle->SetSubsong(order))
if (ZMusic_SetSubsong(mus_playing.handle, order))
{
mus_playing.baseorder = order;
}
}
else if (!mus_playing.handle->IsPlaying())
else if (!ZMusic_IsPlaying(mus_playing.handle))
{
try
{
mus_playing.handle->Play(looping, order);
ZMusic_Start(mus_playing.handle, looping, order);
S_CreateStream();
}
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;
// If a song is playing, move it to the new device.
if (oldmididev != newdev || force)
MusInfo* song = mus_playing.handle;
if (song != nullptr && ZMusic_IsMIDI(song) && ZMusic_IsPlaying(song))
{
if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI())
{
MusInfo* song = mus_playing.handle;
if (song->m_Status == MusInfo::STATE_Playing)
{
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);
}
}
}
// Reload the song to change the device
auto mi = mus_playing;
S_StopMusic(true);
S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
}
// 'force'
if (!force) oldmididev = newdev;
}
//==========================================================================
@ -645,8 +625,8 @@ void S_StopMusic (bool force)
{
S_ResumeMusic();
S_StopStream();
mus_playing.handle->Stop();
delete mus_playing.handle;
ZMusic_Stop(mus_playing.handle);
ZMusic_Close(mus_playing.handle);
mus_playing.handle = nullptr;
}
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());
if (mus_playing.handle != nullptr)
{
delete mus_playing.handle;
ZMusic_Close(mus_playing.handle);
mus_playing.handle = nullptr;
}
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);
void S_RestartMusic ();
void S_MIDIDeviceChanged(int newdev, bool force);
void S_MIDIDeviceChanged(int newdev);
int S_GetMusic (const char **name);