2020-09-15 20:57:54 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
2020-09-15 20:57:54 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// GuiMenu.cpp
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Main menu.
|
|
|
|
// Some submenus are covered in separate source files.
|
2020-05-24 08:29:29 +00:00
|
|
|
//
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "guis/GuiMenu.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
|
|
|
#include "components/OptionListComponent.h"
|
|
|
|
#include "components/SliderComponent.h"
|
|
|
|
#include "components/SwitchComponent.h"
|
2017-06-12 16:38:59 +00:00
|
|
|
#include "guis/GuiCollectionSystemsOptions.h"
|
2020-07-15 16:02:11 +00:00
|
|
|
#include "guis/GuiComplexTextEditPopup.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "guis/GuiDetectDevice.h"
|
2020-11-05 17:35:08 +00:00
|
|
|
#include "guis/GuiScreensaverOptions.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "guis/GuiMsgBox.h"
|
2020-06-06 11:10:33 +00:00
|
|
|
#include "guis/GuiScraperMenu.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "guis/GuiSettings.h"
|
2020-09-15 20:57:54 +00:00
|
|
|
#include "views/gamelist/IGameListView.h"
|
2017-11-18 22:23:56 +00:00
|
|
|
#include "views/UIModeController.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "views/ViewController.h"
|
2020-12-23 17:06:30 +00:00
|
|
|
#include "CollectionSystemsManager.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "EmulationStation.h"
|
2021-01-05 09:45:32 +00:00
|
|
|
#include "FileFilterIndex.h"
|
2020-07-15 16:02:11 +00:00
|
|
|
#include "FileSorts.h"
|
2020-06-21 10:26:21 +00:00
|
|
|
#include "Platform.h"
|
2018-01-30 00:49:08 +00:00
|
|
|
#include "Scripting.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
#include "SystemData.h"
|
2014-06-25 16:29:58 +00:00
|
|
|
#include "VolumeControl.h"
|
2020-06-26 16:03:55 +00:00
|
|
|
|
Changed Audio settings to be much more flexible
Changed the selectable options for EmulationStation audio mixer
(called AudioDevice in EmulationStation) to be a greater range of
selectable options within Linux and RPi so that it is a lot more
flexible and will work with any aftermarket add-on audio cards and
RPi Audio HATs. Hopefully this gives people the flexibility that
they need in order to avoid the issues people have with unusual RPi
audio setups.
Added the ability to select the audio card as well, by surfacing
the audio card under the Audio Card setting. It was previously forced
to 'default' for all linux users, which was too restrictive in some
instances. This change now adds flexbility to support additional
Linux and RPi Audio Cards.
This option will only be available on Linux (and therefore RPi) as
Windows uses a different audio subsystem.
CHOOSING AUDIO ON LINUX AND RPi
You now select which ALSA Audio Card you want EmulationStation to use
by choosing the relevant AUDIO CARD option. If your one is not listed
then you can add a custom one in the es_settings.cfg file (see below).
You then select which ALSA Audio Mixer Control from that Audio Card
that you want EmulationStation to use, by choosing the relevant
AUDIO DEVICE option. (I kept the name AUDIO DEVICE as that what
EmulationStation previously used to describe an Audio Mixer.)
If your mixer name is not listed then you can add a custom one in
the es_settings.cfg file (see below).
ADDING A CUSTOM AUDIO CARD OR AUDIO DEVICE
In addition I added the ability to manually change the setting in
es_settings.cfg to add anything custom that you want. This will give
advanced users enough extra power that should avoid even the most
strange setups.
Step 1:
To add a custom Audio Card, edit the "AudioCard" setting and replace
the value with the name of your Audio Card. You can find this out by
opening a terminal window and running 'aplay -L'. This will generate a
list of Audio Cards similar to the one below:
pi@raspberrypi:~ $ aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
default:CARD=sndrpijustboomd
snd_rpi_justboom_dac,
Default Audio Device
sysdefault:CARD=sndrpijustboomd
snd_rpi_justboom_dac,
Default Audio Device
dmix:CARD=sndrpijustboomd,DEV=0
snd_rpi_justboom_dac,
Direct sample mixing device
dsnoop:CARD=sndrpijustboomd,DEV=0
snd_rpi_justboom_dac,
Direct sample snooping device
hw:CARD=sndrpijustboomd,DEV=0
snd_rpi_justboom_dac,
Direct hardware device without any conversions
plughw:CARD=sndrpijustboomd,DEV=0
snd_rpi_justboom_dac,
Hardware device with all software conversions
Select any one of the Audio Cards listed by using the first word on
the line in your AudioCard settings in the es_settings.cfg, e.g.
<string name="AudioCard" value="default" />
NOTE: If the AudioCard value is not listed, please either close and
reopen EmulationStation (the settings is created upon close if it
doesn't exist), or add it manually to the es_settings.cfg file.
Step 2:
To add a custom Audio Device (mixer), edit the "AudioDevice" setting
and replace the value with the name of your Audio Device. You can get
a list off avilable Audio Devices on the Audio Card by opening a
terminal window and running 'amixer scontrols -D <AudioCard>', where
<AudioCard> is replaced with the name of your Audio Card that you
found in Step 1. This command will generate a list of Audio Devices
(mixers) that you can use in the AudioDevice setting in the
es_settings.cfg file, e.g.
pi@raspberrypi:~ $ amixer scontrols -D default
Simple mixer control 'DSP Program',0
Simple mixer control 'Analogue',0
Simple mixer control 'Analogue Playback Boost',0
Simple mixer control 'Auto Mute',0
Simple mixer control 'Auto Mute Mono',0
Simple mixer control 'Auto Mute Time Left',0
Simple mixer control 'Auto Mute Time Right',0
Simple mixer control 'Clock Missing Period',0
Simple mixer control 'Deemphasis',0
Simple mixer control 'Digital',0
Simple mixer control 'Max Overclock DAC',0
Simple mixer control 'Max Overclock DSP',0
Simple mixer control 'Max Overclock PLL',0
Simple mixer control 'Volume Ramp Down Emergency Rate',0
Simple mixer control 'Volume Ramp Down Emergency Step',0
Simple mixer control 'Volume Ramp Down Rate',0
Simple mixer control 'Volume Ramp Down Step',0
Simple mixer control 'Volume Ramp Up Rate',0
Simple mixer control 'Volume Ramp Up Step',0
Select any one of the Simple mixer controls listed by using the
name within the quotes within the AudioDevice setting in your
es_settings.cfg file, e.g.
<string name="AudioDevice" value="Digital" />
Using the example above, the following two settings within the
es_settings.cfg file will use the 'default' Audio Card to play
sounds, and will use the 'Digital' mixer (Audio Device) to
control the volume.
<string name="AudioCard" value="default" />
<string name="AudioDevice" value="Digital" />
NOTE: Any custom manually used settings will be overwritten if you
select any of the other options in the GUI and exit the Sound
Settings window, as the Sound Settings GUI window overwrites the
es_settings.cfg options when you exit the window.
Fix latest package renames
fonts-droid is now fonts-droid-fallback
vlc-nox is now vlc-bin
Fixed up whitespacing to project tab standard
Had not paid enough attention and had accidentally provided
whitespacing in spaces rather than the project standard of
tabs. This change fixes some additional use of spaces to
ensure all the code in the two files now uses tabs.
Vero4k autodetection and volume mixer fix
2018-07-21 09:06:20 +00:00
|
|
|
#include <algorithm>
|
2020-06-26 16:03:55 +00:00
|
|
|
#include <SDL2/SDL_events.h>
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
GuiMenu::GuiMenu(Window* window) : GuiComponent(window),
|
|
|
|
mMenu(window, "MAIN MENU"), mVersion(window)
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
bool isFullUI = UIModeController::getInstance()->isUIModeFull();
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
|
|
|
addEntry("SCRAPER", 0x777777FF, true, [this] { openScraperSettings(); });
|
2020-06-06 11:10:33 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
|
|
|
addEntry("UI SETTINGS", 0x777777FF, true, [this] { openUISettings(); });
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
addEntry("SOUND SETTINGS", 0x777777FF, true, [this] { openSoundSettings(); });
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
|
|
|
addEntry("GAME COLLECTION SETTINGS", 0x777777FF, true, [this] {
|
|
|
|
openCollectionSystemSettings(); });
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
|
|
|
addEntry("OTHER SETTINGS", 0x777777FF, true, [this] { openOtherSettings(); });
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (isFullUI)
|
|
|
|
addEntry("CONFIGURE INPUT", 0x777777FF, true, [this] { openConfigInput(); });
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
if (!Settings::getInstance()->getBool("ForceKiosk") &&
|
|
|
|
Settings::getInstance()->getString("UIMode") != "kiosk") {
|
|
|
|
if (Settings::getInstance()->getBool("ShowQuitMenu"))
|
|
|
|
addEntry("QUIT", 0x777777FF, true, [this] {openQuitMenu(); });
|
|
|
|
else
|
2020-12-25 21:49:40 +00:00
|
|
|
addEntry("QUIT EMULATIONSTATION", 0x777777FF, false, [this] {openQuitMenu(); });
|
2020-12-17 22:45:29 +00:00
|
|
|
}
|
2017-09-08 14:49:47 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
addChild(&mMenu);
|
|
|
|
addVersionInfo();
|
|
|
|
setSize(mMenu.getSize());
|
|
|
|
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2,
|
|
|
|
Renderer::getScreenHeight() * 0.15f);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 20:57:54 +00:00
|
|
|
GuiMenu::~GuiMenu()
|
|
|
|
{
|
|
|
|
// This is required for the situation where scrolling started just before the menu
|
|
|
|
// was openened. Without this, the scrolling would run until manually stopped after
|
|
|
|
// the menu has been closed.
|
|
|
|
ViewController::get()->stopScrolling();
|
|
|
|
}
|
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::openScraperSettings()
|
|
|
|
{
|
2020-11-06 19:27:41 +00:00
|
|
|
mWindow->pushGui(new GuiScraperMenu(mWindow, "SCRAPER"));
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GuiMenu::openUISettings()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
auto s = new GuiSettings(mWindow, "UI SETTINGS");
|
|
|
|
|
|
|
|
// Optionally start in selected system/gamelist.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto startup_system = std::make_shared<OptionListComponent<std::string>>
|
2020-06-21 12:25:28 +00:00
|
|
|
(mWindow, getHelpStyle(), "GAMELIST ON STARTUP", false);
|
2020-11-05 17:18:11 +00:00
|
|
|
startup_system->add("NONE", "", Settings::getInstance()->getString("StartupSystem") == "");
|
2021-01-30 14:52:10 +00:00
|
|
|
float dotsSize = Font::get(FONT_SIZE_MEDIUM)->sizeText("...").x();
|
2020-06-21 12:25:28 +00:00
|
|
|
for (auto it = SystemData::sSystemVector.cbegin();
|
|
|
|
it != SystemData::sSystemVector.cend(); it++) {
|
2021-01-30 14:52:10 +00:00
|
|
|
if ((*it)->getName() != "retropie") {
|
|
|
|
// If required, abbreviate the system name so it doesn't overlap the setting name.
|
|
|
|
std::string abbreviatedString = Font::get(FONT_SIZE_MEDIUM)->
|
2021-01-31 23:08:29 +00:00
|
|
|
getTextMaxWidth((*it)->getFullName(), mSize.x() * 0.47f);
|
2021-01-30 14:52:10 +00:00
|
|
|
float sizeDifference = Font::get(FONT_SIZE_MEDIUM)->sizeText((*it)->getFullName()).x() -
|
|
|
|
Font::get(FONT_SIZE_MEDIUM)->sizeText(abbreviatedString).x();
|
|
|
|
if (sizeDifference > 0) {
|
|
|
|
// It doesn't make sense to abbreviate if the number of pixels removed by
|
|
|
|
// the abbreviation is less or equal to the size of the three dots that
|
|
|
|
// would be appended to the string.
|
|
|
|
if (sizeDifference <= dotsSize) {
|
|
|
|
abbreviatedString = (*it)->getFullName();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (abbreviatedString.back() == ' ')
|
|
|
|
abbreviatedString.pop_back();
|
|
|
|
abbreviatedString += "...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
startup_system->add(abbreviatedString, (*it)->getName(),
|
2020-06-21 12:25:28 +00:00
|
|
|
Settings::getInstance()->getString("StartupSystem") == (*it)->getName());
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
2021-01-30 14:52:10 +00:00
|
|
|
s->addWithLabel("GAMELIST ON STARTUP", startup_system);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([startup_system, s] {
|
|
|
|
if (startup_system->getSelected() != Settings::getInstance()->getString("StartupSystem")) {
|
|
|
|
Settings::getInstance()->setString("StartupSystem", startup_system->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// GameList view style.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto gamelist_view_style = std::make_shared<OptionListComponent<std::string>>
|
2020-06-21 12:25:28 +00:00
|
|
|
(mWindow, getHelpStyle(), "GAMELIST VIEW STYLE", false);
|
|
|
|
std::vector<std::string> styles;
|
|
|
|
styles.push_back("automatic");
|
|
|
|
styles.push_back("basic");
|
|
|
|
styles.push_back("detailed");
|
|
|
|
styles.push_back("video");
|
|
|
|
styles.push_back("grid");
|
|
|
|
for (auto it = styles.cbegin(); it != styles.cend(); it++)
|
2020-11-05 17:18:11 +00:00
|
|
|
gamelist_view_style->add(*it, *it, Settings::getInstance()->
|
2020-06-21 12:25:28 +00:00
|
|
|
getString("GamelistViewStyle") == *it);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("GAMELIST VIEW STYLE", gamelist_view_style);
|
|
|
|
s->addSaveFunc([gamelist_view_style, s] {
|
|
|
|
if (gamelist_view_style->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("GamelistViewStyle")) {
|
|
|
|
Settings::getInstance()->setString("GamelistViewStyle",
|
|
|
|
gamelist_view_style->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Transition style.
|
|
|
|
auto transition_style = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "TRANSITION STYLE", false);
|
|
|
|
std::vector<std::string> transitions;
|
|
|
|
transitions.push_back("slide");
|
2020-12-25 16:25:23 +00:00
|
|
|
transitions.push_back("fade");
|
2020-06-21 12:25:28 +00:00
|
|
|
transitions.push_back("instant");
|
|
|
|
for (auto it = transitions.cbegin(); it != transitions.cend(); it++)
|
|
|
|
transition_style->add(*it, *it, Settings::getInstance()->
|
|
|
|
getString("TransitionStyle") == *it);
|
|
|
|
s->addWithLabel("TRANSITION STYLE", transition_style);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([transition_style, s] {
|
|
|
|
if (transition_style->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("TransitionStyle")) {
|
|
|
|
Settings::getInstance()->setString("TransitionStyle", transition_style->getSelected());
|
|
|
|
s->setNeedsSaving();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Theme selection.
|
|
|
|
auto themeSets = ThemeData::getThemeSets();
|
2020-07-15 16:02:11 +00:00
|
|
|
if (!themeSets.empty()) {
|
2020-06-21 12:25:28 +00:00
|
|
|
std::map<std::string, ThemeSet>::const_iterator selectedSet =
|
|
|
|
themeSets.find(Settings::getInstance()->getString("ThemeSet"));
|
|
|
|
if (selectedSet == themeSets.cend())
|
|
|
|
selectedSet = themeSets.cbegin();
|
|
|
|
auto theme_set = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "THEME SET", false);
|
|
|
|
for (auto it = themeSets.cbegin(); it != themeSets.cend(); it++)
|
|
|
|
theme_set->add(it->first, it->first, it == selectedSet);
|
|
|
|
s->addWithLabel("THEME SET", theme_set);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([theme_set, s] {
|
|
|
|
if (theme_set->getSelected() != Settings::getInstance()->getString("ThemeSet")) {
|
|
|
|
Scripting::fireEvent("theme-changed", theme_set->getSelected(),
|
|
|
|
Settings::getInstance()->getString("ThemeSet"));
|
2020-12-23 17:06:30 +00:00
|
|
|
CollectionSystemsManager::get()->updateSystemsList();
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->setString("ThemeSet", theme_set->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// UI mode.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto ui_mode = std::make_shared<OptionListComponent<std::string>>
|
2020-06-21 12:25:28 +00:00
|
|
|
(mWindow, getHelpStyle(), "UI MODE", false);
|
2020-11-05 17:18:11 +00:00
|
|
|
std::vector<std::string> uiModes;
|
|
|
|
uiModes.push_back("full");
|
|
|
|
uiModes.push_back("kiosk");
|
|
|
|
uiModes.push_back("kid");
|
2020-12-17 22:45:29 +00:00
|
|
|
std::string setMode;
|
|
|
|
if (Settings::getInstance()->getBool("ForceKiosk"))
|
|
|
|
setMode = "kiosk";
|
|
|
|
else if (Settings::getInstance()->getBool("ForceKid"))
|
|
|
|
setMode = "kid";
|
|
|
|
else
|
|
|
|
setMode = Settings::getInstance()->getString("UIMode");
|
2020-11-05 17:18:11 +00:00
|
|
|
for (auto it = uiModes.cbegin(); it != uiModes.cend(); it++)
|
2020-12-17 22:45:29 +00:00
|
|
|
ui_mode->add(*it, *it, setMode == *it);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("UI MODE", ui_mode);
|
|
|
|
s->addSaveFunc([ui_mode, this, s] {
|
|
|
|
std::string selectedMode = ui_mode->getSelected();
|
2021-01-05 09:45:32 +00:00
|
|
|
// If any of the force flags are set, then always apply and save the setting.
|
|
|
|
if (selectedMode == Settings::getInstance()->getString("UIMode") &&
|
|
|
|
!Settings::getInstance()->getBool("ForceFull") &&
|
|
|
|
!Settings::getInstance()->getBool("ForceKiosk") &&
|
|
|
|
!Settings::getInstance()->getBool("ForceKid")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (selectedMode != "full") {
|
2021-01-17 10:11:07 +00:00
|
|
|
std::string msg = "YOU ARE CHANGING THE UI TO THE RESTRICTED MODE\n'" +
|
2020-11-05 17:18:11 +00:00
|
|
|
Utils::String::toUpper(selectedMode) + "'\n";
|
2021-01-17 10:11:07 +00:00
|
|
|
if (selectedMode == "kiosk") {
|
|
|
|
msg += "THIS WILL HIDE MOST MENU OPTIONS TO PREVENT\n";
|
|
|
|
msg += "CHANGES TO THE SYSTEM\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
msg += "THIS WILL LIMIT THE AVAILABLE GAMES TO THE ONES\n";
|
|
|
|
msg += "FLAGGED SUITABLE FOR CHILDREN\n";
|
|
|
|
}
|
2020-06-22 15:27:53 +00:00
|
|
|
msg += "TO UNLOCK AND RETURN TO THE FULL UI, ENTER THIS CODE: \n";
|
2021-01-17 10:11:07 +00:00
|
|
|
msg += UIModeController::getInstance()->getFormattedPassKeyStr() + "\n\n";
|
2020-06-22 15:27:53 +00:00
|
|
|
msg += "DO YOU WANT TO PROCEED?";
|
2020-11-05 17:18:11 +00:00
|
|
|
mWindow->pushGui(new GuiMsgBox(mWindow, this->getHelpStyle(), msg,
|
2021-01-05 09:45:32 +00:00
|
|
|
"YES", [this, selectedMode] {
|
2020-11-05 17:18:11 +00:00
|
|
|
LOG(LogDebug) << "GuiMenu::openUISettings(): Setting UI mode to '"
|
|
|
|
<< selectedMode << "'.";
|
|
|
|
Settings::getInstance()->setString("UIMode", selectedMode);
|
2020-12-17 22:45:29 +00:00
|
|
|
Settings::getInstance()->setBool("ForceFull", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKiosk", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKid", false);
|
2020-11-05 17:18:11 +00:00
|
|
|
Settings::getInstance()->saveFile();
|
2021-01-05 09:45:32 +00:00
|
|
|
UIModeController::getInstance()->setCurrentUIMode(selectedMode);
|
|
|
|
for (auto it = SystemData::sSystemVector.cbegin();
|
|
|
|
it != SystemData::sSystemVector.cend(); it++) {
|
|
|
|
if ((*it)->getThemeFolder() == "custom-collections") {
|
|
|
|
for (FileData* customSystem :
|
|
|
|
(*it)->getRootFolder()->getChildrenListToDisplay())
|
|
|
|
customSystem->getSystem()->getIndex()->resetFilters();
|
|
|
|
}
|
|
|
|
(*it)->sortSystem();
|
|
|
|
(*it)->getIndex()->resetFilters();
|
|
|
|
}
|
|
|
|
ViewController::get()->reloadAll();
|
|
|
|
ViewController::get()->goToSystem(SystemData::sSystemVector.front(), false);
|
|
|
|
mWindow->invalidateCachedBackground();
|
2020-11-05 17:18:11 +00:00
|
|
|
}, "NO", nullptr));
|
|
|
|
}
|
2021-01-05 09:45:32 +00:00
|
|
|
else {
|
2020-11-05 17:18:11 +00:00
|
|
|
LOG(LogDebug) << "GuiMenu::openUISettings(): Setting UI mode to '" <<
|
|
|
|
selectedMode << "'.";
|
|
|
|
Settings::getInstance()->setString("UIMode", ui_mode->getSelected());
|
2020-12-17 22:45:29 +00:00
|
|
|
Settings::getInstance()->setBool("ForceFull", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKiosk", false);
|
|
|
|
Settings::getInstance()->setBool("ForceKid", false);
|
2021-01-05 09:45:32 +00:00
|
|
|
UIModeController::getInstance()->setCurrentUIMode("full");
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2021-01-05 09:45:32 +00:00
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
|
|
|
s->setNeedsResetFilters();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
s->setNeedsGoToSystem(SystemData::sSystemVector.front());
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
// Default gamelist sort order.
|
|
|
|
typedef OptionListComponent<const FileData::SortType*> SortList;
|
|
|
|
std::string sortOrder;
|
2020-11-05 17:18:11 +00:00
|
|
|
auto default_sort_order = std::make_shared<SortList>
|
2020-07-15 16:02:11 +00:00
|
|
|
(mWindow, getHelpStyle(), "DEFAULT SORT ORDER", false);
|
2021-01-08 19:30:21 +00:00
|
|
|
// Exclude the System sort options.
|
2021-01-09 12:44:18 +00:00
|
|
|
unsigned int numSortTypes = static_cast<unsigned int>(FileSorts::SortTypes.size() - 2);
|
2021-01-08 19:30:21 +00:00
|
|
|
for (unsigned int i = 0; i < numSortTypes; i++) {
|
|
|
|
if (FileSorts::SortTypes[i].description ==
|
|
|
|
Settings::getInstance()->getString("DefaultSortOrder")) {
|
|
|
|
sortOrder = FileSorts::SortTypes[i].description;
|
2020-07-15 16:02:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If an invalid sort order was defined in es_settings.cfg, then apply the default
|
|
|
|
// sort order 'filename, ascending'.
|
|
|
|
if (sortOrder == "")
|
2020-12-14 16:25:41 +00:00
|
|
|
sortOrder = Settings::getInstance()->getDefaultString("DefaultSortOrder");
|
2021-01-08 19:30:21 +00:00
|
|
|
for (unsigned int i = 0; i < numSortTypes; i++) {
|
|
|
|
const FileData::SortType& sort = FileSorts::SortTypes[i];
|
2020-07-15 16:02:11 +00:00
|
|
|
if (sort.description == sortOrder)
|
2020-11-05 17:18:11 +00:00
|
|
|
default_sort_order->add(sort.description, &sort, true);
|
2020-07-15 16:02:11 +00:00
|
|
|
else
|
2020-11-05 17:18:11 +00:00
|
|
|
default_sort_order->add(sort.description, &sort, false);
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("DEFAULT SORT ORDER", default_sort_order);
|
|
|
|
s->addSaveFunc([default_sort_order, sortOrder, s] {
|
|
|
|
std::string selectedSortOrder = default_sort_order.get()->getSelected()->description;
|
2020-07-15 16:02:11 +00:00
|
|
|
if (selectedSortOrder != sortOrder) {
|
|
|
|
Settings::getInstance()->setString("DefaultSortOrder", selectedSortOrder);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-09-13 11:21:38 +00:00
|
|
|
#if defined(USE_OPENGL_21)
|
|
|
|
// Open menu effect.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto menu_opening_effect = std::make_shared<OptionListComponent<std::string>>
|
2020-09-13 12:28:06 +00:00
|
|
|
(mWindow, getHelpStyle(), "MENU OPENING EFFECT", false);
|
2020-09-13 11:21:38 +00:00
|
|
|
std::vector<std::string> menu_effects;
|
|
|
|
menu_effects.push_back("scale-up");
|
|
|
|
menu_effects.push_back("fade-in");
|
|
|
|
menu_effects.push_back("none");
|
|
|
|
for (auto it = menu_effects.cbegin(); it != menu_effects.cend(); it++)
|
2020-11-05 17:18:11 +00:00
|
|
|
menu_opening_effect->add(*it, *it, Settings::getInstance()->
|
2020-09-13 11:46:34 +00:00
|
|
|
getString("MenuOpeningEffect") == *it);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("MENU OPENING EFFECT", menu_opening_effect);
|
|
|
|
s->addSaveFunc([menu_opening_effect, s] {
|
|
|
|
if (menu_opening_effect->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("MenuOpeningEffect")) {
|
|
|
|
Settings::getInstance()->setString("MenuOpeningEffect",
|
|
|
|
menu_opening_effect->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-09-13 11:21:38 +00:00
|
|
|
});
|
2020-11-17 16:20:25 +00:00
|
|
|
#endif
|
2020-09-13 12:28:06 +00:00
|
|
|
|
2020-11-17 16:20:25 +00:00
|
|
|
// Display pillarboxes (and letterboxes) for videos in the gamelists.
|
|
|
|
auto gamelist_video_pillarbox = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
gamelist_video_pillarbox->setState(Settings::getInstance()->getBool("GamelistVideoPillarbox"));
|
|
|
|
s->addWithLabel("DISPLAY PILLARBOXES FOR GAMELIST VIDEOS", gamelist_video_pillarbox);
|
|
|
|
s->addSaveFunc([gamelist_video_pillarbox, s] {
|
|
|
|
if (gamelist_video_pillarbox->getState() !=
|
|
|
|
Settings::getInstance()->getBool("GamelistVideoPillarbox")) {
|
|
|
|
Settings::getInstance()->setBool("GamelistVideoPillarbox",
|
|
|
|
gamelist_video_pillarbox->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
#if defined(USE_OPENGL_21)
|
2020-11-05 17:18:11 +00:00
|
|
|
// Render scanlines for videos in the gamelists.
|
|
|
|
auto gamelist_video_scanlines = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
gamelist_video_scanlines->setState(Settings::getInstance()->getBool("GamelistVideoScanlines"));
|
|
|
|
s->addWithLabel("RENDER SCANLINES FOR GAMELIST VIDEOS", gamelist_video_scanlines);
|
|
|
|
s->addSaveFunc([gamelist_video_scanlines, s] {
|
|
|
|
if (gamelist_video_scanlines->getState() !=
|
|
|
|
Settings::getInstance()->getBool("GamelistVideoScanlines")) {
|
|
|
|
Settings::getInstance()->setBool("GamelistVideoScanlines",
|
|
|
|
gamelist_video_scanlines->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-09-13 11:21:38 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-28 17:44:17 +00:00
|
|
|
// Sort folders on top of the gamelists.
|
|
|
|
auto folders_on_top = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
folders_on_top->setState(Settings::getInstance()->getBool("FoldersOnTop"));
|
|
|
|
s->addWithLabel("SORT FOLDERS ON TOP OF GAMELISTS", folders_on_top);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([folders_on_top, s] {
|
|
|
|
if (folders_on_top->getState() !=
|
|
|
|
Settings::getInstance()->getBool("FoldersOnTop")) {
|
|
|
|
Settings::getInstance()->setBool("FoldersOnTop", folders_on_top->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
2020-07-28 17:44:17 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Sort favorites on top of non-favorites in the gamelists.
|
|
|
|
auto favorites_first = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
favorites_first->setState(Settings::getInstance()->getBool("FavoritesFirst"));
|
|
|
|
s->addWithLabel("SORT FAVORITE GAMES ABOVE NON-FAVORITES", favorites_first);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([favorites_first,s ] {
|
|
|
|
if (favorites_first->getState() !=
|
|
|
|
Settings::getInstance()->getBool("FavoritesFirst")) {
|
|
|
|
Settings::getInstance()->setBool("FavoritesFirst", favorites_first->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsSorting();
|
|
|
|
s->setNeedsSortingCollections();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-25 20:29:54 +00:00
|
|
|
// Enable gamelist star markings for favorite games.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto favorites_star = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
favorites_star->setState(Settings::getInstance()->getBool("FavoritesStar"));
|
|
|
|
s->addWithLabel("ADD STAR MARKINGS TO FAVORITE GAMES", favorites_star);
|
|
|
|
s->addSaveFunc([favorites_star, s] {
|
|
|
|
if (favorites_star->getState() != Settings::getInstance()->getBool("FavoritesStar")) {
|
|
|
|
Settings::getInstance()->setBool("FavoritesStar", favorites_star->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
2020-10-25 20:29:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-01-12 21:41:28 +00:00
|
|
|
// Enable quick list scrolling overlay.
|
|
|
|
auto list_scroll_overlay = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
list_scroll_overlay->setState(Settings::getInstance()->getBool("ListScrollOverlay"));
|
|
|
|
s->addWithLabel("ENABLE QUICK LIST SCROLLING OVERLAY", list_scroll_overlay);
|
|
|
|
s->addSaveFunc([list_scroll_overlay, s] {
|
|
|
|
if (list_scroll_overlay->getState() !=
|
|
|
|
Settings::getInstance()->getBool("ListScrollOverlay")) {
|
|
|
|
Settings::getInstance()->setBool("ListScrollOverlay", list_scroll_overlay->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-10-31 09:01:19 +00:00
|
|
|
// Enable the 'Y' button for tagging games as favorites.
|
|
|
|
auto favorites_add_button = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
favorites_add_button->setState(Settings::getInstance()->getBool("FavoritesAddButton"));
|
2020-11-09 16:50:02 +00:00
|
|
|
s->addWithLabel("ENABLE SHORTCUT TO TOGGLE FAVORITES", favorites_add_button);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([favorites_add_button, s] {
|
2020-10-31 09:01:19 +00:00
|
|
|
if (Settings::getInstance()->getBool("FavoritesAddButton") !=
|
|
|
|
favorites_add_button->getState()) {
|
|
|
|
Settings::getInstance()->setBool("FavoritesAddButton",
|
|
|
|
favorites_add_button->getState());
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2020-10-31 09:01:19 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Gamelist filters.
|
|
|
|
auto gamelist_filters = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
gamelist_filters->setState(Settings::getInstance()->getBool("GamelistFilters"));
|
|
|
|
s->addWithLabel("ENABLE GAMELIST FILTERS", gamelist_filters);
|
|
|
|
s->addSaveFunc([gamelist_filters, s] {
|
|
|
|
if (Settings::getInstance()->getBool("GamelistFilters") !=
|
|
|
|
gamelist_filters->getState()) {
|
|
|
|
Settings::getInstance()->setBool("GamelistFilters", gamelist_filters->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
s->setNeedsReloading();
|
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Quick system select (navigate left/right in gamelist view).
|
|
|
|
auto quick_system_select = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
quick_system_select->setState(Settings::getInstance()->getBool("QuickSystemSelect"));
|
|
|
|
s->addWithLabel("ENABLE QUICK SYSTEM SELECT", quick_system_select);
|
|
|
|
s->addSaveFunc([quick_system_select, s] {
|
|
|
|
if (Settings::getInstance()->getBool("QuickSystemSelect") !=
|
|
|
|
quick_system_select->getState()) {
|
|
|
|
Settings::getInstance()->setBool("QuickSystemSelect", quick_system_select->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// On-screen help prompts.
|
|
|
|
auto show_help_prompts = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
show_help_prompts->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
|
|
|
|
s->addWithLabel("DISPLAY ON-SCREEN HELP", show_help_prompts);
|
|
|
|
s->addSaveFunc([show_help_prompts, s] {
|
|
|
|
if (Settings::getInstance()->getBool("ShowHelpPrompts") != show_help_prompts->getState()) {
|
|
|
|
Settings::getInstance()->setBool("ShowHelpPrompts", show_help_prompts->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-09-13 12:28:06 +00:00
|
|
|
// Play videos immediately (overrides theme setting).
|
|
|
|
auto play_videos_immediately = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
play_videos_immediately->setState(Settings::getInstance()->getBool("PlayVideosImmediately"));
|
|
|
|
s->addWithLabel("PLAY VIDEOS IMMEDIATELY (OVERRIDE THEME)", play_videos_immediately);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([play_videos_immediately, s] {
|
|
|
|
if (Settings::getInstance()->getBool("PlayVideosImmediately") !=
|
|
|
|
play_videos_immediately->getState()) {
|
|
|
|
Settings::getInstance()->setBool("PlayVideosImmediately",
|
|
|
|
play_videos_immediately->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-09-13 12:28:06 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Screensaver.
|
|
|
|
ComponentListRow screensaver_row;
|
|
|
|
screensaver_row.elements.clear();
|
|
|
|
screensaver_row.addElement(std::make_shared<TextComponent>
|
|
|
|
(mWindow, "SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
|
|
|
|
screensaver_row.addElement(makeArrow(mWindow), false);
|
|
|
|
screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
|
|
|
|
s->addRow(screensaver_row);
|
|
|
|
|
|
|
|
mWindow->pushGui(s);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
void GuiMenu::openSoundSettings()
|
|
|
|
{
|
|
|
|
auto s = new GuiSettings(mWindow, "SOUND SETTINGS");
|
|
|
|
|
|
|
|
// TEMPORARY - Hide the volume slider on macOS until the volume control logic
|
|
|
|
// has been implemented for this operating system.
|
|
|
|
#if !defined(__APPLE__)
|
|
|
|
// System volume.
|
|
|
|
auto system_volume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
|
|
|
|
system_volume->setValue(static_cast<float>(VolumeControl::getInstance()->getVolume()));
|
|
|
|
s->addWithLabel("SYSTEM VOLUME", system_volume);
|
|
|
|
s->addSaveFunc([system_volume] {
|
|
|
|
VolumeControl::getInstance()->
|
2020-12-28 10:29:32 +00:00
|
|
|
setVolume(static_cast<int>(std::round(system_volume->getValue())));
|
2020-11-05 17:18:11 +00:00
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
2020-12-20 15:41:58 +00:00
|
|
|
// Volume for navigation sounds.
|
|
|
|
auto sound_volume_navigation =
|
|
|
|
std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
|
|
|
|
sound_volume_navigation->setValue(static_cast<float>(Settings::getInstance()->
|
|
|
|
getInt("SoundVolumeNavigation")));
|
2020-12-20 23:23:22 +00:00
|
|
|
s->addWithLabel("NAVIGATION SOUNDS VOLUME", sound_volume_navigation);
|
2020-12-20 15:41:58 +00:00
|
|
|
s->addSaveFunc([sound_volume_navigation, s] {
|
|
|
|
if (sound_volume_navigation->getValue() !=
|
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeNavigation"))) {
|
|
|
|
Settings::getInstance()->setInt("SoundVolumeNavigation",
|
|
|
|
static_cast<int>(sound_volume_navigation->getValue()));
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Volume for videos.
|
|
|
|
auto sound_volume_videos =
|
|
|
|
std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
|
|
|
|
sound_volume_videos->setValue(static_cast<float>(Settings::getInstance()->
|
|
|
|
getInt("SoundVolumeVideos")));
|
2020-12-20 23:23:22 +00:00
|
|
|
s->addWithLabel("VIDEO PLAYER VOLUME", sound_volume_videos);
|
2020-12-20 15:41:58 +00:00
|
|
|
s->addSaveFunc([sound_volume_videos, s] {
|
|
|
|
if (sound_volume_videos->getValue() !=
|
|
|
|
static_cast<float>(Settings::getInstance()->getInt("SoundVolumeVideos"))) {
|
|
|
|
Settings::getInstance()->setInt("SoundVolumeVideos",
|
|
|
|
static_cast<int>(sound_volume_videos->getValue()));
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
if (UIModeController::getInstance()->isUIModeFull()) {
|
|
|
|
// The ALSA Audio Card and Audio Device selection code is disabled at the moment.
|
|
|
|
// As PulseAudio controls the sound devices for the desktop environment, it doesn't
|
|
|
|
// make much sense to be able to select ALSA devices directly. Normally (always?)
|
|
|
|
// the selection doesn't make any difference at all. But maybe some PulseAudio
|
|
|
|
// settings could be added later on, if needed.
|
|
|
|
// The code is still active for Raspberry Pi though as I'm not sure if this is
|
|
|
|
// useful for that device.
|
|
|
|
// #if defined(__linux__)
|
|
|
|
#if defined(_RPI_)
|
|
|
|
// Audio card.
|
|
|
|
auto audio_card = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "AUDIO CARD", false);
|
|
|
|
std::vector<std::string> audio_cards;
|
|
|
|
#if defined(_RPI_)
|
|
|
|
// RPi Specific Audio Cards.
|
|
|
|
audio_cards.push_back("local");
|
|
|
|
audio_cards.push_back("hdmi");
|
|
|
|
audio_cards.push_back("both");
|
|
|
|
#endif
|
|
|
|
audio_cards.push_back("default");
|
|
|
|
audio_cards.push_back("sysdefault");
|
|
|
|
audio_cards.push_back("dmix");
|
|
|
|
audio_cards.push_back("hw");
|
|
|
|
audio_cards.push_back("plughw");
|
|
|
|
audio_cards.push_back("null");
|
|
|
|
if (Settings::getInstance()->getString("AudioCard") != "") {
|
|
|
|
if (std::find(audio_cards.begin(), audio_cards.end(),
|
|
|
|
Settings::getInstance()->getString("AudioCard")) == audio_cards.end()) {
|
|
|
|
audio_cards.push_back(Settings::getInstance()->getString("AudioCard"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto ac = audio_cards.cbegin(); ac != audio_cards.cend(); ac++)
|
|
|
|
audio_card->add(*ac, *ac, Settings::getInstance()->getString("AudioCard") == *ac);
|
|
|
|
s->addWithLabel("AUDIO CARD", audio_card);
|
|
|
|
s->addSaveFunc([audio_card, s] {
|
|
|
|
if (audio_card->getSelected() != Settings::getInstance()->getString("AudioCard")) {
|
|
|
|
Settings::getInstance()->setString("AudioCard", audio_card->getSelected());
|
|
|
|
VolumeControl::getInstance()->deinit();
|
|
|
|
VolumeControl::getInstance()->init();
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Volume control device.
|
|
|
|
auto vol_dev = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "AUDIO DEVICE", false);
|
|
|
|
std::vector<std::string> transitions;
|
|
|
|
transitions.push_back("PCM");
|
|
|
|
transitions.push_back("Speaker");
|
|
|
|
transitions.push_back("Master");
|
|
|
|
transitions.push_back("Digital");
|
|
|
|
transitions.push_back("Analogue");
|
|
|
|
if (Settings::getInstance()->getString("AudioDevice") != "") {
|
|
|
|
if (std::find(transitions.begin(), transitions.end(),
|
|
|
|
Settings::getInstance()->getString("AudioDevice")) == transitions.end()) {
|
|
|
|
transitions.push_back(Settings::getInstance()->getString("AudioDevice"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto it = transitions.cbegin(); it != transitions.cend(); it++)
|
|
|
|
vol_dev->add(*it, *it, Settings::getInstance()->getString("AudioDevice") == *it);
|
|
|
|
s->addWithLabel("AUDIO DEVICE", vol_dev);
|
|
|
|
s->addSaveFunc([vol_dev, s] {
|
|
|
|
if (vol_dev->getSelected() != Settings::getInstance()->getString("AudioDevice")) {
|
|
|
|
Settings::getInstance()->setString("AudioDevice", vol_dev->getSelected());
|
|
|
|
VolumeControl::getInstance()->deinit();
|
|
|
|
VolumeControl::getInstance()->init();
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(_RPI_)
|
2020-11-12 16:40:06 +00:00
|
|
|
// OMXPlayer audio device.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto omx_audio_dev = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "OMX PLAYER AUDIO DEVICE", false);
|
|
|
|
std::vector<std::string> omx_cards;
|
|
|
|
// RPi Specific Audio Cards
|
|
|
|
omx_cards.push_back("local");
|
|
|
|
omx_cards.push_back("hdmi");
|
|
|
|
omx_cards.push_back("both");
|
|
|
|
omx_cards.push_back("alsa:hw:0,0");
|
|
|
|
omx_cards.push_back("alsa:hw:1,0");
|
|
|
|
if (Settings::getInstance()->getString("OMXAudioDev") != "") {
|
|
|
|
if (std::find(omx_cards.begin(), omx_cards.end(),
|
|
|
|
Settings::getInstance()->getString("OMXAudioDev")) == omx_cards.end()) {
|
|
|
|
omx_cards.push_back(Settings::getInstance()->getString("OMXAudioDev"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto it = omx_cards.cbegin(); it != omx_cards.cend(); it++)
|
|
|
|
omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it);
|
|
|
|
s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev);
|
|
|
|
s->addSaveFunc([omx_audio_dev, s] {
|
|
|
|
if (omx_audio_dev->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("OMXAudioDev")) {
|
|
|
|
Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Video audio.
|
|
|
|
auto gamelist_video_audio = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
gamelist_video_audio->setState(Settings::getInstance()->getBool("GamelistVideoAudio"));
|
2020-12-31 16:56:53 +00:00
|
|
|
s->addWithLabel("PLAY AUDIO FOR VIDEOS IN THE GAMELIST VIEW", gamelist_video_audio);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([gamelist_video_audio, s] {
|
|
|
|
if (gamelist_video_audio->getState() !=
|
|
|
|
Settings::getInstance()->getBool("GamelistVideoAudio")) {
|
|
|
|
Settings::getInstance()->setBool("GamelistVideoAudio",
|
|
|
|
gamelist_video_audio->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Navigation sounds.
|
|
|
|
auto navigation_sounds = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
navigation_sounds->setState(Settings::getInstance()->
|
|
|
|
getBool("NavigationSounds"));
|
|
|
|
s->addWithLabel("ENABLE NAVIGATION SOUNDS", navigation_sounds);
|
|
|
|
s->addSaveFunc([navigation_sounds, s] {
|
|
|
|
if (navigation_sounds->getState() !=
|
|
|
|
Settings::getInstance()->getBool("NavigationSounds")) {
|
|
|
|
Settings::getInstance()->setBool("NavigationSounds",
|
|
|
|
navigation_sounds->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::openOtherSettings()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
auto s = new GuiSettings(mWindow, "OTHER SETTINGS");
|
|
|
|
|
|
|
|
// Maximum VRAM.
|
2020-08-08 20:33:27 +00:00
|
|
|
auto max_vram = std::make_shared<SliderComponent>(mWindow, 80.f, 1024.f, 8.f, "MiB");
|
2020-11-05 17:18:11 +00:00
|
|
|
max_vram->setValue(static_cast<float>(Settings::getInstance()->getInt("MaxVRAM")));
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addWithLabel("VRAM LIMIT", max_vram);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([max_vram, s] {
|
|
|
|
if (max_vram->getValue() != Settings::getInstance()->getInt("MaxVRAM")) {
|
|
|
|
Settings::getInstance()->setInt("MaxVRAM",
|
2020-12-28 10:29:32 +00:00
|
|
|
static_cast<int>(std::round(max_vram->getValue())));
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2021-01-24 22:44:50 +00:00
|
|
|
// Display/monitor.
|
|
|
|
auto display_index = std::make_shared<OptionListComponent<std::string>>
|
2021-01-24 22:54:43 +00:00
|
|
|
(mWindow, getHelpStyle(), "DISPLAY/MONITOR INDEX", false);
|
2021-01-24 22:44:50 +00:00
|
|
|
std::vector<std::string> displayIndex;
|
|
|
|
displayIndex.push_back("1");
|
|
|
|
displayIndex.push_back("2");
|
|
|
|
displayIndex.push_back("3");
|
|
|
|
displayIndex.push_back("4");
|
|
|
|
for (auto it = displayIndex.cbegin(); it != displayIndex.cend(); it++)
|
|
|
|
display_index->add(*it, *it,
|
|
|
|
Settings::getInstance()->getInt("DisplayIndex") == atoi((*it).c_str()));
|
2021-01-24 22:54:43 +00:00
|
|
|
s->addWithLabel("DISPLAY/MONITOR INDEX (REQUIRES RESTART)", display_index);
|
2021-01-24 22:44:50 +00:00
|
|
|
s->addSaveFunc([display_index, s] {
|
|
|
|
if (atoi(display_index->getSelected().c_str()) !=
|
|
|
|
Settings::getInstance()->getInt("DisplayIndex")) {
|
|
|
|
Settings::getInstance()->setInt("DisplayIndex",
|
|
|
|
atoi(display_index->getSelected().c_str()));
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-08-23 15:04:30 +00:00
|
|
|
#if defined(__unix__)
|
2020-06-21 12:25:28 +00:00
|
|
|
// Fullscreen mode.
|
|
|
|
auto fullscreen_mode = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "FULLSCREEN MODE", false);
|
|
|
|
std::vector<std::string> screenmode;
|
|
|
|
screenmode.push_back("normal");
|
|
|
|
screenmode.push_back("borderless");
|
|
|
|
for (auto it = screenmode.cbegin(); it != screenmode.cend(); it++)
|
|
|
|
fullscreen_mode->add(*it, *it, Settings::getInstance()->getString("FullscreenMode") == *it);
|
|
|
|
s->addWithLabel("FULLSCREEN MODE (REQUIRES RESTART)", fullscreen_mode);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([fullscreen_mode, s] {
|
|
|
|
if (fullscreen_mode->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("FullscreenMode")) {
|
|
|
|
Settings::getInstance()->setString("FullscreenMode", fullscreen_mode->getSelected());
|
|
|
|
s->setNeedsSaving();
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// When to save game metadata.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto save_gamelist_mode = std::make_shared<OptionListComponent<std::string>>
|
|
|
|
(mWindow, getHelpStyle(), "WHEN TO SAVE METADATA", false);
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<std::string> saveModes;
|
|
|
|
saveModes.push_back("on exit");
|
|
|
|
saveModes.push_back("always");
|
|
|
|
saveModes.push_back("never");
|
2020-07-15 16:02:11 +00:00
|
|
|
for (auto it = saveModes.cbegin(); it != saveModes.cend(); it++) {
|
2020-11-05 17:18:11 +00:00
|
|
|
save_gamelist_mode->add(*it, *it, Settings::getInstance()->
|
2020-06-21 12:25:28 +00:00
|
|
|
getString("SaveGamelistsMode") == *it);
|
2020-07-15 16:02:11 +00:00
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addWithLabel("WHEN TO SAVE GAME METADATA", save_gamelist_mode);
|
|
|
|
s->addSaveFunc([save_gamelist_mode, s] {
|
|
|
|
if (save_gamelist_mode->getSelected() !=
|
|
|
|
Settings::getInstance()->getString("SaveGamelistsMode")) {
|
2020-10-19 15:16:57 +00:00
|
|
|
Settings::getInstance()->setString("SaveGamelistsMode",
|
2020-11-05 17:18:11 +00:00
|
|
|
save_gamelist_mode->getSelected());
|
2020-10-19 15:16:57 +00:00
|
|
|
// Always save the gamelist.xml files if switching to 'always' as there may
|
|
|
|
// be changes that will otherwise be lost.
|
|
|
|
if (Settings::getInstance()->getString("SaveGamelistsMode") == "always") {
|
|
|
|
for (auto it = SystemData::sSystemVector.cbegin();
|
|
|
|
it != SystemData::sSystemVector.cend(); it++)
|
|
|
|
(*it)->writeMetaData();
|
|
|
|
}
|
2020-11-05 17:18:11 +00:00
|
|
|
s->setNeedsSaving();
|
2020-10-19 15:16:57 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
});
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
// Game media directory.
|
2020-12-15 17:42:38 +00:00
|
|
|
ComponentListRow rowMediaDir;
|
2020-11-05 17:18:11 +00:00
|
|
|
auto media_directory = std::make_shared<TextComponent>(mWindow, "GAME MEDIA DIRECTORY",
|
2020-07-15 16:02:11 +00:00
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
2020-12-15 17:42:38 +00:00
|
|
|
auto bracketMediaDirectory = std::make_shared<ImageComponent>(mWindow);
|
|
|
|
bracketMediaDirectory->setImage(":/graphics/arrow.svg");
|
|
|
|
bracketMediaDirectory->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()));
|
|
|
|
rowMediaDir.addElement(media_directory, true);
|
|
|
|
rowMediaDir.addElement(bracketMediaDirectory, false);
|
|
|
|
std::string titleMediaDir = "ENTER GAME MEDIA DIRECTORY";
|
2020-07-15 16:02:11 +00:00
|
|
|
std::string mediaDirectoryStaticText = "Default directory:";
|
|
|
|
std::string defaultDirectoryText = "~/.emulationstation/downloaded_media/";
|
2020-12-15 17:42:38 +00:00
|
|
|
std::string initValueMediaDir = Settings::getInstance()->getString("MediaDirectory");
|
|
|
|
bool multiLineMediaDir = false;
|
|
|
|
auto updateValMediaDir = [this](const std::string& newVal) {
|
2020-07-15 16:02:11 +00:00
|
|
|
Settings::getInstance()->setString("MediaDirectory", newVal);
|
|
|
|
Settings::getInstance()->saveFile();
|
|
|
|
ViewController::get()->reloadAll();
|
2020-11-05 17:18:11 +00:00
|
|
|
mWindow->invalidateCachedBackground();
|
2020-07-15 16:02:11 +00:00
|
|
|
};
|
2020-12-15 17:42:38 +00:00
|
|
|
rowMediaDir.makeAcceptInputHandler([this, titleMediaDir, mediaDirectoryStaticText,
|
|
|
|
defaultDirectoryText, initValueMediaDir, updateValMediaDir, multiLineMediaDir] {
|
|
|
|
mWindow->pushGui(new GuiComplexTextEditPopup(mWindow, getHelpStyle(),
|
|
|
|
titleMediaDir, mediaDirectoryStaticText, defaultDirectoryText,
|
2020-07-15 16:02:11 +00:00
|
|
|
Settings::getInstance()->getString("MediaDirectory"),
|
2020-12-15 17:42:38 +00:00
|
|
|
updateValMediaDir, multiLineMediaDir, "SAVE", "SAVE CHANGES?"));
|
2020-07-15 16:02:11 +00:00
|
|
|
});
|
2020-12-15 17:42:38 +00:00
|
|
|
s->addRow(rowMediaDir);
|
|
|
|
|
|
|
|
// Emulator core path.
|
|
|
|
ComponentListRow rowCorePath;
|
|
|
|
auto emulator_core_path = std::make_shared<TextComponent>(mWindow, "EMULATOR CORE PATH",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
|
|
|
|
auto bracketCorePath = std::make_shared<ImageComponent>(mWindow);
|
|
|
|
bracketCorePath->setImage(":/graphics/arrow.svg");
|
|
|
|
bracketCorePath->setResize(Vector2f(0, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()));
|
|
|
|
rowCorePath.addElement(emulator_core_path, true);
|
|
|
|
rowCorePath.addElement(bracketCorePath, false);
|
2020-12-20 13:30:31 +00:00
|
|
|
#if defined(_WIN64)
|
|
|
|
std::string titleCorePath = "ENTER EMULATOR CORE PATH (USE SEMICOLON AS SEPARATOR)";
|
|
|
|
#else
|
2020-12-15 17:42:38 +00:00
|
|
|
std::string titleCorePath = "ENTER EMULATOR CORE PATH (USE COLON AS SEPARATOR)";
|
2020-12-20 13:30:31 +00:00
|
|
|
#endif
|
2020-12-15 17:42:38 +00:00
|
|
|
std::string emulatorCorePathStaticText = "Default path:";
|
|
|
|
std::string defaultEmulatorCorePath = Settings::getInstance()->
|
|
|
|
getDefaultString("EmulatorCorePath");
|
|
|
|
if (defaultEmulatorCorePath == "")
|
|
|
|
defaultEmulatorCorePath = "<No default path defined>";
|
|
|
|
std::string initValueCorePath = Settings::getInstance()->getString("EmulatorCorePath");
|
|
|
|
bool multiLineCorePath = false;
|
|
|
|
auto updateValCorePath = [this](const std::string& newVal) {
|
|
|
|
Settings::getInstance()->setString("EmulatorCorePath", newVal);
|
|
|
|
Settings::getInstance()->saveFile();
|
|
|
|
};
|
|
|
|
rowCorePath.makeAcceptInputHandler([this, titleCorePath, emulatorCorePathStaticText,
|
|
|
|
defaultEmulatorCorePath, initValueCorePath, updateValCorePath, multiLineCorePath] {
|
|
|
|
mWindow->pushGui(new GuiComplexTextEditPopup(mWindow, getHelpStyle(),
|
|
|
|
titleCorePath, emulatorCorePathStaticText, defaultEmulatorCorePath,
|
|
|
|
Settings::getInstance()->getString("EmulatorCorePath"),
|
|
|
|
updateValCorePath, multiLineCorePath, "SAVE", "SAVE CHANGES?"));
|
|
|
|
});
|
|
|
|
s->addRow(rowCorePath);
|
2020-07-15 16:02:11 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
#if defined(_RPI_)
|
2020-11-12 16:40:06 +00:00
|
|
|
// Video playing using OMXPlayer.
|
2020-11-05 17:18:11 +00:00
|
|
|
auto video_omx_player = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
video_omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer"));
|
|
|
|
s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", video_omx_player);
|
|
|
|
s->addSaveFunc([video_omx_player, s] {
|
|
|
|
if (video_omx_player->getState() !=
|
|
|
|
Settings::getInstance()->getBool("VideoOmxPlayer")) {
|
|
|
|
Settings::getInstance()->setBool("VideoOmxPlayer", video_omx_player->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
// Need to reload all views to re-create the right video components.
|
|
|
|
s->setNeedsReloading();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
#endif
|
|
|
|
|
2020-08-23 15:04:30 +00:00
|
|
|
#if defined(_WIN64)
|
2020-11-05 17:18:11 +00:00
|
|
|
// Hide taskbar during the ES program session.
|
2020-07-18 11:21:44 +00:00
|
|
|
auto hide_taskbar = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
hide_taskbar->setState(Settings::getInstance()->getBool("HideTaskbar"));
|
|
|
|
s->addWithLabel("HIDE TASKBAR (REQUIRES RESTART)", hide_taskbar);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([hide_taskbar, s] {
|
|
|
|
if (hide_taskbar->getState() !=
|
|
|
|
Settings::getInstance()->getBool("HideTaskbar")) {
|
|
|
|
Settings::getInstance()-> setBool("HideTaskbar", hide_taskbar->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-07-19 20:08:14 +00:00
|
|
|
|
|
|
|
// Run ES in the background when a game has been launched.
|
|
|
|
auto run_in_background = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
run_in_background->setState(Settings::getInstance()->getBool("RunInBackground"));
|
|
|
|
s->addWithLabel("RUN IN BACKGROUND (WHILE GAME IS LAUNCHED)", run_in_background);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([run_in_background,s] {
|
|
|
|
if (run_in_background->getState() != Settings::getInstance()->getBool("RunInBackground")) {
|
|
|
|
Settings::getInstance()->setBool("RunInBackground", run_in_background->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-07-18 11:21:44 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
// Allow overriding of the launch command per game (the option to disable this is
|
|
|
|
// intended primarily for testing purposes).
|
2020-07-08 15:06:34 +00:00
|
|
|
auto launchcommand_override = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
launchcommand_override->setState(Settings::getInstance()->getBool("LaunchCommandOverride"));
|
2020-07-09 17:24:20 +00:00
|
|
|
s->addWithLabel("PER GAME LAUNCH COMMAND OVERRIDE", launchcommand_override);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([launchcommand_override, s] {
|
|
|
|
if (launchcommand_override->getState() !=
|
|
|
|
Settings::getInstance()->getBool("LaunchCommandOverride")) {
|
|
|
|
Settings::getInstance()->
|
|
|
|
setBool("LaunchCommandOverride", launchcommand_override->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Show hidden files.
|
|
|
|
auto show_hidden_files = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
show_hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles"));
|
|
|
|
s->addWithLabel("SHOW HIDDEN FILES AND FOLDERS (REQUIRES RESTART)", show_hidden_files);
|
|
|
|
s->addSaveFunc([show_hidden_files, s] {
|
|
|
|
if (show_hidden_files->getState() != Settings::getInstance()->getBool("ShowHiddenFiles")) {
|
|
|
|
Settings::getInstance()->setBool("ShowHiddenFiles", show_hidden_files->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-07-26 20:19:29 +00:00
|
|
|
|
2020-11-05 17:18:11 +00:00
|
|
|
// Show hidden games.
|
|
|
|
auto show_hidden_games = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
show_hidden_games->setState(Settings::getInstance()->getBool("ShowHiddenGames"));
|
|
|
|
s->addWithLabel("SHOW HIDDEN GAMES (REQUIRES RESTART)", show_hidden_games);
|
|
|
|
s->addSaveFunc([show_hidden_games, s] {
|
|
|
|
if (show_hidden_games->getState() != Settings::getInstance()->getBool("ShowHiddenGames")) {
|
|
|
|
Settings::getInstance()->setBool("ShowHiddenGames", show_hidden_games->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
2020-07-26 20:19:29 +00:00
|
|
|
});
|
|
|
|
|
2020-07-15 16:02:11 +00:00
|
|
|
// Custom event scripts, fired using Scripting::fireEvent().
|
2020-07-09 17:24:20 +00:00
|
|
|
auto custom_eventscripts = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
custom_eventscripts->setState(Settings::getInstance()->getBool("CustomEventScripts"));
|
2020-10-31 09:01:19 +00:00
|
|
|
s->addWithLabel("ENABLE CUSTOM EVENT SCRIPTS", custom_eventscripts);
|
2020-11-05 17:18:11 +00:00
|
|
|
s->addSaveFunc([custom_eventscripts, s] {
|
|
|
|
if (custom_eventscripts->getState() !=
|
|
|
|
Settings::getInstance()->getBool("CustomEventScripts")) {
|
|
|
|
Settings::getInstance()->setBool("CustomEventScripts", custom_eventscripts->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Only show ROMs included in the gamelist.xml files.
|
|
|
|
auto parse_gamelist_only = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
parse_gamelist_only->setState(Settings::getInstance()->getBool("ParseGamelistOnly"));
|
|
|
|
s->addWithLabel("ONLY SHOW ROMS FROM GAMELIST.XML FILES", parse_gamelist_only);
|
|
|
|
s->addSaveFunc([parse_gamelist_only, s] {
|
|
|
|
if (parse_gamelist_only->getState() !=
|
|
|
|
Settings::getInstance()->getBool("ParseGamelistOnly")) {
|
|
|
|
Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelist_only->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Display game media from the ROM directories.
|
|
|
|
auto rom_dir_game_media = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
rom_dir_game_media->setState(Settings::getInstance()->getBool("ROMDirGameMedia"));
|
|
|
|
s->addWithLabel("DISPLAY GAME MEDIA FROM ROM DIRECTORIES", rom_dir_game_media);
|
|
|
|
s->addSaveFunc([rom_dir_game_media, s] {
|
|
|
|
if (rom_dir_game_media->getState() != Settings::getInstance()->getBool("ROMDirGameMedia")) {
|
|
|
|
Settings::getInstance()->setBool("ROMDirGameMedia", rom_dir_game_media->getState());
|
|
|
|
s->setNeedsSaving();
|
2021-01-03 10:22:30 +00:00
|
|
|
s->setNeedsReloading();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// GPU statistics overlay.
|
|
|
|
auto display_gpu_statistics = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
display_gpu_statistics->setState(Settings::getInstance()->getBool("DisplayGPUStatistics"));
|
|
|
|
s->addWithLabel("DISPLAY GPU STATISTICS OVERLAY", display_gpu_statistics);
|
|
|
|
s->addSaveFunc([display_gpu_statistics, s] {
|
|
|
|
if (display_gpu_statistics->getState() !=
|
|
|
|
Settings::getInstance()->getBool("DisplayGPUStatistics")) {
|
|
|
|
Settings::getInstance()->setBool("DisplayGPUStatistics",
|
|
|
|
display_gpu_statistics->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
// Whether to enable the menu in Kid mode.
|
|
|
|
auto enable_menu_kid_mode = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
enable_menu_kid_mode->setState(Settings::getInstance()->getBool("EnableMenuKidMode"));
|
|
|
|
s->addWithLabel("ENABLE MENU IN KID MODE", enable_menu_kid_mode);
|
|
|
|
s->addSaveFunc([enable_menu_kid_mode, s] {
|
|
|
|
if (Settings::getInstance()->getBool("EnableMenuKidMode") !=
|
|
|
|
enable_menu_kid_mode->getState()) {
|
|
|
|
Settings::getInstance()->setBool("EnableMenuKidMode", enable_menu_kid_mode->getState());
|
|
|
|
s->setNeedsSaving();
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
// macOS requires root privileges to reboot and power off so it doesn't make much
|
|
|
|
// sense to show the quit menu for this operating system.
|
|
|
|
#if !defined(__APPLE__)
|
|
|
|
// Whether to show the quit menu with the options to reboot and shutdown the computer.
|
|
|
|
auto show_quit_menu = std::make_shared<SwitchComponent>(mWindow);
|
|
|
|
show_quit_menu->setState(Settings::getInstance()->getBool("ShowQuitMenu"));
|
|
|
|
s->addWithLabel("SHOW QUIT MENU (REBOOT AND POWER OFF ENTRIES)", show_quit_menu);
|
|
|
|
s->addSaveFunc([this, show_quit_menu, s] {
|
|
|
|
if (show_quit_menu->getState() !=
|
|
|
|
Settings::getInstance()->getBool("ShowQuitMenu")) {
|
|
|
|
Settings::getInstance()->setBool("ShowQuitMenu", show_quit_menu->getState());
|
|
|
|
s->setNeedsSaving();
|
|
|
|
GuiMenu::close(false);
|
2020-11-05 17:18:11 +00:00
|
|
|
}
|
|
|
|
});
|
2020-08-23 17:17:06 +00:00
|
|
|
#endif
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
mWindow->pushGui(s);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
2017-06-01 20:08:44 +00:00
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::openConfigInput()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
Window* window = mWindow;
|
|
|
|
window->pushGui(new GuiMsgBox(window, getHelpStyle(),
|
|
|
|
"ARE YOU SURE YOU WANT TO CONFIGURE INPUT?", "YES", [window] {
|
2020-08-03 09:39:04 +00:00
|
|
|
window->pushGui(new GuiDetectDevice(window, false, false, nullptr));
|
2020-06-21 12:25:28 +00:00
|
|
|
}, "NO", nullptr)
|
|
|
|
);
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::openQuitMenu()
|
|
|
|
{
|
2020-12-17 22:45:29 +00:00
|
|
|
if (!Settings::getInstance()->getBool("ShowQuitMenu")) {
|
|
|
|
mWindow->pushGui(new GuiMsgBox(mWindow, this->getHelpStyle(),
|
|
|
|
"REALLY QUIT?", "YES", [this] {
|
|
|
|
Scripting::fireEvent("quit");
|
|
|
|
close(true);
|
|
|
|
quitES();
|
|
|
|
}, "NO", nullptr));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
auto s = new GuiSettings(mWindow, "QUIT");
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
Window* window = mWindow;
|
|
|
|
HelpStyle style = getHelpStyle();
|
2020-06-21 12:25:28 +00:00
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
// This transparent bracket is only neeeded to generate the correct help prompts.
|
|
|
|
auto bracket = std::make_shared<ImageComponent>(mWindow);
|
|
|
|
bracket->setImage(":/graphics/arrow.svg");
|
|
|
|
bracket->setOpacity(0);
|
|
|
|
|
|
|
|
ComponentListRow row;
|
|
|
|
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
|
|
|
window->pushGui(new GuiMsgBox(window, this->getHelpStyle(),
|
|
|
|
"REALLY QUIT?", "YES", [this] {
|
|
|
|
Scripting::fireEvent("quit");
|
|
|
|
close(true);
|
|
|
|
quitES();
|
|
|
|
}, "NO", nullptr));
|
|
|
|
});
|
|
|
|
row.addElement(std::make_shared<TextComponent>(window, "QUIT EMULATIONSTATION",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
|
|
|
|
row.addElement(bracket, false);
|
|
|
|
s->addRow(row);
|
2020-06-21 12:25:28 +00:00
|
|
|
|
|
|
|
row.elements.clear();
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
|
|
|
window->pushGui(new GuiMsgBox(window, this->getHelpStyle(),
|
|
|
|
"REALLY REBOOT?", "YES", [] {
|
|
|
|
Scripting::fireEvent("quit", "reboot");
|
|
|
|
Scripting::fireEvent("reboot");
|
2020-06-25 17:52:38 +00:00
|
|
|
if (quitES(QuitMode::REBOOT) != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
LOG(LogWarning) << "Reboot terminated with non-zero result!";
|
2020-06-25 17:52:38 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
}, "NO", nullptr));
|
|
|
|
});
|
|
|
|
row.addElement(std::make_shared<TextComponent>(window, "REBOOT SYSTEM",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
|
2020-12-17 22:45:29 +00:00
|
|
|
row.addElement(bracket, false);
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addRow(row);
|
|
|
|
|
|
|
|
row.elements.clear();
|
|
|
|
row.makeAcceptInputHandler([window, this] {
|
|
|
|
window->pushGui(new GuiMsgBox(window, this->getHelpStyle(),
|
|
|
|
"REALLY POWER OFF?", "YES", [] {
|
|
|
|
Scripting::fireEvent("quit", "poweroff");
|
|
|
|
Scripting::fireEvent("poweroff");
|
2020-06-25 17:52:38 +00:00
|
|
|
if (quitES(QuitMode::POWEROFF) != 0) {
|
2020-06-21 12:25:28 +00:00
|
|
|
LOG(LogWarning) << "Power off terminated with non-zero result!";
|
2020-06-25 17:52:38 +00:00
|
|
|
}
|
2020-06-21 12:25:28 +00:00
|
|
|
}, "NO", nullptr));
|
|
|
|
});
|
|
|
|
row.addElement(std::make_shared<TextComponent>(window, "POWER OFF SYSTEM",
|
|
|
|
Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
|
2020-12-17 22:45:29 +00:00
|
|
|
row.addElement(bracket, false);
|
2020-06-21 12:25:28 +00:00
|
|
|
s->addRow(row);
|
|
|
|
|
2020-12-17 22:45:29 +00:00
|
|
|
mWindow->pushGui(s);
|
|
|
|
}
|
2017-09-08 14:49:47 +00:00
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2017-09-08 14:49:47 +00:00
|
|
|
void GuiMenu::addVersionInfo()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mVersion.setFont(Font::get(FONT_SIZE_SMALL));
|
|
|
|
mVersion.setColor(0x5E5E5EFF);
|
|
|
|
mVersion.setText("EMULATIONSTATION-DE V" + Utils::String::toUpper(PROGRAM_VERSION_STRING));
|
|
|
|
mVersion.setHorizontalAlignment(ALIGN_CENTER);
|
|
|
|
addChild(&mVersion);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 19:27:41 +00:00
|
|
|
void GuiMenu::openScreensaverOptions()
|
|
|
|
{
|
2020-11-05 17:35:08 +00:00
|
|
|
mWindow->pushGui(new GuiScreensaverOptions(mWindow, "SCREENSAVER SETTINGS"));
|
2017-06-12 16:38:59 +00:00
|
|
|
}
|
|
|
|
|
2020-11-06 19:27:41 +00:00
|
|
|
void GuiMenu::openCollectionSystemSettings()
|
|
|
|
{
|
|
|
|
mWindow->pushGui(new GuiCollectionSystemsOptions(mWindow, "GAME COLLECTION SETTINGS"));
|
2017-06-01 20:08:44 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
void GuiMenu::onSizeChanged()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mVersion.setSize(mSize.x(), 0);
|
|
|
|
mVersion.setPosition(0, mSize.y() - mVersion.getSize().y());
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 22:59:00 +00:00
|
|
|
void GuiMenu::addEntry(const std::string& name, unsigned int color,
|
2020-06-21 12:25:28 +00:00
|
|
|
bool add_arrow, const std::function<void()>& func)
|
2014-06-25 16:29:58 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
|
2017-03-25 17:02:28 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
// Populate the list.
|
|
|
|
ComponentListRow row;
|
|
|
|
row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (add_arrow) {
|
|
|
|
std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
|
|
|
|
row.addElement(bracket, false);
|
|
|
|
}
|
2017-03-25 17:02:28 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
row.makeAcceptInputHandler(func);
|
|
|
|
mMenu.addRow(row);
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 18:03:31 +00:00
|
|
|
void GuiMenu::close(bool closeAllWindows)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::function<void()> closeFunc;
|
|
|
|
if (!closeAllWindows) {
|
|
|
|
closeFunc = [this] { delete this; };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Window* window = mWindow;
|
|
|
|
closeFunc = [window, this] {
|
|
|
|
while (window->peekGui() != ViewController::get())
|
|
|
|
delete window->peekGui();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
closeFunc();
|
2020-06-09 18:03:31 +00:00
|
|
|
}
|
|
|
|
|
2014-06-25 16:29:58 +00:00
|
|
|
bool GuiMenu::input(InputConfig* config, Input input)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
if (GuiComponent::input(config, input))
|
|
|
|
return true;
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
const bool isStart = config->isMappedTo("start", input);
|
|
|
|
if (input.value != 0 && (config->isMappedTo("b", input) || isStart)) {
|
|
|
|
close(isStart);
|
|
|
|
return true;
|
|
|
|
}
|
2014-06-25 16:29:58 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return false;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<HelpPrompt> GuiMenu::getHelpPrompts()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
std::vector<HelpPrompt> prompts;
|
|
|
|
prompts.push_back(HelpPrompt("up/down", "choose"));
|
|
|
|
prompts.push_back(HelpPrompt("a", "select"));
|
|
|
|
prompts.push_back(HelpPrompt("b", "close menu"));
|
|
|
|
prompts.push_back(HelpPrompt("start", "close menu"));
|
|
|
|
return prompts;
|
2014-06-25 16:29:58 +00:00
|
|
|
}
|
2020-06-07 18:09:02 +00:00
|
|
|
|
|
|
|
HelpStyle GuiMenu::getHelpStyle()
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
HelpStyle style = HelpStyle();
|
|
|
|
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
|
|
|
|
return style;
|
2020-06-07 18:09:02 +00:00
|
|
|
}
|