diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp index 172aaf806..58cc93aa0 100644 --- a/source/common/menu/menudef.cpp +++ b/source/common/menu/menudef.cpp @@ -46,6 +46,8 @@ #include "cmdlib.h" #include "c_cvars.h" #include "optionmenuitems.h" +#include "i_soundfont.h" +#include "zmusic/zmusic.h" // Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded. FString gSkillNames[MAXSKILLS]; @@ -61,7 +63,9 @@ static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common setti FOptionMenuSettings OptionSettings; FOptionMap OptionValues; +void I_BuildMIDIMenuList(FOptionValues* opt); void I_BuildALDeviceList(FOptionValues *opt); +void I_BuildALResamplersList(FOptionValues* opt); static void DeinitMenus() { @@ -1393,6 +1397,55 @@ static void InitCrosshairsList() #endif } +//============================================================================= +// +// Initialize the music configuration submenus +// +//============================================================================= +extern "C" +{ + extern int adl_getBanksCount(); + extern const char* const* adl_getBankNames(); +} + +static void InitMusicMenus() +{ + FMenuDescriptor** advmenu = MenuDescriptors.CheckKey(NAME_AdvSoundOptions); + auto soundfonts = sfmanager.GetList(); + std::tuple sfmenus[] = { + std::make_tuple("TimidityConfigMenu", SF_SF2 | SF_GUS, "timidity_config"), + std::make_tuple("FluidPatchsetMenu", SF_SF2, "fluid_patchset") }; + + for (auto& p : sfmenus) + { + FMenuDescriptor** menu = MenuDescriptors.CheckKey(std::get<0>(p)); + + if (menu != nullptr) + { + if (soundfonts.Size() > 0) + { + for (auto& entry : soundfonts) + { + if (entry.type & std::get<1>(p)) + { + FString display = entry.mName; + display.ReplaceChars("_", ' '); + auto it = new FOptionMenuItemCommand (display, FStringf("%s \"%s\"", std::get<2>(p), entry.mName.GetChars())/*, true*/); + static_cast(*menu)->mItems.Push(it); + } + } + } + else if (advmenu != nullptr) + { + // Remove the item for this submenu + auto d = static_cast(*advmenu); + auto it = d->GetItem(std::get<0>(p)); + if (it != nullptr) d->mItems.Delete(d->mItems.Find(it)); + } + } + } +} + //============================================================================= // // Special menus will be created once all engine data is loaded @@ -1403,19 +1456,23 @@ void M_CreateMenus() { BuildEpisodeMenu(); InitCrosshairsList(); + InitMusicMenus(); -#if 0 - FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices); - if (opt != NULL) + FOptionValues** opt = OptionValues.CheckKey(NAME_Mididevices); + if (opt != nullptr) { I_BuildMIDIMenuList(*opt); } opt = OptionValues.CheckKey(NAME_Aldevices); - if (opt != NULL) + if (opt != nullptr) { I_BuildALDeviceList(*opt); } -#endif + opt = OptionValues.CheckKey(NAME_Alresamplers); + if (opt != nullptr) + { + I_BuildALResamplersList(*opt); + } } //============================================================================= diff --git a/source/common/music/backend/oalsound.cpp b/source/common/music/backend/oalsound.cpp index ff8afc2f0..5506e445b 100644 --- a/source/common/music/backend/oalsound.cpp +++ b/source/common/music/backend/oalsound.cpp @@ -43,6 +43,7 @@ #include "cmdlib.h" #include "c_cvars.h" #include "printf.h" +#include "menu.h" #include "zmusic/sounddecoder.h" #include "filereadermusicinterface.h" @@ -96,7 +97,6 @@ bool IsOpenALPresent() -#if 0 void I_BuildALDeviceList(FOptionValues *opt) { opt->mValues.Resize(1); @@ -148,7 +148,6 @@ void I_BuildALResamplersList(FOptionValues *opt) } #endif } -#endif ReverbContainer *ForcedEnvironment; diff --git a/source/common/music/i_music.cpp b/source/common/music/i_music.cpp index 23547764a..dd4093b1f 100644 --- a/source/common/music/i_music.cpp +++ b/source/common/music/i_music.cpp @@ -226,7 +226,7 @@ static void SetupGenMidi() { // The OPL renderer should not care about where this comes from. // Note: No I_Error here - this needs to be consistent with the rest of the music code. - auto lump = fileSystem.FindFile("demolition/genmidi.dat"); + auto lump = fileSystem.FindFile("demolition/genmidi.op2"); if (lump < 0) { Printf("No GENMIDI lump found. OPL playback not available."); diff --git a/source/common/music/music_config.cpp b/source/common/music/music_config.cpp index e28875606..2f8cc98ab 100644 --- a/source/common/music/music_config.cpp +++ b/source/common/music/music_config.cpp @@ -74,7 +74,7 @@ CUSTOM_CVAR(String, fluid_lib, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTU FORWARD_STRING_CVAR(fluid_lib); } -CUSTOM_CVAR(String, fluid_patchset, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, fluid_patchset, "demolition", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(fluid_patchset); } @@ -273,7 +273,7 @@ CUSTOM_CVAR(Float, min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CV FORWARD_CVAR(min_sustain_time); } -CUSTOM_CVAR(String, timidity_config, "gzdoom", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, timidity_config, "demolition", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) { FORWARD_STRING_CVAR(timidity_config); } diff --git a/source/common/music/music_midi_base.cpp b/source/common/music/music_midi_base.cpp index 02bf631f9..6c1b615f1 100644 --- a/source/common/music/music_midi_base.cpp +++ b/source/common/music/music_midi_base.cpp @@ -33,32 +33,150 @@ #define DEF_MIDIDEV -5 -static uint32_t nummididevices; -#define NUM_DEF_DEVICES 7 +#define NUM_DEF_DEVICES 3 #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include - -void I_InitMusicWin32 () -{ - nummididevices = midiOutGetNumDevs (); -} - - #endif #include "c_dispatch.h" #include "v_text.h" +#include "menu/menu.h" #include "zmusic/zmusic.h" #include "s_music.h" #include "c_cvars.h" #include "printf.h" EXTERN_CVAR(Int, snd_mididevice) +static uint32_t nummididevices; + + +static void AddDefaultMidiDevices(FOptionValues *opt) +{ + FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(NUM_DEF_DEVICES)]; + pair[0].Text = "FluidSynth"; + pair[0].Value = -5.0; + pair[1].Text = "TiMidity++"; + pair[1].Value = -2.0; + pair[2].Text = "OPL Synth Emulation"; + pair[2].Value = -3.0; + +} + +#ifdef _WIN32 + +void I_InitMusicWin32 () +{ + nummididevices = midiOutGetNumDevs (); +} + +void I_BuildMIDIMenuList (FOptionValues *opt) +{ + AddDefaultMidiDevices(opt); + + for (uint32_t id = 0; id < nummididevices; ++id) + { + MIDIOUTCAPS caps; + MMRESULT res; + + res = midiOutGetDevCaps (id, &caps, sizeof(caps)); + assert(res == MMSYSERR_NOERROR); + if (res == MMSYSERR_NOERROR) + { + FOptionValues::Pair *pair = &opt->mValues[opt->mValues.Reserve(1)]; + pair->Text = caps.szPname; + pair->Value = (float)id; + } + } +} + +static void PrintMidiDevice (int id, const char *name, uint16_t tech, uint32_t support) +{ + if (id == snd_mididevice) + { + Printf (TEXTCOLOR_BOLD); + } + Printf ("% 2d. %s : ", id, name); + switch (tech) + { + case MIDIDEV_MIDIPORT: Printf ("MIDIPORT"); break; + case MIDIDEV_SYNTH: Printf ("SYNTH"); break; + case MIDIDEV_SQSYNTH: Printf ("SQSYNTH"); break; + case MIDIDEV_FMSYNTH: Printf ("FMSYNTH"); break; + case MIDIDEV_MAPPER: Printf ("MAPPER"); break; + case MIDIDEV_WAVETABLE: Printf ("WAVETABLE"); break; + case MIDIDEV_SWSYNTH: Printf ("SWSYNTH"); break; + } + if (support & MIDICAPS_CACHE) + { + Printf (" CACHE"); + } + if (support & MIDICAPS_LRVOLUME) + { + Printf (" LRVOLUME"); + } + if (support & MIDICAPS_STREAM) + { + Printf (" STREAM"); + } + if (support & MIDICAPS_VOLUME) + { + Printf (" VOLUME"); + } + Printf (TEXTCOLOR_NORMAL "\n"); +} + +CCMD (snd_listmididevices) +{ + UINT id; + MIDIOUTCAPS caps; + MMRESULT res; + + PrintMidiDevice(-8, "libOPN", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice(-7, "libADL", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice (-6, "WildMidi", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-5, "FluidSynth", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-4, "Gravis Ultrasound Emulation", MIDIDEV_SWSYNTH, 0); + PrintMidiDevice (-3, "Emulated OPL FM Synth", MIDIDEV_FMSYNTH, 0); + PrintMidiDevice (-2, "TiMidity++", MIDIDEV_SWSYNTH, 0); + if (nummididevices != 0) + { + for (id = 0; id < nummididevices; ++id) + { + FString text; + res = midiOutGetDevCaps (id, &caps, sizeof(caps)); + if (res == MMSYSERR_NODRIVER) + text = ""; + else if (res == MMSYSERR_NOMEM) + text = ""; + else if (res == MMSYSERR_NOERROR) + text = caps.szPname; + else + continue; + + PrintMidiDevice (id, text, caps.wTechnology, caps.dwSupport); + } + } +} + +#else + +void I_BuildMIDIMenuList (FOptionValues *opt) +{ + AddDefaultMidiDevices(opt); +} + +CCMD (snd_listmididevices) +{ + Printf("%s-5. FluidSynth\n", -5 == snd_mididevice ? TEXTCOLOR_BOLD : ""); + Printf("%s-3. Emulated OPL FM Synth\n", -3 == snd_mididevice ? TEXTCOLOR_BOLD : ""); + Printf("%s-2. TiMidity++\n", -2 == snd_mididevice ? TEXTCOLOR_BOLD : ""); +} +#endif CUSTOM_CVAR (Int, snd_mididevice, DEF_MIDIDEV, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) diff --git a/source/common/utility/namedef.h b/source/common/utility/namedef.h index ffd9c8978..3fdb641b3 100644 --- a/source/common/utility/namedef.h +++ b/source/common/utility/namedef.h @@ -40,3 +40,7 @@ xx(StartGame) xx(ImageScroller) xx(QuitMenu) xx(EndgameMenu) +xx(Mididevices) +xx(Aldevices) +xx(Alresamplers) +xx(AdvSoundOptions) \ No newline at end of file diff --git a/wadsrc/static/demolition/GENMIDI.op2 b/wadsrc/static/demolition/GENMIDI.op2 new file mode 100644 index 000000000..5c86b7787 Binary files /dev/null and b/wadsrc/static/demolition/GENMIDI.op2 differ