- added user configurable menus where soundfonts, patch sets or Timidity EXEs can be selected from lists being stored in the config file to reduce the hassle of testing MIDIs with different settings.

This commit is contained in:
Christoph Oelckers 2017-04-18 16:42:28 +02:00
parent fb12c58533
commit 8180d34765
9 changed files with 167 additions and 54 deletions

View file

@ -1165,6 +1165,17 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
return (DMenuItemBase*)p; return (DMenuItemBase*)p;
} }
DMenuItemBase * CreateOptionMenuItemCommand(const char *label, FName cmd, bool centered)
{
auto c = PClass::FindClass("OptionMenuItemCommand");
auto p = c->CreateNew();
FString namestr = label;
VMValue params[] = { p, &namestr, cmd.GetIndex(), centered };
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
return (DMenuItemBase*)p;
}
DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param) DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param)
{ {
auto c = PClass::FindClass("ListMenuItemPatchItem"); auto c = PClass::FindClass("ListMenuItemPatchItem");

View file

@ -355,5 +355,6 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy); DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy);
DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param); DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param);
DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param); DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param);
DMenuItemBase * CreateOptionMenuItemCommand(const char *label, FName cmd, bool centered = false);
#endif #endif

View file

@ -53,6 +53,7 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "vm.h" #include "vm.h"
#include "types.h" #include "types.h"
#include "gameconfigfile.h"
@ -1283,6 +1284,93 @@ static void InitCrosshairsList()
} }
} }
//=============================================================================
//
// Initialize the music configuration submenus
//
//=============================================================================
static void InitMusicMenus()
{
DMenuDescriptor **advmenu = MenuDescriptors.CheckKey("AdvSoundOptions");
DMenuDescriptor **gusmenu = MenuDescriptors.CheckKey("GusConfigMenu");
DMenuDescriptor **timiditymenu = MenuDescriptors.CheckKey("TimidityExeMenu");
DMenuDescriptor **wildmidimenu = MenuDescriptors.CheckKey("WildMidiConfigMenu");
DMenuDescriptor **fluidmenu = MenuDescriptors.CheckKey("FluidPatchsetMenu");
const char *key, *value;
if (GameConfig->SetSection("SoundFonts"))
{
while (GameConfig->NextInSection(key, value))
{
if (FileExists(value))
{
if (fluidmenu != nullptr)
{
auto it = CreateOptionMenuItemCommand(key, FStringf("fluid_patchset %s", NicePath(value)), true);
static_cast<DOptionMenuDescriptor*>(*fluidmenu)->mItems.Push(it);
}
}
}
}
else if (advmenu != nullptr)
{
// Remove the item for this submenu
auto d = static_cast<DOptionMenuDescriptor*>(*advmenu);
auto it = d->GetItem("FluidPatchsetMenu");
if (it != nullptr) d->mItems.Delete(d->mItems.Find(it));
}
if (GameConfig->SetSection("PatchSets"))
{
while (GameConfig->NextInSection(key, value))
{
if (FileExists(value))
{
if (gusmenu != nullptr)
{
auto it = CreateOptionMenuItemCommand(key, FStringf("midi_config %s", NicePath(value)), true);
static_cast<DOptionMenuDescriptor*>(*gusmenu)->mItems.Push(it);
}
if (wildmidimenu != nullptr)
{
auto it = CreateOptionMenuItemCommand(key, FStringf("wildmidi_config %s", NicePath(value)), true);
static_cast<DOptionMenuDescriptor*>(*wildmidimenu)->mItems.Push(it);
}
}
}
}
else if (advmenu != nullptr)
{
// Remove the item for this submenu
auto d = static_cast<DOptionMenuDescriptor*>(*advmenu);
auto it = d->GetItem("GusConfigMenu");
if (it != nullptr) d->mItems.Delete(d->mItems.Find(it));
it = d->GetItem("WildMidiConfigMenu");
if (it != nullptr) d->mItems.Delete(d->mItems.Find(it));
}
#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))
{
if (timiditymenu != nullptr)
{
auto it = CreateOptionMenuItemCommand(key, FStringf("timidity_exe %s", NicePath(value)), true);
static_cast<DOptionMenuDescriptor*>(*timiditymenu)->mItems.Push(it);
}
}
}
}
else
{
auto d = static_cast<DOptionMenuDescriptor*>(*advmenu);
auto it = d->GetItem("TimidityExeMenu");
if (it != nullptr) d->mItems.Delete(d->mItems.Find(it));
}
#endif
}
//============================================================================= //=============================================================================
// //
// With the current workings of the menu system this cannot be done any longer // With the current workings of the menu system this cannot be done any longer
@ -1332,6 +1420,7 @@ void M_CreateMenus()
BuildEpisodeMenu(); BuildEpisodeMenu();
BuildPlayerclassMenu(); BuildPlayerclassMenu();
InitCrosshairsList(); InitCrosshairsList();
InitMusicMenus();
InitKeySections(); InitKeySections();
FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices); FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices);

View file

@ -109,14 +109,6 @@
// TYPES ------------------------------------------------------------------- // TYPES -------------------------------------------------------------------
struct MusPlayingInfo
{
FString name;
MusInfo *handle;
int baseorder;
bool loop;
};
enum enum
{ {
SOURCE_None, // Sound is always on top of the listener. SOURCE_None, // Sound is always on top of the listener.
@ -151,7 +143,7 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor);
static bool SoundPaused; // whether sound is paused static bool SoundPaused; // whether sound is paused
static bool MusicPaused; // whether music is paused static bool MusicPaused; // whether music is paused
static MusPlayingInfo mus_playing; // music currently being played MusPlayingInfo mus_playing; // music currently being played
static FString LastSong; // last music that was played static FString LastSong; // last music that was played
static FPlayList *PlayList; static FPlayList *PlayList;
static int RestartEvictionsAt; // do not restart evicted channels before this level.time static int RestartEvictionsAt; // do not restart evicted channels before this level.time

View file

@ -3,7 +3,7 @@
#include <stdio.h> #include <stdio.h>
#include "basictypes.h" #include "doomtype.h"
#include "vectors.h" #include "vectors.h"
#include "tarray.h" #include "tarray.h"
@ -161,5 +161,15 @@ enum EMidiDevice
MDEV_WILDMIDI = 6, MDEV_WILDMIDI = 6,
}; };
class MusInfo;
struct MusPlayingInfo
{
FString name;
MusInfo *handle;
int baseorder;
bool loop;
};
#endif #endif

View file

@ -41,6 +41,7 @@
#include "gameconfigfile.h" #include "gameconfigfile.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "m_misc.h" #include "m_misc.h"
#include "s_sound.h"
#include "templates.h" #include "templates.h"
#include "v_text.h" #include "v_text.h"
@ -55,42 +56,6 @@ static bool nummididevicesset;
#define NUM_DEF_DEVICES 5 #define NUM_DEF_DEVICES 5
#endif #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<FString> SoundFonts;
TArray<FString> PatchSets;
TArray<FString> 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) static void AddDefaultMidiDevices(FOptionValues *opt)
{ {
int p; int p;
@ -115,6 +80,8 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
} }
extern MusPlayingInfo mus_playing;
void MIDIDeviceChanged(int newdev, bool force) void MIDIDeviceChanged(int newdev, bool force)
{ {
static int oldmididev = INT_MIN; static int oldmididev = INT_MIN;
@ -127,8 +94,18 @@ void MIDIDeviceChanged(int newdev, bool force)
MusInfo *song = currSong; MusInfo *song = currSong;
if (song->m_Status == MusInfo::STATE_Playing) if (song->m_Status == MusInfo::STATE_Playing)
{ {
song->Stop(); if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force)
song->Start(song->m_Looping); {
// FluidSynth must reload the song to change the patch set.
auto mi = mus_playing;
S_StopMusic(true);
S_ChangeMusic(mi.name, mi.baseorder, mi.loop);
}
else
{
song->Stop();
song->Start(song->m_Looping);
}
} }
} }
else else

View file

@ -2161,6 +2161,7 @@ ADVSNDMNU_TIMIDITYCHORUS = "Chorus";
ADVSNDMNU_TIMIDITYVOLUME = "Relative volume"; ADVSNDMNU_TIMIDITYVOLUME = "Relative volume";
ADVSNDMNU_WILDMIDI = "WildMidi"; ADVSNDMNU_WILDMIDI = "WildMidi";
ADVSNDMNU_WILDMIDICONFIG = "WildMidi config file"; ADVSNDMNU_WILDMIDICONFIG = "WildMidi config file";
ADVSNDMNU_SELCONFIG = "Select configuration";
// Module Replayer Options // Module Replayer Options
MODMNU_TITLE = "MODULE REPLAYER OPTIONS"; MODMNU_TITLE = "MODULE REPLAYER OPTIONS";

View file

@ -1637,12 +1637,14 @@ OptionMenu AdvSoundOptions
StaticText " " StaticText " "
StaticText "$ADVSNDMNU_GUSEMULATION", 1 StaticText "$ADVSNDMNU_GUSEMULATION", 1
TextField "$ADVSNDMNU_GUSCONFIG", "midi_config" TextField "$ADVSNDMNU_GUSCONFIG", "midi_config"
SubMenu "$ADVSNDMNU_SELCONFIG", "GusConfigMenu"
Slider "$ADVSNDMNU_MIDIVOICES", "midi_voices", 16, 256, 4, 0 Slider "$ADVSNDMNU_MIDIVOICES", "midi_voices", 16, 256, 4, 0
Option "$ADVSNDMNU_DMXGUS", "midi_dmxgus", "OnOff" Option "$ADVSNDMNU_DMXGUS", "midi_dmxgus", "OnOff"
Option "$ADVSNDMNU_GUSMEMSIZE", "gus_memsize", "GusMemory" Option "$ADVSNDMNU_GUSMEMSIZE", "gus_memsize", "GusMemory"
StaticText " " StaticText " "
StaticText "$ADVSNDMNU_FLUIDSYNTH", 1 StaticText "$ADVSNDMNU_FLUIDSYNTH", 1
TextField "$ADVSNDMNU_FLUIDPATCHSET", "fluid_patchset" TextField "$ADVSNDMNU_FLUIDPATCHSET", "fluid_patchset"
SubMenu "$ADVSNDMNU_SELCONFIG", "FluidPatchsetMenu"
Slider "$ADVSNDMNU_FLUIDGAIN", "fluid_gain", 0, 10, 0.5, 1 Slider "$ADVSNDMNU_FLUIDGAIN", "fluid_gain", 0, 10, 0.5, 1
Option "$ADVSNDMNU_REVERB", "fluid_reverb", "OnOff" Option "$ADVSNDMNU_REVERB", "fluid_reverb", "OnOff"
Slider "$ADVSNDMNU_FLUIDVOICES", "fluid_voices", 16, 4096, 16, 1 Slider "$ADVSNDMNU_FLUIDVOICES", "fluid_voices", 16, 4096, 16, 1
@ -1650,15 +1652,40 @@ OptionMenu AdvSoundOptions
StaticText " " StaticText " "
StaticText "$ADVSNDMNU_TIMIDITY", 1 StaticText "$ADVSNDMNU_TIMIDITY", 1
TextField "$ADVSNDMNU_TIMIDITYEXE", "timidity_exe" TextField "$ADVSNDMNU_TIMIDITYEXE", "timidity_exe"
IfOption(Windows)
{
SubMenu "$ADVSNDMNU_SELCONFIG", "TimidityExeMenu"
}
Option "$ADVSNDMNU_REVERB", "timidity_reverb", "OnOff" Option "$ADVSNDMNU_REVERB", "timidity_reverb", "OnOff"
Option "$ADVSNDMNU_TIMIDITYCHORUS", "timidity_chorus", "OnOff" Option "$ADVSNDMNU_TIMIDITYCHORUS", "timidity_chorus", "OnOff"
Slider "$ADVSNDMNU_TIMIDITYVOLUME", "timidity_mastervolume", 0, 4, 0.2, 1 Slider "$ADVSNDMNU_TIMIDITYVOLUME", "timidity_mastervolume", 0, 4, 0.2, 1
StaticText " " StaticText " "
StaticText "$ADVSNDMNU_WILDMIDI", 1 StaticText "$ADVSNDMNU_WILDMIDI", 1
TextField "$ADVSNDMNU_WILDMIDICONFIG", "wildmidi_config" TextField "$ADVSNDMNU_WILDMIDICONFIG", "wildmidi_config"
SubMenu "$ADVSNDMNU_SELCONFIG", "WildMidiConfigMenu"
Option "$ADVSNDMNU_REVERB", "wildmidi_reverb", "OnOff" Option "$ADVSNDMNU_REVERB", "wildmidi_reverb", "OnOff"
} }
OptionMenu GusConfigMenu
{
Title "$ADVSNDMNU_SELCONFIG"
}
OptionMenu WildMidiConfigMenu
{
Title "$ADVSNDMNU_SELCONFIG"
}
OptionMenu TimidityExeMenu
{
Title "$ADVSNDMNU_SELCONFIG"
}
OptionMenu FluidPatchsetMenu
{
Title "$ADVSNDMNU_SELCONFIG"
}
/*======================================= /*=======================================
* *
* Module Replayer Options Menu * Module Replayer Options Menu

View file

@ -44,7 +44,7 @@ class OptionMenuItem : MenuItemBase
mCentered = center; mCentered = center;
} }
protected void drawLabel(int indent, int y, int color, bool grayed = false) protected int drawLabel(int indent, int y, int color, bool grayed = false)
{ {
String label = Stringtable.Localize(mLabel); String label = Stringtable.Localize(mLabel);
@ -55,6 +55,7 @@ class OptionMenuItem : MenuItemBase
if (!mCentered) x = indent - w; if (!mCentered) x = indent - w;
else x = (screen.GetWidth() - w) / 2; else x = (screen.GetWidth() - w) / 2;
screen.DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); screen.DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay);
return x;
} }
int CursorSpace() int CursorSpace()
@ -92,16 +93,20 @@ class OptionMenuItem : MenuItemBase
class OptionMenuItemSubmenu : OptionMenuItem class OptionMenuItemSubmenu : OptionMenuItem
{ {
int mParam; int mParam;
OptionMenuItemSubmenu Init(String label, Name command, int param = 0) OptionMenuItemSubmenu Init(String label, Name command, int param = 0, bool centered = false)
{ {
Super.init(label, command); Super.init(label, command, centered);
mParam = param; mParam = param;
return self; return self;
} }
override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected)
{ {
drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColorMore); int x = drawLabel(indent, y, selected? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColorMore);
if (mCentered)
{
return x - 16*CleanXfac_1;
}
return indent; return indent;
} }
@ -121,9 +126,9 @@ class OptionMenuItemSubmenu : OptionMenuItem
class OptionMenuItemCommand : OptionMenuItemSubmenu class OptionMenuItemCommand : OptionMenuItemSubmenu
{ {
OptionMenuItemCommand Init(String label, Name command) OptionMenuItemCommand Init(String label, Name command, bool centered = false)
{ {
Super.Init(label, command); Super.Init(label, command, 0, centered);
return self; return self;
} }