From dc32c2148a9830164e8f2f276bfafb8ef76409cf Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 15 Oct 2019 00:23:03 +0200 Subject: [PATCH] - ZMusic interface refactoring. Use global functions instead of the class interface which exposed too many implementation details. --- libraries/zmusic/zmusic/configuration.cpp | 5 +- libraries/zmusic/zmusic/musinfo.h | 1 - libraries/zmusic/zmusic/zmusic.cpp | 99 +++++++++++++++++++++++ libraries/zmusic/zmusic/zmusic.h | 16 +++- src/sound/music/i_music.cpp | 6 +- src/sound/music/music_config.cpp | 6 +- src/sound/music/music_midi_base.cpp | 69 ++++++---------- src/sound/s_music.cpp | 66 ++++++--------- src/sound/s_music.h | 2 +- 9 files changed, 173 insertions(+), 97 deletions(-) diff --git a/libraries/zmusic/zmusic/configuration.cpp b/libraries/zmusic/zmusic/configuration.cpp index ded3ea8c68..9a73e2880a 100644 --- a/libraries/zmusic/zmusic/configuration.cpp +++ b/libraries/zmusic/zmusic/configuration.cpp @@ -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; diff --git a/libraries/zmusic/zmusic/musinfo.h b/libraries/zmusic/zmusic/musinfo.h index ed907fb22e..12aa87df19 100644 --- a/libraries/zmusic/zmusic/musinfo.h +++ b/libraries/zmusic/zmusic/musinfo.h @@ -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 }; diff --git a/libraries/zmusic/zmusic/zmusic.cpp b/libraries/zmusic/zmusic/zmusic.cpp index 0fc6de6d50..4060ee223e 100644 --- a/libraries/zmusic/zmusic/zmusic.cpp +++ b/libraries/zmusic/zmusic/zmusic.cpp @@ -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(); +} diff --git a/libraries/zmusic/zmusic/zmusic.h b/libraries/zmusic/zmusic/zmusic.h index 2bd6fcdeb8..abb1f7d4cc 100644 --- a/libraries/zmusic/zmusic/zmusic.h +++ b/libraries/zmusic/zmusic/zmusic.h @@ -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); diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index c6d9f749cd..bef7fe307a 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -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"; } diff --git a/src/sound/music/music_config.cpp b/src/sound/music/music_config.cpp index 47486e8a31..da6103b5ca 100644 --- a/src/sound/music/music_config.cpp +++ b/src/sound/music/music_config.cpp @@ -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) diff --git a/src/sound/music/music_midi_base.cpp b/src/sound/music/music_midi_base.cpp index 6d08fe0e7d..cdd2790d4a 100644 --- a/src/sound/music/music_midi_base.cpp +++ b/src/sound/music/music_midi_base.cpp @@ -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 -#include - -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); +} diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp index 8cae82760a..a6a06f8235 100644 --- a/src/sound/s_music.cpp +++ b/src/sound/s_music.cpp @@ -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 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 = ""; diff --git a/src/sound/s_music.h b/src/sound/s_music.h index f196a658fa..76a0798749 100644 --- a/src/sound/s_music.h +++ b/src/sound/s_music.h @@ -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);