From eb124f616062c6933f727c10a6c1919ebcb22ed9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 26 Feb 2018 16:34:58 +0100 Subject: [PATCH] - made the sound font loading a bit more error resistant. - implemented a fallback both for sound font lookup and for MIDI device selection so that if some non-working combination is set up, the player will fall back to something that works. --- src/sound/i_soundfont.cpp | 8 ++ src/sound/i_soundinternal.h | 2 + .../music_fluidsynth_mididevice.cpp | 2 +- .../music_timiditypp_mididevice.cpp | 6 +- .../mididevices/music_wildmidi_mididevice.cpp | 5 ++ .../mididevices/music_win_mididevice.cpp | 3 +- src/sound/music_midi_base.cpp | 2 +- src/sound/musicformats/music_midistream.cpp | 74 ++++++++++++------- src/sound/timidity/instrum.cpp | 2 +- src/sound/timidity/timidity.cpp | 12 ++- 10 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/sound/i_soundfont.cpp b/src/sound/i_soundfont.cpp index 77e85be08..ab7e31907 100644 --- a/src/sound/i_soundfont.cpp +++ b/src/sound/i_soundfont.cpp @@ -390,6 +390,14 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all return &sfi; } } + // We did not find what we were looking for. Let's just return the first valid item that works with the given device. + for (auto &sfi : soundfonts) + { + if (allowed & sfi.type) + { + return &sfi; + } + } return nullptr; } diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index 3aced0400..e1ae80290 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -162,6 +162,8 @@ enum EMidiDevice MDEV_FLUIDSYNTH = 4, MDEV_GUS = 5, MDEV_WILDMIDI = 6, + + MDEV_COUNT }; class MusInfo; diff --git a/src/sound/mididevices/music_fluidsynth_mididevice.cpp b/src/sound/mididevices/music_fluidsynth_mididevice.cpp index 90cb2ba67..3f87c8107 100644 --- a/src/sound/mididevices/music_fluidsynth_mididevice.cpp +++ b/src/sound/mididevices/music_fluidsynth_mididevice.cpp @@ -357,9 +357,9 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(const char *args) #endif - Printf("Failed to load any MIDI patches.\n"); delete_fluid_synth(FluidSynth); FluidSynth = NULL; + I_Error("Failed to load any MIDI patches.\n"); } diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index 276dd42d5..3770b9428 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -32,8 +32,6 @@ ** */ -#include "i_midi_win32.h" - #include #include @@ -130,6 +128,10 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args) { Renderer = new TimidityPlus::Player(timidity_frequency, instruments); } + else + { + I_Error("Failed to load any MIDI patches"); + } sampletime = 0; } diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index a14af5149..2a71f1c7e 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -40,6 +40,7 @@ #include "m_swap.h" #include "w_wad.h" #include "v_text.h" +#include "i_system.h" // MACROS ------------------------------------------------------------------ @@ -123,6 +124,10 @@ WildMIDIDevice::WildMIDIDevice(const char *args) if (wildmidi_reverb) flags |= WM_MO_REVERB; Renderer->SetOption(WM_MO_ENHANCED_RESAMPLING | WM_MO_REVERB, flags); } + else + { + I_Error("Failed to load any MIDI patches"); + } } //========================================================================== diff --git a/src/sound/mididevices/music_win_mididevice.cpp b/src/sound/mididevices/music_win_mididevice.cpp index d75a20de2..2e1a4c5a9 100644 --- a/src/sound/mididevices/music_win_mididevice.cpp +++ b/src/sound/mididevices/music_win_mididevice.cpp @@ -42,6 +42,7 @@ #include "templates.h" #include "doomdef.h" #include "m_swap.h" +#include "i_system.h" #ifndef __GNUC__ #include @@ -682,7 +683,7 @@ MIDIDevice *CreateWinMIDIDevice(int mididevice) if (d->BufferDoneEvent == nullptr || d->ExitEvent == nullptr) { delete d; - return nullptr; + I_Error("failed to create MIDI events"); } return d; } diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index 33c36842a..8b94c6903 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -126,7 +126,7 @@ CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) return; } else if (self == -1) self = DEF_MIDIDEV; - mididevice = MAX(0, self); + mididevice = MAX(0, self); MIDIDeviceChanged(self); } diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index 989dc6af7..db610e23f 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -183,42 +183,60 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) { // fixme: This should check up front if the device can be started. // Checks to ensure that a device finds a compatible sound font are entirely missing here. + bool checked[MDEV_COUNT] = { false }; - switch (devtype) + if (devtype == MDEV_SNDSYS) devtype = MDEV_FLUIDSYNTH; + while (true) { - case MDEV_GUS: - return new TimidityMIDIDevice(Args); - - case MDEV_MMAPI: -#ifdef _WIN32 - return CreateWinMIDIDevice(mididevice); -#endif - // Intentional fall-through for non-Windows systems. - - case MDEV_FLUIDSYNTH: - case MDEV_SNDSYS: - return new FluidSynthMIDIDevice(Args); - - case MDEV_OPL: try { - return new OPLMIDIDevice(Args); + switch (devtype) + { + case MDEV_GUS: + return new TimidityMIDIDevice(Args); + + case MDEV_MMAPI: +#ifdef _WIN32 + return CreateWinMIDIDevice(mididevice); +#endif + // Intentional fall-through for non-Windows systems. + + case MDEV_FLUIDSYNTH: + return new FluidSynthMIDIDevice(Args); + + case MDEV_OPL: + return new OPLMIDIDevice(Args); + + case MDEV_TIMIDITY: + return CreateTimidityPPMIDIDevice(Args); + + case MDEV_WILDMIDI: + return new WildMIDIDevice(Args); + + default: + break; + } } catch (CRecoverableError &err) { - // The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found. - Printf("Unable to create OPL MIDI device: %s\nFalling back to default playback", err.GetMessage()); - return new FluidSynthMIDIDevice(nullptr); + checked[devtype] = true; + devtype = MDEV_DEFAULT; + // Opening the requested device did not work out so choose another one. + if (!checked[MDEV_FLUIDSYNTH]) devtype = MDEV_FLUIDSYNTH; + else if (!checked[MDEV_TIMIDITY]) devtype = MDEV_TIMIDITY; + else if (!checked[MDEV_WILDMIDI]) devtype = MDEV_WILDMIDI; + else if (!checked[MDEV_GUS]) devtype = MDEV_GUS; +#ifdef _WIN32 + else if (!checked[MDEV_MMAPI]) devtype = MDEV_MMAPI; +#endif + else if (!checked[MDEV_OPL]) devtype = MDEV_OPL; + + if (devtype == MDEV_DEFAULT) + { + Printf("Failed to play music: Unable to open any MIDI Device."); + return nullptr; + } } - - case MDEV_TIMIDITY: - return CreateTimidityPPMIDIDevice(Args); - - case MDEV_WILDMIDI: - return new WildMIDIDevice(Args); - - default: - return NULL; } } diff --git a/src/sound/timidity/instrum.cpp b/src/sound/timidity/instrum.cpp index b804433bd..d92f7eb81 100644 --- a/src/sound/timidity/instrum.cpp +++ b/src/sound/timidity/instrum.cpp @@ -161,7 +161,7 @@ static Instrument *load_instrument(Renderer *song, const char *name, int percuss int i, j; bool noluck = false; - if (!name) return 0; + if (!name || gus_sfreader == nullptr) return nullptr; /* Open patch file */ fp = gus_sfreader->LookupFile(name).first; diff --git a/src/sound/timidity/timidity.cpp b/src/sound/timidity/timidity.cpp index 2aa3432bb..455ed1713 100644 --- a/src/sound/timidity/timidity.cpp +++ b/src/sound/timidity/timidity.cpp @@ -720,15 +720,21 @@ void FreeDLS(DLS_Data *data); Renderer::Renderer(float sample_rate, const char *args) { + int res = 0; // Load explicitly stated sound font if so desired. if (args != nullptr && *args != 0) { - if (!stricmp(args, "DMXGUS")) LoadDMXGUS(); - LoadConfig(args); + if (!stricmp(args, "DMXGUS")) res = LoadDMXGUS(); + res = LoadConfig(args); } else if (tonebank[0] == nullptr) { - LoadConfig(); + res = LoadConfig(); + } + + if (res < 0) + { + I_Error("Failed to load any MIDI patches"); } // These can be left empty here if an error occured during sound font initialization.