From 7923d25ccef1a0516ee40b032f11a3f65713a19f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Jan 2020 20:01:38 +0100 Subject: [PATCH] - made the ZMusic interface more DLL friendly: Reworked all functions not to throw exceptions across the library boundary and made a few definitions internal. Not complete yet. --- libraries/timidity/common.cpp | 2 +- libraries/zmusic/midisources/midisource.cpp | 42 ++++++--- libraries/zmusic/musicformats/music_midi.cpp | 18 +++- libraries/zmusic/zmusic/configuration.cpp | 10 +-- libraries/zmusic/zmusic/zmusic.cpp | 85 +++++++++++++----- libraries/zmusic/zmusic/zmusic.h | 95 ++++++++++++-------- libraries/zmusic/zmusic/zmusic_internal.h | 11 +++ src/sound/music/i_music.cpp | 38 +++----- src/sound/music/music_config.cpp | 6 +- src/sound/s_music.cpp | 50 +++++------ src/sound/s_music.h | 4 +- 11 files changed, 222 insertions(+), 139 deletions(-) create mode 100644 libraries/zmusic/zmusic/zmusic_internal.h diff --git a/libraries/timidity/common.cpp b/libraries/timidity/common.cpp index f58b53543..53f099f6b 100644 --- a/libraries/timidity/common.cpp +++ b/libraries/timidity/common.cpp @@ -57,7 +57,7 @@ void *safe_malloc(size_t count) auto p = malloc(count); if (!p) { - std::terminate(); // we must abort, though... + abort(); // we must abort, though... } return p; #endif diff --git a/libraries/zmusic/midisources/midisource.cpp b/libraries/zmusic/midisources/midisource.cpp index 0fa3d0fdb..e696887d1 100644 --- a/libraries/zmusic/midisources/midisource.cpp +++ b/libraries/zmusic/midisources/midisource.cpp @@ -33,7 +33,7 @@ ** */ - +#include "zmusic/zmusic_internal.h" #include "midisource.h" @@ -418,7 +418,7 @@ extern int MUSHeaderSearch(const uint8_t *head, int len); // //========================================================================== -EMIDIType IdentifyMIDIType(uint32_t *id, int size) +EMIDIType ZMusic_IdentifyMIDIType(uint32_t *id, int size) { // Check for MUS format // Tolerate sloppy wads by searching up to 32 bytes for the header @@ -467,23 +467,39 @@ EMIDIType IdentifyMIDIType(uint32_t *id, int size) // //========================================================================== -MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype) +DLL_EXPORT ZMusic_MidiSource ZMusic_CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype) { - switch (miditype) + try { - case MIDI_MUS: - return new MUSSong2(data, length); + MIDISource* source; + switch (miditype) + { + case MIDI_MUS: + source = new MUSSong2(data, length); + break; - case MIDI_MIDI: - return new MIDISong2(data, length); + case MIDI_MIDI: + source = new MIDISong2(data, length); + break; - case MIDI_HMI: - return new HMISong(data, length); + case MIDI_HMI: + source = new HMISong(data, length); + break; - case MIDI_XMI: - return new XMISong(data, length); + case MIDI_XMI: + source = new XMISong(data, length); + break; - default: + default: + SetError("Unable to identify MIDI data"); + source = nullptr; + break; + } + return source; + } + catch (const std::exception & ex) + { + SetError(ex.what()); return nullptr; } } diff --git a/libraries/zmusic/musicformats/music_midi.cpp b/libraries/zmusic/musicformats/music_midi.cpp index 614081e89..8ff722978 100644 --- a/libraries/zmusic/musicformats/music_midi.cpp +++ b/libraries/zmusic/musicformats/music_midi.cpp @@ -37,6 +37,7 @@ #include #include #include +#include "zmusic/zmusic_internal.h" #include "zmusic/musinfo.h" #include "mididevices/mididevice.h" #include "midisources/midisource.h" @@ -1004,9 +1005,18 @@ MusInfo* CreateMIDIStreamer(MIDISource *source, EMidiDevice devtype, const char* return me; } -void MIDIDumpWave(MIDISource* source, EMidiDevice devtype, const char *devarg, const char *outname, int subsong, int samplerate) +DLL_EXPORT bool ZMusic_MIDIDumpWave(ZMusic_MidiSource source, EMidiDevice devtype, const char *devarg, const char *outname, int subsong, int samplerate) { - MIDIStreamer me(devtype, devarg); - me.SetMIDISource(source); - me.DumpWave(outname, subsong, samplerate); + try + { + MIDIStreamer me(devtype, devarg); + me.SetMIDISource(source); + me.DumpWave(outname, subsong, samplerate); + return true; + } + catch (const std::exception & ex) + { + SetError(ex.what()); + return false; + } } diff --git a/libraries/zmusic/zmusic/configuration.cpp b/libraries/zmusic/zmusic/configuration.cpp index 9a73e2880..b78deb0aa 100644 --- a/libraries/zmusic/zmusic/configuration.cpp +++ b/libraries/zmusic/zmusic/configuration.cpp @@ -37,7 +37,7 @@ #include "oplsynth/oplio.h" #include "../../libraries/dumb/include/dumb.h" -#include "zmusic.h" +#include "zmusic_internal.h" #include "musinfo.h" #include "midiconfig.h" @@ -54,25 +54,25 @@ struct Dummy MiscConfig miscConfig; Callbacks musicCallbacks; -void ZMusic_SetCallbacks(const Callbacks* cb) +DLL_EXPORT void ZMusic_SetCallbacks(const Callbacks* cb) { dumb_decode_vorbis = cb->DumbVorbisDecode; musicCallbacks = *cb; } -void ZMusic_SetGenMidi(const uint8_t* data) +DLL_EXPORT void ZMusic_SetGenMidi(const uint8_t* data) { memcpy(oplConfig.OPLinstruments, data, 175 * 36); oplConfig.genmidiset = true; } -void ZMusic_SetWgOpn(const void* data, unsigned len) +DLL_EXPORT void ZMusic_SetWgOpn(const void* data, unsigned len) { opnConfig.default_bank.resize(len); memcpy(opnConfig.default_bank.data(), data, len); } -void ZMusic_SetDmxGus(const void* data, unsigned len) +DLL_EXPORT void ZMusic_SetDmxGus(const void* data, unsigned len) { gusConfig.dmxgus.resize(len); memcpy(gusConfig.dmxgus.data(), data, len); diff --git a/libraries/zmusic/zmusic/zmusic.cpp b/libraries/zmusic/zmusic/zmusic.cpp index 7d6b18f8a..dbca55d9c 100644 --- a/libraries/zmusic/zmusic/zmusic.cpp +++ b/libraries/zmusic/zmusic/zmusic.cpp @@ -38,7 +38,7 @@ #include #include #include "m_swap.h" -#include "zmusic.h" +#include "zmusic_internal.h" #include "midiconfig.h" #include "musinfo.h" #include "streamsources/streamsource.h" @@ -157,6 +157,7 @@ MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, co if(reader->read(id, 32) != 32 || reader->seek(-32, SEEK_CUR) != 0) { + SetError("Unable to read header"); reader->close(); return nullptr; } @@ -190,16 +191,17 @@ MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, co } } - EMIDIType miditype = IdentifyMIDIType(id, sizeof(id)); + EMIDIType miditype = ZMusic_IdentifyMIDIType(id, sizeof(id)); if (miditype != MIDI_NOTMIDI) { std::vector data(reader->filelength()); if (reader->read(data.data(), (long)data.size()) != (long)data.size()) { + SetError("Failed to read MIDI data"); reader->close(); return nullptr; } - auto source = CreateMIDISource(data.data(), data.size(), miditype); + auto source = ZMusic_CreateMIDISource(data.data(), data.size(), miditype); if (source == nullptr) { reader->close(); @@ -207,6 +209,7 @@ MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, co } if (!source->isValid()) { + SetError("Invalid data in MIDI file"); delete source; return nullptr; } @@ -268,23 +271,26 @@ MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, co { // File could not be identified as music. if (reader) reader->close(); + SetError("Unable to identify as music"); return nullptr; } if (info && !info->IsValid()) { delete info; + SetError("Unable to identify as music"); info = nullptr; } + if (reader) reader->close(); + return info; } - catch (...) + catch (const std::exception &ex) { // Make sure the reader is closed if this function abnormally terminates if (reader) reader->close(); - throw; + SetError(ex.what()); + return nullptr; } - if (reader) reader->close(); - return info; } //========================================================================== @@ -293,7 +299,7 @@ MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, co // //========================================================================== -MusInfo *ZMusic_OpenCDSong (int track, int id) +DLL_EXPORT MusInfo *ZMusic_OpenCDSong (int track, int id) { MusInfo *info = CD_OpenSong (track, id); @@ -301,6 +307,7 @@ MusInfo *ZMusic_OpenCDSong (int track, int id) { delete info; info = nullptr; + SetError("Unable to open CD Audio"); } return info; @@ -312,7 +319,7 @@ MusInfo *ZMusic_OpenCDSong (int track, int id) // //========================================================================== -bool ZMusic_FillStream(MusInfo* song, void* buff, int len) +DLL_EXPORT bool ZMusic_FillStream(MusInfo* song, void* buff, int len) { if (song == nullptr) return false; std::lock_guard lock(song->CritSec); @@ -325,10 +332,19 @@ bool ZMusic_FillStream(MusInfo* song, void* buff, int len) // //========================================================================== -void ZMusic_Start(MusInfo *song, int subsong, bool loop) +DLL_EXPORT bool ZMusic_Start(MusInfo *song, int subsong, bool loop) { - if (!song) return; - song->Play(loop, subsong); + if (!song) return true; // Starting a null song is not an error! It just won't play anything. + try + { + song->Play(loop, subsong); + return true; + } + catch (const std::exception & ex) + { + SetError(ex.what()); + return false; + } } //========================================================================== @@ -337,51 +353,51 @@ void ZMusic_Start(MusInfo *song, int subsong, bool loop) // //========================================================================== -void ZMusic_Pause(MusInfo *song) +DLL_EXPORT void ZMusic_Pause(MusInfo *song) { if (!song) return; song->Pause(); } -void ZMusic_Resume(MusInfo *song) +DLL_EXPORT void ZMusic_Resume(MusInfo *song) { if (!song) return; song->Resume(); } -void ZMusic_Update(MusInfo *song) +DLL_EXPORT void ZMusic_Update(MusInfo *song) { if (!song) return; song->Update(); } -bool ZMusic_IsPlaying(MusInfo *song) +DLL_EXPORT bool ZMusic_IsPlaying(MusInfo *song) { if (!song) return false; return song->IsPlaying(); } -void ZMusic_Stop(MusInfo *song) +DLL_EXPORT void ZMusic_Stop(MusInfo *song) { if (!song) return; std::lock_guard lock(song->CritSec); song->Stop(); } -bool ZMusic_SetSubsong(MusInfo *song, int subsong) +DLL_EXPORT bool ZMusic_SetSubsong(MusInfo *song, int subsong) { if (!song) return false; std::lock_guard lock(song->CritSec); return song->SetSubsong(subsong); } -bool ZMusic_IsLooping(MusInfo *song) +DLL_EXPORT bool ZMusic_IsLooping(MusInfo *song) { if (!song) return false; return song->m_Looping; } -bool ZMusic_IsMIDI(MusInfo *song) +DLL_EXPORT bool ZMusic_IsMIDI(MusInfo *song) { if (!song) return false; return song->IsMIDI(); @@ -394,13 +410,13 @@ SoundStreamInfo ZMusic_GetStreamInfo(MusInfo *song) return song->GetStreamInfo(); } -void ZMusic_Close(MusInfo *song) +DLL_EXPORT void ZMusic_Close(MusInfo *song) { if (!song) return; delete song; } -void ZMusic_VolumeChanged(MusInfo *song) +DLL_EXPORT void ZMusic_VolumeChanged(MusInfo *song) { if (!song) return; std::lock_guard lock(song->CritSec); @@ -413,3 +429,28 @@ std::string ZMusic_GetStats(MusInfo *song) std::lock_guard lock(song->CritSec); return song->GetStats(); } + +static std::string staticErrorMessage; +void SetError(const char* msg) +{ + staticErrorMessage = msg; +} + +DLL_EXPORT const char* ZMusic_GetLastError() +{ + return staticErrorMessage.c_str(); +} + +DLL_EXPORT bool ZMusic_WriteSMF(MIDISource* source, const char *fn, int looplimit) +{ + std::vector midi; + bool success; + + if (!source) return false; + source->CreateSMF(midi, 1); + auto f = MusicIO::utf8_fopen(fn, "wt"); + if (f == nullptr) return false; + success = (fwrite(&midi[0], 1, midi.size(), f) == midi.size()); + delete f; + return success; +} diff --git a/libraries/zmusic/zmusic/zmusic.h b/libraries/zmusic/zmusic/zmusic.h index abb1f7d4c..e81495c8a 100644 --- a/libraries/zmusic/zmusic/zmusic.h +++ b/libraries/zmusic/zmusic/zmusic.h @@ -140,42 +140,63 @@ struct Callbacks }; -// Sets callbacks for functionality that the client needs to provide. -void ZMusic_SetCallbacks(const Callbacks *callbacks); -// Sets GenMidi data for OPL playback. If this isn't provided the OPL synth will not work. -void ZMusic_SetGenMidi(const uint8_t* data); -// Set default bank for OPN. Without this OPN only works with custom banks. -void ZMusic_SetWgOpn(const void* data, unsigned len); -// Set DMXGUS data for running the GUS synth in actual GUS mode. -void ZMusic_SetDmxGus(const void* data, unsigned len); -// These exports are needed by the MIDI dumpers which need to remain on the client side. -class MIDISource; // abstract for the client +#ifndef ZMUSIC_INTERNAL +#define DLL_IMPORT // _declspec(dllimport) +typedef struct { int zm1; } *ZMusic_MidiSource; +typedef struct { int zm2; } *ZMusic_MusicStream; +#endif + +extern "C" +{ + DLL_IMPORT const char* ZMusic_GetLastError(); + + // Sets callbacks for functionality that the client needs to provide. + DLL_IMPORT void ZMusic_SetCallbacks(const Callbacks* callbacks); + // Sets GenMidi data for OPL playback. If this isn't provided the OPL synth will not work. + DLL_IMPORT void ZMusic_SetGenMidi(const uint8_t* data); + // Set default bank for OPN. Without this OPN only works with custom banks. + DLL_IMPORT void ZMusic_SetWgOpn(const void* data, unsigned len); + // Set DMXGUS data for running the GUS synth in actual GUS mode. + DLL_IMPORT void ZMusic_SetDmxGus(const void* data, unsigned len); + + // These exports are needed by the MIDI dumpers which need to remain on the client side because the need access to the client's file system. + DLL_IMPORT EMIDIType ZMusic_IdentifyMIDIType(uint32_t* id, int size); + DLL_IMPORT ZMusic_MidiSource ZMusic_CreateMIDISource(const uint8_t* data, size_t length, EMIDIType miditype); + DLL_IMPORT bool ZMusic_MIDIDumpWave(ZMusic_MidiSource source, EMidiDevice devtype, const char* devarg, const char* outname, int subsong, int samplerate); + + DLL_IMPORT ZMusic_MusicStream ZMusic_OpenSong(MusicIO::FileInterface* reader, EMidiDevice device, const char* Args); + DLL_IMPORT ZMusic_MusicStream ZMusic_OpenCDSong(int track, int cdid = 0); + + DLL_IMPORT bool ZMusic_FillStream(ZMusic_MusicStream stream, void* buff, int len); + DLL_IMPORT bool ZMusic_Start(ZMusic_MusicStream song, int subsong, bool loop); + DLL_IMPORT void ZMusic_Pause(ZMusic_MusicStream song); + DLL_IMPORT void ZMusic_Resume(ZMusic_MusicStream song); + DLL_IMPORT void ZMusic_Update(ZMusic_MusicStream song); + DLL_IMPORT bool ZMusic_IsPlaying(ZMusic_MusicStream song); + DLL_IMPORT void ZMusic_Stop(ZMusic_MusicStream song); + DLL_IMPORT void ZMusic_Close(ZMusic_MusicStream song); + DLL_IMPORT bool ZMusic_SetSubsong(ZMusic_MusicStream song, int subsong); + DLL_IMPORT bool ZMusic_IsLooping(ZMusic_MusicStream song); + DLL_IMPORT bool ZMusic_IsMIDI(ZMusic_MusicStream song); + DLL_IMPORT void ZMusic_VolumeChanged(ZMusic_MusicStream song); + DLL_IMPORT bool ZMusic_WriteSMF(ZMusic_MidiSource source, const char* fn, int looplimit); + SoundStreamInfo ZMusic_GetStreamInfo(ZMusic_MusicStream 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. +} + class MusInfo; -EMIDIType IdentifyMIDIType(uint32_t *id, int size); -MIDISource *CreateMIDISource(const uint8_t *data, size_t length, EMIDIType miditype); -void MIDIDumpWave(MIDISource* source, EMidiDevice devtype, const char* devarg, const char* outname, int subsong, int samplerate); - -MusInfo *ZMusic_OpenSong (MusicIO::FileInterface *reader, EMidiDevice device, const char *Args); -MusInfo *ZMusic_OpenCDSong (int track, int cdid = 0); - -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); -bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, MusInfo* song, float value, float *pRealValue = nullptr); -bool ChangeMusicSetting(ZMusic::EStringConfigKey key, MusInfo* song, const char *value); +#if 0 +std::string ZMusic_GetStats(ZMusic_MusicStream song); +bool ChangeMusicSetting(ZMusic::EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue = nullptr); +bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, ZMusic_MusicStream song, float value, float* pRealValue = nullptr); +bool ChangeMusicSetting(ZMusic::EStringConfigKey key, ZMusic_MusicStream song, const char* value); +#else +// Cannot be done yet. +std::string ZMusic_GetStats(MusInfo* song); +bool ChangeMusicSetting(ZMusic::EIntConfigKey key, MusInfo* song, int value, int* pRealValue = nullptr); +bool ChangeMusicSetting(ZMusic::EFloatConfigKey key, MusInfo* song, float value, float* pRealValue = nullptr); +bool ChangeMusicSetting(ZMusic::EStringConfigKey key, MusInfo* song, const char* value); +#endif \ No newline at end of file diff --git a/libraries/zmusic/zmusic/zmusic_internal.h b/libraries/zmusic/zmusic/zmusic_internal.h new file mode 100644 index 000000000..5b7838239 --- /dev/null +++ b/libraries/zmusic/zmusic/zmusic_internal.h @@ -0,0 +1,11 @@ +#pragma once +#define ZMUSIC_INTERNAL + +#define DLL_EXPORT // __declspec(dllexport) +#define DLL_IMPORT +typedef class MIDISource *ZMusic_MidiSource; +typedef class MusInfo *ZMusic_MusicStream; + +#include "zmusic.h" + +void SetError(const char *text); diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index bef7fe307..b24cb8027 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -39,6 +39,7 @@ #include +#include "zmusic/zmusic.h" #include "m_argv.h" #include "w_wad.h" #include "c_dispatch.h" @@ -52,7 +53,6 @@ #include "i_soundfont.h" #include "s_music.h" #include "doomstat.h" -#include "zmusic/zmusic.h" #include "streamsources/streamsource.h" #include "filereadermusicinterface.h" #include "../libraries/zmusic/midisources/midisource.h" @@ -342,7 +342,7 @@ ADD_STAT(music) { if (mus_playing.handle != nullptr) { - return FString(ZMusic_GetStats(mus_playing.handle).c_str()); + return FString(ZMusic_GetStats((MusInfo*)mus_playing.handle).c_str()); } return "No song playing"; } @@ -353,7 +353,7 @@ ADD_STAT(music) // //========================================================================== -static MIDISource *GetMIDISource(const char *fn) +static ZMusic_MidiSource GetMIDISource(const char *fn) { FString src = fn; if (src.Compare("*") == 0) src = mus_playing.name; @@ -375,7 +375,7 @@ static MIDISource *GetMIDISource(const char *fn) Printf("Unable to read lump %s\n", src.GetChars()); return nullptr; } - auto type = IdentifyMIDIType(id, 32); + auto type = ZMusic_IdentifyMIDIType(id, 32); if (type == MIDI_NOTMIDI) { Printf("%s is not MIDI-based.\n", src.GetChars()); @@ -383,11 +383,11 @@ static MIDISource *GetMIDISource(const char *fn) } auto data = wlump.Read(); - auto source = CreateMIDISource(data.Data(), data.Size(), type); + auto source = ZMusic_CreateMIDISource(data.Data(), data.Size(), type); if (source == nullptr) { - Printf("%s is not MIDI-based.\n", src.GetChars()); + Printf("Unable to open %s: %s\n", src.GetChars(), ZMusic_GetLastError()); return nullptr; } return source; @@ -431,13 +431,9 @@ UNSAFE_CCMD (writewave) auto savedsong = mus_playing; S_StopMusic(true); if (dev == MDEV_DEFAULT && snd_mididevice >= 0) dev = MDEV_FLUIDSYNTH; // The Windows system synth cannot dump a wave. - try + if (!ZMusic_MIDIDumpWave(source, dev, argv.argc() < 6 ? nullptr : argv[6], argv[2], argv.argc() < 4 ? 0 : (int)strtol(argv[3], nullptr, 10), argv.argc() < 5 ? 0 : (int)strtol(argv[4], nullptr, 10))) { - MIDIDumpWave(source, dev, argv.argc() < 6 ? nullptr : argv[6], argv[2], argv.argc() < 4 ? 0 : (int)strtol(argv[3], nullptr, 10), argv.argc() < 5 ? 0 : (int)strtol(argv[4], nullptr, 10)); - } - catch (const std::runtime_error& err) - { - Printf("MIDI dump failed: %s\n", err.what()); + Printf("MIDI dump of %s failed: %s\n",argv[1], ZMusic_GetLastError()); } S_ChangeMusic(savedsong.name, savedsong.baseorder, savedsong.loop, true); @@ -467,23 +463,13 @@ UNSAFE_CCMD(writemidi) return; } auto source = GetMIDISource(argv[1]); - if (source == nullptr) return; - - std::vector midi; - bool success; - - source->CreateSMF(midi, 1); - auto f = FileWriter::Open(argv[2]); - if (f == nullptr) + if (source == nullptr) { - Printf("Could not open %s.\n", argv[2]); + Printf("Unable to open %s: %s\n", argv[1], ZMusic_GetLastError()); return; } - success = (f->Write(&midi[0], midi.size()) == midi.size()); - delete f; - - if (!success) + if (!ZMusic_WriteSMF(source, argv[1], 1)) { - Printf("Could not write to music file %s.\n", argv[2]); + Printf("Unable to write %s\n", argv[1]); } } diff --git a/src/sound/music/music_config.cpp b/src/sound/music/music_config.cpp index da6103b5c..ea57f8465 100644 --- a/src/sound/music/music_config.cpp +++ b/src/sound/music/music_config.cpp @@ -48,18 +48,18 @@ #define FORWARD_CVAR(key) \ decltype(*self) newval; \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle, *self, &newval); \ + auto ret = ChangeMusicSetting(ZMusic::key, (MusInfo*)mus_playing.handle, *self, &newval); \ self = (decltype(*self))newval; \ if (ret) S_MIDIDeviceChanged(-1); #define FORWARD_BOOL_CVAR(key) \ int newval; \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self, &newval); \ + auto ret = ChangeMusicSetting(ZMusic::key, (MusInfo*)mus_playing.handle,*self, &newval); \ self = !!newval; \ if (ret) S_MIDIDeviceChanged(-1); #define FORWARD_STRING_CVAR(key) \ - auto ret = ChangeMusicSetting(ZMusic::key, mus_playing.handle,*self); \ + auto ret = ChangeMusicSetting(ZMusic::key, (MusInfo*)mus_playing.handle,*self); \ if (ret) S_MIDIDeviceChanged(-1); diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp index b1fee6676..c09487e2c 100644 --- a/src/sound/s_music.cpp +++ b/src/sound/s_music.cpp @@ -171,7 +171,7 @@ void S_StopStream() // //========================================================================== -static void S_StartMusicPlaying(MusInfo* song, bool loop, float rel_vol, int subsong) +static bool S_StartMusicPlaying(ZMusic_MusicStream song, bool loop, float rel_vol, int subsong) { if (rel_vol > 0.f) { @@ -180,10 +180,14 @@ static void S_StartMusicPlaying(MusInfo* song, bool loop, float rel_vol, int sub I_SetRelativeVolume(saved_relative_volume * factor); } ZMusic_Stop(song); - ZMusic_Start(song, subsong, loop); + if (!ZMusic_Start(song, subsong, loop)) + { + return false; + } // Notify the sound system of the changed relative volume snd_musicvolume.Callback(); + return true; } @@ -418,15 +422,11 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } else if (!ZMusic_IsPlaying(mus_playing.handle)) { - try + if (!ZMusic_Start(mus_playing.handle, looping, order)) { - ZMusic_Start(mus_playing.handle, looping, order); - S_CreateStream(); - } - catch (const std::runtime_error& err) - { - Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); + Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError()); } + S_CreateStream(); } return true; @@ -444,12 +444,16 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } S_StopMusic (true); mus_playing.handle = ZMusic_OpenCDSong (track, id); + if (mus_playing.handle == nullptr) + { + Printf("Unable to start CD Audio for track #%d, ID %d\n", track, id); + } } else { int lumpnum = -1; int length = 0; - MusInfo *handle = nullptr; + ZMusic_MusicStream handle = nullptr; MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname); // Strip off any leading file:// component. @@ -504,14 +508,11 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } else { - try + auto mreader = new FileReaderMusicInterface(reader); + mus_playing.handle = ZMusic_OpenSong(mreader, devp? (EMidiDevice)devp->device : MDEV_DEFAULT, devp? devp->args.GetChars() : ""); + if (mus_playing.handle == nullptr) { - auto mreader = new FileReaderMusicInterface(reader); - mus_playing.handle = ZMusic_OpenSong(mreader, devp? (EMidiDevice)devp->device : MDEV_DEFAULT, devp? devp->args.GetChars() : ""); - } - catch (const std::runtime_error& err) - { - Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), err.what()); + Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError()); } } } @@ -523,16 +524,13 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) if (mus_playing.handle != 0) { // play it - try + if (!S_StartMusicPlaying(mus_playing.handle, looping, S_GetMusicVolume(musicname), order)) { - S_StartMusicPlaying(mus_playing.handle, looping, S_GetMusicVolume(musicname), order); - S_CreateStream(); - mus_playing.baseorder = order; - } - catch (const std::runtime_error& err) - { - Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); + Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError()); + return false; } + S_CreateStream(); + mus_playing.baseorder = order; return true; } return false; @@ -575,7 +573,7 @@ void S_RestartMusic () void S_MIDIDeviceChanged(int newdev) { - MusInfo* song = mus_playing.handle; + auto song = mus_playing.handle; if (song != nullptr && ZMusic_IsMIDI(song) && ZMusic_IsPlaying(song)) { // Reload the song to change the device diff --git a/src/sound/s_music.h b/src/sound/s_music.h index 76a079874..b70bbf8b2 100644 --- a/src/sound/s_music.h +++ b/src/sound/s_music.h @@ -28,6 +28,7 @@ #ifndef __S_MUSIC__ #define __S_MUSIC__ +#include "zmusic/zmusic.h" #include "doomtype.h" #include "i_soundinternal.h" @@ -78,11 +79,10 @@ typedef TMap MidiDeviceMap; extern MusicAliasMap MusicAliases; extern MidiDeviceMap MidiDevices; -class MusInfo; struct MusPlayingInfo { FString name; - MusInfo* handle; + ZMusic_MusicStream handle; int baseorder; bool loop; FString LastSong; // last music that was played