mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
- 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:
parent
fb12c58533
commit
8180d34765
9 changed files with 167 additions and 54 deletions
|
@ -1165,6 +1165,17 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
|
|||
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)
|
||||
{
|
||||
auto c = PClass::FindClass("ListMenuItemPatchItem");
|
||||
|
|
|
@ -355,5 +355,6 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
|
|||
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy);
|
||||
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 * CreateOptionMenuItemCommand(const char *label, FName cmd, bool centered = false);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "cmdlib.h"
|
||||
#include "vm.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
|
||||
|
@ -1332,6 +1420,7 @@ void M_CreateMenus()
|
|||
BuildEpisodeMenu();
|
||||
BuildPlayerclassMenu();
|
||||
InitCrosshairsList();
|
||||
InitMusicMenus();
|
||||
InitKeySections();
|
||||
|
||||
FOptionValues **opt = OptionValues.CheckKey(NAME_Mididevices);
|
||||
|
|
|
@ -109,14 +109,6 @@
|
|||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
struct MusPlayingInfo
|
||||
{
|
||||
FString name;
|
||||
MusInfo *handle;
|
||||
int baseorder;
|
||||
bool loop;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
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 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 FPlayList *PlayList;
|
||||
static int RestartEvictionsAt; // do not restart evicted channels before this level.time
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "doomtype.h"
|
||||
#include "vectors.h"
|
||||
#include "tarray.h"
|
||||
|
||||
|
@ -161,5 +161,15 @@ enum EMidiDevice
|
|||
MDEV_WILDMIDI = 6,
|
||||
};
|
||||
|
||||
class MusInfo;
|
||||
struct MusPlayingInfo
|
||||
{
|
||||
FString name;
|
||||
MusInfo *handle;
|
||||
int baseorder;
|
||||
bool loop;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "gameconfigfile.h"
|
||||
#include "cmdlib.h"
|
||||
#include "m_misc.h"
|
||||
#include "s_sound.h"
|
||||
|
||||
#include "templates.h"
|
||||
#include "v_text.h"
|
||||
|
@ -55,42 +56,6 @@ 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<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)
|
||||
{
|
||||
int p;
|
||||
|
@ -115,6 +80,8 @@ static void AddDefaultMidiDevices(FOptionValues *opt)
|
|||
|
||||
}
|
||||
|
||||
extern MusPlayingInfo mus_playing;
|
||||
|
||||
void MIDIDeviceChanged(int newdev, bool force)
|
||||
{
|
||||
static int oldmididev = INT_MIN;
|
||||
|
@ -127,8 +94,18 @@ void MIDIDeviceChanged(int newdev, bool force)
|
|||
MusInfo *song = currSong;
|
||||
if (song->m_Status == MusInfo::STATE_Playing)
|
||||
{
|
||||
song->Stop();
|
||||
song->Start(song->m_Looping);
|
||||
if (song->GetDeviceType() == MDEV_FLUIDSYNTH && force)
|
||||
{
|
||||
// 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
|
||||
|
|
|
@ -2161,6 +2161,7 @@ ADVSNDMNU_TIMIDITYCHORUS = "Chorus";
|
|||
ADVSNDMNU_TIMIDITYVOLUME = "Relative volume";
|
||||
ADVSNDMNU_WILDMIDI = "WildMidi";
|
||||
ADVSNDMNU_WILDMIDICONFIG = "WildMidi config file";
|
||||
ADVSNDMNU_SELCONFIG = "Select configuration";
|
||||
|
||||
// Module Replayer Options
|
||||
MODMNU_TITLE = "MODULE REPLAYER OPTIONS";
|
||||
|
|
|
@ -1637,12 +1637,14 @@ OptionMenu AdvSoundOptions
|
|||
StaticText " "
|
||||
StaticText "$ADVSNDMNU_GUSEMULATION", 1
|
||||
TextField "$ADVSNDMNU_GUSCONFIG", "midi_config"
|
||||
SubMenu "$ADVSNDMNU_SELCONFIG", "GusConfigMenu"
|
||||
Slider "$ADVSNDMNU_MIDIVOICES", "midi_voices", 16, 256, 4, 0
|
||||
Option "$ADVSNDMNU_DMXGUS", "midi_dmxgus", "OnOff"
|
||||
Option "$ADVSNDMNU_GUSMEMSIZE", "gus_memsize", "GusMemory"
|
||||
StaticText " "
|
||||
StaticText "$ADVSNDMNU_FLUIDSYNTH", 1
|
||||
TextField "$ADVSNDMNU_FLUIDPATCHSET", "fluid_patchset"
|
||||
SubMenu "$ADVSNDMNU_SELCONFIG", "FluidPatchsetMenu"
|
||||
Slider "$ADVSNDMNU_FLUIDGAIN", "fluid_gain", 0, 10, 0.5, 1
|
||||
Option "$ADVSNDMNU_REVERB", "fluid_reverb", "OnOff"
|
||||
Slider "$ADVSNDMNU_FLUIDVOICES", "fluid_voices", 16, 4096, 16, 1
|
||||
|
@ -1650,15 +1652,40 @@ OptionMenu AdvSoundOptions
|
|||
StaticText " "
|
||||
StaticText "$ADVSNDMNU_TIMIDITY", 1
|
||||
TextField "$ADVSNDMNU_TIMIDITYEXE", "timidity_exe"
|
||||
IfOption(Windows)
|
||||
{
|
||||
SubMenu "$ADVSNDMNU_SELCONFIG", "TimidityExeMenu"
|
||||
}
|
||||
Option "$ADVSNDMNU_REVERB", "timidity_reverb", "OnOff"
|
||||
Option "$ADVSNDMNU_TIMIDITYCHORUS", "timidity_chorus", "OnOff"
|
||||
Slider "$ADVSNDMNU_TIMIDITYVOLUME", "timidity_mastervolume", 0, 4, 0.2, 1
|
||||
StaticText " "
|
||||
StaticText "$ADVSNDMNU_WILDMIDI", 1
|
||||
TextField "$ADVSNDMNU_WILDMIDICONFIG", "wildmidi_config"
|
||||
SubMenu "$ADVSNDMNU_SELCONFIG", "WildMidiConfigMenu"
|
||||
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
|
||||
|
|
|
@ -44,7 +44,7 @@ class OptionMenuItem : MenuItemBase
|
|||
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);
|
||||
|
||||
|
@ -55,6 +55,7 @@ class OptionMenuItem : MenuItemBase
|
|||
if (!mCentered) x = indent - w;
|
||||
else x = (screen.GetWidth() - w) / 2;
|
||||
screen.DrawText (SmallFont, color, x, y, label, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay);
|
||||
return x;
|
||||
}
|
||||
|
||||
int CursorSpace()
|
||||
|
@ -92,16 +93,20 @@ class OptionMenuItem : MenuItemBase
|
|||
class OptionMenuItemSubmenu : OptionMenuItem
|
||||
{
|
||||
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;
|
||||
return self;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -121,9 +126,9 @@ class OptionMenuItemSubmenu : OptionMenuItem
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue