- 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.
This commit is contained in:
Christoph Oelckers 2020-01-01 20:01:38 +01:00
parent c24f9b42ba
commit 7923d25cce
11 changed files with 222 additions and 139 deletions

View file

@ -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

View file

@ -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)
{
try
{
MIDISource* source;
switch (miditype)
{
case MIDI_MUS:
return new MUSSong2(data, length);
source = new MUSSong2(data, length);
break;
case MIDI_MIDI:
return new MIDISong2(data, length);
source = new MIDISong2(data, length);
break;
case MIDI_HMI:
return new HMISong(data, length);
source = new HMISong(data, length);
break;
case MIDI_XMI:
return new XMISong(data, length);
source = new XMISong(data, length);
break;
default:
SetError("Unable to identify MIDI data");
source = nullptr;
break;
}
return source;
}
catch (const std::exception & ex)
{
SetError(ex.what());
return nullptr;
}
}

View file

@ -37,6 +37,7 @@
#include <string>
#include <algorithm>
#include <assert.h>
#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)
{
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;
}
}

View file

@ -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);

View file

@ -38,7 +38,7 @@
#include <string>
#include <zlib.h>
#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<uint8_t> 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;
}
}
catch (...)
{
// Make sure the reader is closed if this function abnormally terminates
if (reader) reader->close();
throw;
}
if (reader) reader->close();
return info;
}
catch (const std::exception &ex)
{
// Make sure the reader is closed if this function abnormally terminates
if (reader) reader->close();
SetError(ex.what());
return nullptr;
}
}
//==========================================================================
@ -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<std::mutex> 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;
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<std::mutex> 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<std::mutex> 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<std::mutex> lock(song->CritSec);
@ -413,3 +429,28 @@ std::string ZMusic_GetStats(MusInfo *song)
std::lock_guard<std::mutex> 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<uint8_t> 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;
}

View file

@ -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

View file

@ -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);

View file

@ -39,6 +39,7 @@
#include <zlib.h>
#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<uint8_t> 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]);
}
}

View file

@ -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);

View file

@ -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);
Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
}
S_CreateStream();
}
catch (const std::runtime_error& err)
{
Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what());
}
}
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.
@ -503,15 +507,12 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
mus_playing.handle = handle;
}
else
{
try
{
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)
if (mus_playing.handle == nullptr)
{
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);
Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
return false;
}
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());
}
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

View file

@ -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<FName, MidiDeviceSetting> 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