diff --git a/src/s_sound.h b/src/s_sound.h index 779bae295..4d67c0514 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -401,18 +401,6 @@ ReverbContainer *S_FindEnvironment (const char *name); ReverbContainer *S_FindEnvironment (int id); void S_AddEnvironment (ReverbContainer *settings); -enum EMidiDevice -{ - MDEV_DEFAULT = -1, - MDEV_MMAPI = 0, - MDEV_OPL = 1, - MDEV_SNDSYS = 2, - MDEV_TIMIDITY = 3, - MDEV_FLUIDSYNTH = 4, - MDEV_GUS = 5, - MDEV_WILDMIDI = 6, -}; - struct MidiDeviceSetting { int device; diff --git a/src/sound/i_music.h b/src/sound/i_music.h index 069d2f142..9939868a7 100644 --- a/src/sound/i_music.h +++ b/src/sound/i_music.h @@ -35,6 +35,7 @@ #define __I_MUSIC_H__ #include "doomdef.h" +#include "i_soundinternal.h" class FileReader; struct FOptionValues; @@ -77,6 +78,7 @@ public: virtual bool SetPosition (unsigned int ms); virtual bool SetSubsong (int subsong); virtual void Update(); + virtual int GetDeviceType() const { return MDEV_DEFAULT; } // MDEV_DEFAULT stands in for anything that cannot change playback parameters which needs a restart. virtual FString GetStats(); virtual MusInfo *GetOPLDumper(const char *filename); virtual MusInfo *GetWaveDumper(const char *filename, int rate); diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index 6cb2e05a2..596093a06 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -83,6 +83,7 @@ public: virtual void WildMidiSetOption(int opt, int set); virtual bool Preprocess(MIDIStreamer *song, bool looping); virtual FString GetStats(); + virtual int GetDeviceType() const { return MDEV_DEFAULT; } }; @@ -191,6 +192,7 @@ protected: void HandleLongEvent(const uint8_t *data, int len); void ComputeOutput(float *buffer, int len); bool ServiceStream(void *buff, int numbytes); + int GetDeviceType() const override { return MDEV_OPL; } }; // OPL dumper implementation of a MIDI output device ------------------------ @@ -217,6 +219,7 @@ public: int Open(MidiCallback, void *userdata); void PrecacheInstruments(const uint16_t *instruments, int count); FString GetStats(); + int GetDeviceType() const override { return MDEV_GUS; } protected: Timidity::Renderer *Renderer; @@ -251,6 +254,7 @@ public: int Open(MidiCallback, void *userdata); void PrecacheInstruments(const uint16_t *instruments, int count); FString GetStats(); + int GetDeviceType() const override { return MDEV_WILDMIDI; } protected: WildMidi_Renderer *Renderer; @@ -285,6 +289,7 @@ public: void FluidSettingInt(const char *setting, int value); void FluidSettingNum(const char *setting, double value); void FluidSettingStr(const char *setting, const char *value); + int GetDeviceType() const override { return MDEV_FLUIDSYNTH; } protected: void HandleEvent(int status, int parm1, int parm2); @@ -358,6 +363,7 @@ public: void WildMidiSetOption(int opt, int set); void CreateSMF(TArray &file, int looplimit=0); int ServiceEvent(); + int GetDeviceType() const override { return MIDI->GetDeviceType(); } protected: MIDIStreamer(const char *dumpname, EMidiDevice type); @@ -676,5 +682,6 @@ MusInfo *SndFile_OpenSong(FileReader &fr); // -------------------------------------------------------------------------- extern MusInfo *currSong; +void MIDIDeviceChanged(int newdev, bool force = false); EXTERN_CVAR (Float, snd_musicvolume) diff --git a/src/sound/i_soundinternal.h b/src/sound/i_soundinternal.h index bb154a195..f5f49f560 100644 --- a/src/sound/i_soundinternal.h +++ b/src/sound/i_soundinternal.h @@ -149,4 +149,17 @@ private: SoundDecoder& operator=(const SoundDecoder &rhs); }; +enum EMidiDevice +{ + MDEV_DEFAULT = -1, + MDEV_MMAPI = 0, + MDEV_OPL = 1, + MDEV_SNDSYS = 2, + MDEV_TIMIDITY = 3, + MDEV_FLUIDSYNTH = 4, + MDEV_GUS = 5, + MDEV_WILDMIDI = 6, +}; + + #endif diff --git a/src/sound/mididevices/music_fluidsynth_mididevice.cpp b/src/sound/mididevices/music_fluidsynth_mididevice.cpp index 711cf7480..47378ff56 100644 --- a/src/sound/mididevices/music_fluidsynth_mididevice.cpp +++ b/src/sound/mididevices/music_fluidsynth_mididevice.cpp @@ -103,7 +103,13 @@ extern "C" unsigned __stdcall GetSystemDirectoryA(char *lpBuffer, unsigned uSize CVAR(String, fluid_lib, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR(String, fluid_patchset, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(String, fluid_patchset, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_FLUIDSYNTH) + { + MIDIDeviceChanged(-1, true); + } +} CUSTOM_CVAR(Float, fluid_gain, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { diff --git a/src/sound/mididevices/music_timiditypp_mididevice.cpp b/src/sound/mididevices/music_timiditypp_mididevice.cpp index e2166c0a1..b6ba6997d 100644 --- a/src/sound/mididevices/music_timiditypp_mididevice.cpp +++ b/src/sound/mididevices/music_timiditypp_mididevice.cpp @@ -71,6 +71,7 @@ public: void Stop(); bool IsOpen(); void TimidityVolumeChanged(); + int GetDeviceType() const override { return MDEV_TIMIDITY; } protected: bool LaunchTimidity(); @@ -105,10 +106,17 @@ BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode); static char TimidityTitle[] = "TiMidity (" GAMENAME " Launched)"; const char TimidityPPMIDIDevice::EventName[] = "TiMidity Killer"; -CVAR (String, timidity_exe, "timidity.exe", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR (String, timidity_exe, "timidity.exe", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) #else -CVAR (String, timidity_exe, "timidity", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(String, timidity_exe, "timidity", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) #endif +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_TIMIDITY) + { + MIDIDeviceChanged(-1, true); + } +} + CVAR (String, timidity_extargs, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // extra args to pass to Timidity CVAR (String, timidity_chorus, "0", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, timidity_reverb, "0", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) diff --git a/src/sound/mididevices/music_wildmidi_mididevice.cpp b/src/sound/mididevices/music_wildmidi_mididevice.cpp index c446105a8..b3599d1e8 100644 --- a/src/sound/mididevices/music_wildmidi_mididevice.cpp +++ b/src/sound/mididevices/music_wildmidi_mididevice.cpp @@ -59,7 +59,14 @@ static FString CurrentConfig; // PUBLIC DATA DEFINITIONS ------------------------------------------------- -CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_WILDMIDI) + { + MIDIDeviceChanged(-1, true); + } +} + CVAR(Int, wildmidi_frequency, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index 20711d2a0..b7af50d6a 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -38,6 +38,9 @@ #include "c_dispatch.h" #include "i_music.h" #include "i_system.h" +#include "gameconfigfile.h" +#include "cmdlib.h" +#include "m_misc.h" #include "templates.h" #include "v_text.h" @@ -52,6 +55,42 @@ static bool nummididevicesset; #define NUM_DEF_DEVICES 5 #endif +//Provide some lists from which the user can choose the music resources in the menu instead of having to type them in manually +// These lists have to be maintained manually for the moment. +TArray SoundFonts; +TArray PatchSets; +TArray TimidityExes; + +static void ReadSoundFonts() +{ + const char *key, *value; + // Do not check for missing files here so that they will be saved back. + // Deletion should be done explicitly im the menu, equivalent to how the savegame menu works. + if (GameConfig->SetSection("SoundFonts")) + { + while (GameConfig->NextInSection(key, value)) + { + if (FileExists(value)) SoundFonts.Push(value); + } + } + if (GameConfig->SetSection("PatchSets")) + { + while (GameConfig->NextInSection(key, value)) + { + if (FileExists(value)) PatchSets.Push(value); + } + } +#ifdef _WIN32 // Different Timidity paths only make sense if they can be stored in arbitrary paths with local configs (i.e. not if things are done the Linux way) + if (GameConfig->SetSection("TimidityExes")) + { + while (GameConfig->NextInSection(key, value)) + { + if (FileExists(value)) PatchSets.Push(value); + } + } +#endif +} + static void AddDefaultMidiDevices(FOptionValues *opt) { int p; @@ -76,12 +115,12 @@ static void AddDefaultMidiDevices(FOptionValues *opt) } -static void MIDIDeviceChanged(int newdev) +void MIDIDeviceChanged(int newdev, bool force) { static int oldmididev = INT_MIN; // If a song is playing, move it to the new device. - if (oldmididev != newdev) + if (oldmididev != newdev || force) { if (currSong != NULL && currSong->IsMIDI()) { @@ -97,7 +136,8 @@ static void MIDIDeviceChanged(int newdev) S_MIDIDeviceChanged(); } } - oldmididev = newdev; + // 'force' + if (!force) oldmididev = newdev; } #ifdef _WIN32 diff --git a/src/sound/musicformats/music_opl.cpp b/src/sound/musicformats/music_opl.cpp index 0f949fae0..64596c2fb 100644 --- a/src/sound/musicformats/music_opl.cpp +++ b/src/sound/musicformats/music_opl.cpp @@ -53,7 +53,13 @@ CUSTOM_CVAR (Int, opl_numchips, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) } } -CVAR(Int, opl_core, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Int, opl_core, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr && currSong->GetDeviceType() == MDEV_OPL) + { + MIDIDeviceChanged(-1, true); + } +} int current_opl_core; // Get OPL core override from $mididevice diff --git a/src/sound/timidity/timidity.cpp b/src/sound/timidity/timidity.cpp index 86fe9d11d..a74d6baeb 100644 --- a/src/sound/timidity/timidity.cpp +++ b/src/sound/timidity/timidity.cpp @@ -32,6 +32,7 @@ #include "files.h" #include "w_wad.h" +// Unlike the other softsynths, this one cannot change its config data at run time. CVAR(String, midi_config, CONFIG_FILE, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, midi_voices, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(String, gus_patchdir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)