1 #include "guis/GuiMenu.h"
2 
3 #include "components/OptionListComponent.h"
4 #include "components/SliderComponent.h"
5 #include "components/SwitchComponent.h"
6 #include "guis/GuiCollectionSystemsOptions.h"
7 #include "guis/GuiDetectDevice.h"
8 #include "guis/GuiGeneralScreensaverOptions.h"
9 #include "guis/GuiMsgBox.h"
10 #include "guis/GuiScraperStart.h"
11 #include "guis/GuiSettings.h"
12 #include "views/UIModeController.h"
13 #include "views/ViewController.h"
14 #include "CollectionSystemManager.h"
15 #include "EmulationStation.h"
16 #include "Scripting.h"
17 #include "SystemData.h"
18 #include "VolumeControl.h"
19 #include <SDL_events.h>
20 #include <algorithm>
21 #include "platform.h"
22 
GuiMenu(Window * window)23 GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MENU"), mVersion(window)
24 {
25 	bool isFullUI = UIModeController::getInstance()->isUIModeFull();
26 
27 	if (isFullUI)
28 		addEntry("SCRAPER", 0x777777FF, true, [this] { openScraperSettings(); });
29 
30 	addEntry("SOUND SETTINGS", 0x777777FF, true, [this] { openSoundSettings(); });
31 
32 
33 	if (isFullUI)
34 		addEntry("UI SETTINGS", 0x777777FF, true, [this] { openUISettings(); });
35 
36 	if (isFullUI)
37 		addEntry("GAME COLLECTION SETTINGS", 0x777777FF, true, [this] { openCollectionSystemSettings(); });
38 
39 	if (isFullUI)
40 		addEntry("OTHER SETTINGS", 0x777777FF, true, [this] { openOtherSettings(); });
41 
42 	if (isFullUI)
43 		addEntry("CONFIGURE INPUT", 0x777777FF, true, [this] { openConfigInput(); });
44 
45 	addEntry("QUIT", 0x777777FF, true, [this] {openQuitMenu(); });
46 
47 	addChild(&mMenu);
48 	addVersionInfo();
49 	setSize(mMenu.getSize());
50 	setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, Renderer::getScreenHeight() * 0.15f);
51 }
52 
openScraperSettings()53 void GuiMenu::openScraperSettings()
54 {
55 	auto s = new GuiSettings(mWindow, "SCRAPER");
56 
57 	// scrape from
58 	auto scraper_list = std::make_shared< OptionListComponent< std::string > >(mWindow, "SCRAPE FROM", false);
59 	std::vector<std::string> scrapers = getScraperList();
60 
61 	// Select either the first entry of the one read from the settings, just in case the scraper from settings has vanished.
62 	for(auto it = scrapers.cbegin(); it != scrapers.cend(); it++)
63 		scraper_list->add(*it, *it, *it == Settings::getInstance()->getString("Scraper"));
64 
65 	s->addWithLabel("SCRAPE FROM", scraper_list);
66 	s->addSaveFunc([scraper_list] { Settings::getInstance()->setString("Scraper", scraper_list->getSelected()); });
67 
68 	// scrape ratings
69 	auto scrape_ratings = std::make_shared<SwitchComponent>(mWindow);
70 	scrape_ratings->setState(Settings::getInstance()->getBool("ScrapeRatings"));
71 	s->addWithLabel("SCRAPE RATINGS", scrape_ratings);
72 	s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings", scrape_ratings->getState()); });
73 
74 	// scrape now
75 	ComponentListRow row;
76 	auto openScrapeNow = [this] { mWindow->pushGui(new GuiScraperStart(mWindow)); };
77 	std::function<void()> openAndSave = openScrapeNow;
78 	openAndSave = [s, openAndSave] { s->save(); openAndSave(); };
79 	row.makeAcceptInputHandler(openAndSave);
80 
81 	auto scrape_now = std::make_shared<TextComponent>(mWindow, "SCRAPE NOW", Font::get(FONT_SIZE_MEDIUM), 0x777777FF);
82 	auto bracket = makeArrow(mWindow);
83 	row.addElement(scrape_now, true);
84 	row.addElement(bracket, false);
85 	s->addRow(row);
86 
87 	mWindow->pushGui(s);
88 }
89 
openSoundSettings()90 void GuiMenu::openSoundSettings()
91 {
92 	auto s = new GuiSettings(mWindow, "SOUND SETTINGS");
93 
94 	// volume
95 	auto volume = std::make_shared<SliderComponent>(mWindow, 0.f, 100.f, 1.f, "%");
96 	volume->setValue((float)VolumeControl::getInstance()->getVolume());
97 	s->addWithLabel("SYSTEM VOLUME", volume);
98 	s->addSaveFunc([volume] { VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); });
99 
100 	if (UIModeController::getInstance()->isUIModeFull())
101 	{
102 #if defined(__linux__)
103 		// audio card
104 		auto audio_card = std::make_shared< OptionListComponent<std::string> >(mWindow, "AUDIO CARD", false);
105 		std::vector<std::string> audio_cards;
106 		audio_cards.push_back("default");
107 		audio_cards.push_back("sysdefault");
108 		audio_cards.push_back("dmix");
109 		audio_cards.push_back("hw");
110 		audio_cards.push_back("plughw");
111 		audio_cards.push_back("null");
112 		if (Settings::getInstance()->getString("AudioCard") != "") {
113 			if(std::find(audio_cards.begin(), audio_cards.end(), Settings::getInstance()->getString("AudioCard")) == audio_cards.end()) {
114 				audio_cards.push_back(Settings::getInstance()->getString("AudioCard"));
115 			}
116 		}
117 		for(auto ac = audio_cards.cbegin(); ac != audio_cards.cend(); ac++)
118 			audio_card->add(*ac, *ac, Settings::getInstance()->getString("AudioCard") == *ac);
119 		s->addWithLabel("AUDIO CARD", audio_card);
120 		s->addSaveFunc([audio_card] {
121 			Settings::getInstance()->setString("AudioCard", audio_card->getSelected());
122 			VolumeControl::getInstance()->deinit();
123 			VolumeControl::getInstance()->init();
124 		});
125 
126 		// volume control device
127 		auto vol_dev = std::make_shared< OptionListComponent<std::string> >(mWindow, "AUDIO DEVICE", false);
128 		std::vector<std::string> transitions;
129 		transitions.push_back("PCM");
130 		transitions.push_back("HDMI");
131 		transitions.push_back("Headphone");
132 		transitions.push_back("Speaker");
133 		transitions.push_back("Master");
134 		transitions.push_back("Digital");
135 		transitions.push_back("Analogue");
136 		if (Settings::getInstance()->getString("AudioDevice") != "") {
137 			if(std::find(transitions.begin(), transitions.end(), Settings::getInstance()->getString("AudioDevice")) == transitions.end()) {
138 				transitions.push_back(Settings::getInstance()->getString("AudioDevice"));
139 			}
140 		}
141 		for(auto it = transitions.cbegin(); it != transitions.cend(); it++)
142 			vol_dev->add(*it, *it, Settings::getInstance()->getString("AudioDevice") == *it);
143 		s->addWithLabel("AUDIO DEVICE", vol_dev);
144 		s->addSaveFunc([vol_dev] {
145 			Settings::getInstance()->setString("AudioDevice", vol_dev->getSelected());
146 			VolumeControl::getInstance()->deinit();
147 			VolumeControl::getInstance()->init();
148 		});
149 #endif
150 
151 		// disable sounds
152 		auto sounds_enabled = std::make_shared<SwitchComponent>(mWindow);
153 		sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds"));
154 		s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled);
155 		s->addSaveFunc([sounds_enabled] {
156 			if (sounds_enabled->getState()
157 				&& !Settings::getInstance()->getBool("EnableSounds")
158 				&& PowerSaver::getMode() == PowerSaver::INSTANT)
159 			{
160 				Settings::getInstance()->setString("PowerSaverMode", "default");
161 				PowerSaver::init();
162 			}
163 			Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState());
164 		});
165 
166 		auto video_audio = std::make_shared<SwitchComponent>(mWindow);
167 		video_audio->setState(Settings::getInstance()->getBool("VideoAudio"));
168 		s->addWithLabel("ENABLE VIDEO AUDIO", video_audio);
169 		s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); });
170 
171 #ifdef _RPI_
172 		// OMX player Audio Device
173 		auto omx_audio_dev = std::make_shared< OptionListComponent<std::string> >(mWindow, "OMX PLAYER AUDIO DEVICE", false);
174 		std::vector<std::string> omx_cards;
175 		// RPi Specific  Audio Cards
176 		omx_cards.push_back("local");
177 		omx_cards.push_back("hdmi");
178 		omx_cards.push_back("both");
179 		omx_cards.push_back("alsa");
180 		omx_cards.push_back("alsa:hw:0,0");
181 		omx_cards.push_back("alsa:hw:1,0");
182 		if (Settings::getInstance()->getString("OMXAudioDev") != "") {
183 			if (std::find(omx_cards.begin(), omx_cards.end(), Settings::getInstance()->getString("OMXAudioDev")) == omx_cards.end()) {
184 				omx_cards.push_back(Settings::getInstance()->getString("OMXAudioDev"));
185 			}
186 		}
187 		for (auto it = omx_cards.cbegin(); it != omx_cards.cend(); it++)
188 			omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it);
189 		s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev);
190 		s->addSaveFunc([omx_audio_dev] {
191 			if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected())
192 				Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected());
193 		});
194 #endif
195 	}
196 
197 	mWindow->pushGui(s);
198 
199 }
200 
openUISettings()201 void GuiMenu::openUISettings()
202 {
203 	auto s = new GuiSettings(mWindow, "UI SETTINGS");
204 
205 	//UI mode
206 	auto UImodeSelection = std::make_shared< OptionListComponent<std::string> >(mWindow, "UI MODE", false);
207 	std::vector<std::string> UImodes = UIModeController::getInstance()->getUIModes();
208 	for (auto it = UImodes.cbegin(); it != UImodes.cend(); it++)
209 		UImodeSelection->add(*it, *it, Settings::getInstance()->getString("UIMode") == *it);
210 	s->addWithLabel("UI MODE", UImodeSelection);
211 	Window* window = mWindow;
212 	s->addSaveFunc([ UImodeSelection, window]
213 	{
214 		std::string selectedMode = UImodeSelection->getSelected();
215 		if (selectedMode != "Full")
216 		{
217 			std::string msg = "You are changing the UI to a restricted mode:\n" + selectedMode + "\n";
218 			msg += "This will hide most menu-options to prevent changes to the system.\n";
219 			msg += "To unlock and return to the full UI, enter this code: \n";
220 			msg += "\"" + UIModeController::getInstance()->getFormattedPassKeyStr() + "\"\n\n";
221 			msg += "Do you want to proceed?";
222 			window->pushGui(new GuiMsgBox(window, msg,
223 				"YES", [selectedMode] {
224 					LOG(LogDebug) << "Setting UI mode to " << selectedMode;
225 					Settings::getInstance()->setString("UIMode", selectedMode);
226 					Settings::getInstance()->saveFile();
227 			}, "NO",nullptr));
228 		}
229 	});
230 
231 	// screensaver
232 	ComponentListRow screensaver_row;
233 	screensaver_row.elements.clear();
234 	screensaver_row.addElement(std::make_shared<TextComponent>(mWindow, "SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
235 	screensaver_row.addElement(makeArrow(mWindow), false);
236 	screensaver_row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
237 	s->addRow(screensaver_row);
238 
239 	// quick system select (left/right in game list view)
240 	auto quick_sys_select = std::make_shared<SwitchComponent>(mWindow);
241 	quick_sys_select->setState(Settings::getInstance()->getBool("QuickSystemSelect"));
242 	s->addWithLabel("QUICK SYSTEM SELECT", quick_sys_select);
243 	s->addSaveFunc([quick_sys_select] { Settings::getInstance()->setBool("QuickSystemSelect", quick_sys_select->getState()); });
244 
245 	// carousel transition option
246 	auto move_carousel = std::make_shared<SwitchComponent>(mWindow);
247 	move_carousel->setState(Settings::getInstance()->getBool("MoveCarousel"));
248 	s->addWithLabel("CAROUSEL TRANSITIONS", move_carousel);
249 	s->addSaveFunc([move_carousel] {
250 		if (move_carousel->getState()
251 			&& !Settings::getInstance()->getBool("MoveCarousel")
252 			&& PowerSaver::getMode() == PowerSaver::INSTANT)
253 		{
254 			Settings::getInstance()->setString("PowerSaverMode", "default");
255 			PowerSaver::init();
256 		}
257 		Settings::getInstance()->setBool("MoveCarousel", move_carousel->getState());
258 	});
259 
260 	// transition style
261 	auto transition_style = std::make_shared< OptionListComponent<std::string> >(mWindow, "TRANSITION STYLE", false);
262 	std::vector<std::string> transitions;
263 	transitions.push_back("fade");
264 	transitions.push_back("slide");
265 	transitions.push_back("instant");
266 	for(auto it = transitions.cbegin(); it != transitions.cend(); it++)
267 		transition_style->add(*it, *it, Settings::getInstance()->getString("TransitionStyle") == *it);
268 	s->addWithLabel("TRANSITION STYLE", transition_style);
269 	s->addSaveFunc([transition_style] {
270 		if (Settings::getInstance()->getString("TransitionStyle") == "instant"
271 			&& transition_style->getSelected() != "instant"
272 			&& PowerSaver::getMode() == PowerSaver::INSTANT)
273 		{
274 			Settings::getInstance()->setString("PowerSaverMode", "default");
275 			PowerSaver::init();
276 		}
277 		Settings::getInstance()->setString("TransitionStyle", transition_style->getSelected());
278 	});
279 
280 	// theme set
281 	auto themeSets = ThemeData::getThemeSets();
282 
283 	if(!themeSets.empty())
284 	{
285 		std::map<std::string, ThemeSet>::const_iterator selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet"));
286 		if(selectedSet == themeSets.cend())
287 			selectedSet = themeSets.cbegin();
288 
289 		auto theme_set = std::make_shared< OptionListComponent<std::string> >(mWindow, "THEME SET", false);
290 		for(auto it = themeSets.cbegin(); it != themeSets.cend(); it++)
291 			theme_set->add(it->first, it->first, it == selectedSet);
292 		s->addWithLabel("THEME SET", theme_set);
293 
294 		Window* window = mWindow;
295 		s->addSaveFunc([window, theme_set]
296 		{
297 			bool needReload = false;
298 			std::string oldTheme = Settings::getInstance()->getString("ThemeSet");
299 			if(oldTheme != theme_set->getSelected())
300 				needReload = true;
301 
302 			Settings::getInstance()->setString("ThemeSet", theme_set->getSelected());
303 
304 			if(needReload)
305 			{
306 				Scripting::fireEvent("theme-changed", theme_set->getSelected(), oldTheme);
307 				CollectionSystemManager::get()->updateSystemsList();
308 				ViewController::get()->goToStart();
309 				ViewController::get()->reloadAll(); // TODO - replace this with some sort of signal-based implementation
310 			}
311 		});
312 	}
313 
314 	// GameList view style
315 	auto gamelist_style = std::make_shared< OptionListComponent<std::string> >(mWindow, "GAMELIST VIEW STYLE", false);
316 	std::vector<std::string> styles;
317 	styles.push_back("automatic");
318 	styles.push_back("basic");
319 	styles.push_back("detailed");
320 	styles.push_back("video");
321 	styles.push_back("grid");
322 
323 	for (auto it = styles.cbegin(); it != styles.cend(); it++)
324 		gamelist_style->add(*it, *it, Settings::getInstance()->getString("GamelistViewStyle") == *it);
325 	s->addWithLabel("GAMELIST VIEW STYLE", gamelist_style);
326 	s->addSaveFunc([gamelist_style] {
327 		bool needReload = false;
328 		if (Settings::getInstance()->getString("GamelistViewStyle") != gamelist_style->getSelected())
329 			needReload = true;
330 		Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected());
331 		if (needReload)
332 			ViewController::get()->reloadAll();
333 	});
334 
335 	// Optionally start in selected system
336 	auto systemfocus_list = std::make_shared< OptionListComponent<std::string> >(mWindow, "START ON SYSTEM", false);
337 	systemfocus_list->add("NONE", "", Settings::getInstance()->getString("StartupSystem") == "");
338 	for (auto it = SystemData::sSystemVector.cbegin(); it != SystemData::sSystemVector.cend(); it++)
339 	{
340 		if ("retropie" != (*it)->getName())
341 		{
342 			systemfocus_list->add((*it)->getName(), (*it)->getName(), Settings::getInstance()->getString("StartupSystem") == (*it)->getName());
343 		}
344 	}
345 	s->addWithLabel("START ON SYSTEM", systemfocus_list);
346 	s->addSaveFunc([systemfocus_list] {
347 		Settings::getInstance()->setString("StartupSystem", systemfocus_list->getSelected());
348 	});
349 
350 	// show help
351 	auto show_help = std::make_shared<SwitchComponent>(mWindow);
352 	show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
353 	s->addWithLabel("ON-SCREEN HELP", show_help);
354 	s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); });
355 
356 	// enable filters (ForceDisableFilters)
357 	auto enable_filter = std::make_shared<SwitchComponent>(mWindow);
358 	enable_filter->setState(!Settings::getInstance()->getBool("ForceDisableFilters"));
359 	s->addWithLabel("ENABLE FILTERS", enable_filter);
360 	s->addSaveFunc([enable_filter] {
361 		bool filter_is_enabled = !Settings::getInstance()->getBool("ForceDisableFilters");
362 		Settings::getInstance()->setBool("ForceDisableFilters", !enable_filter->getState());
363 		if (enable_filter->getState() != filter_is_enabled) ViewController::get()->ReloadAndGoToStart();
364 	});
365 
366 	// hide start menu in Kid Mode
367 	auto disable_start = std::make_shared<SwitchComponent>(mWindow);
368 	disable_start->setState(Settings::getInstance()->getBool("DisableKidStartMenu"));
369 	s->addWithLabel("DISABLE START MENU IN KID MODE", disable_start);
370 	s->addSaveFunc([disable_start] { Settings::getInstance()->setBool("DisableKidStartMenu", disable_start->getState()); });
371 
372 	mWindow->pushGui(s);
373 
374 }
375 
openOtherSettings()376 void GuiMenu::openOtherSettings()
377 {
378 	auto s = new GuiSettings(mWindow, "OTHER SETTINGS");
379 
380 	// maximum vram
381 	auto max_vram = std::make_shared<SliderComponent>(mWindow, 0.f, 1000.f, 10.f, "Mb");
382 	max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM")));
383 	s->addWithLabel("VRAM LIMIT", max_vram);
384 	s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)Math::round(max_vram->getValue())); });
385 
386 	// power saver
387 	auto power_saver = std::make_shared< OptionListComponent<std::string> >(mWindow, "POWER SAVER MODES", false);
388 	std::vector<std::string> modes;
389 	modes.push_back("disabled");
390 	modes.push_back("default");
391 	modes.push_back("enhanced");
392 	modes.push_back("instant");
393 	for (auto it = modes.cbegin(); it != modes.cend(); it++)
394 		power_saver->add(*it, *it, Settings::getInstance()->getString("PowerSaverMode") == *it);
395 	s->addWithLabel("POWER SAVER MODES", power_saver);
396 	s->addSaveFunc([this, power_saver] {
397 		if (Settings::getInstance()->getString("PowerSaverMode") != "instant" && power_saver->getSelected() == "instant") {
398 			Settings::getInstance()->setString("TransitionStyle", "instant");
399 			Settings::getInstance()->setBool("MoveCarousel", false);
400 			Settings::getInstance()->setBool("EnableSounds", false);
401 		}
402 		Settings::getInstance()->setString("PowerSaverMode", power_saver->getSelected());
403 		PowerSaver::init();
404 	});
405 
406 	// gamelists
407 	auto gamelistsSaveMode = std::make_shared< OptionListComponent<std::string> >(mWindow, "SAVE METADATA", false);
408 	std::vector<std::string> saveModes;
409 	saveModes.push_back("on exit");
410 	saveModes.push_back("always");
411 	saveModes.push_back("never");
412 
413 	for(auto it = saveModes.cbegin(); it != saveModes.cend(); it++)
414 		gamelistsSaveMode->add(*it, *it, Settings::getInstance()->getString("SaveGamelistsMode") == *it);
415 	s->addWithLabel("SAVE METADATA", gamelistsSaveMode);
416 	s->addSaveFunc([gamelistsSaveMode] {
417 		Settings::getInstance()->setString("SaveGamelistsMode", gamelistsSaveMode->getSelected());
418 	});
419 
420 	auto parse_gamelists = std::make_shared<SwitchComponent>(mWindow);
421 	parse_gamelists->setState(Settings::getInstance()->getBool("ParseGamelistOnly"));
422 	s->addWithLabel("PARSE GAMESLISTS ONLY", parse_gamelists);
423 	s->addSaveFunc([parse_gamelists] { Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelists->getState()); });
424 
425 	auto local_art = std::make_shared<SwitchComponent>(mWindow);
426 	local_art->setState(Settings::getInstance()->getBool("LocalArt"));
427 	s->addWithLabel("SEARCH FOR LOCAL ART", local_art);
428 	s->addSaveFunc([local_art] { Settings::getInstance()->setBool("LocalArt", local_art->getState()); });
429 
430 	// hidden files
431 	auto hidden_files = std::make_shared<SwitchComponent>(mWindow);
432 	hidden_files->setState(Settings::getInstance()->getBool("ShowHiddenFiles"));
433 	s->addWithLabel("SHOW HIDDEN FILES", hidden_files);
434 	s->addSaveFunc([hidden_files] { Settings::getInstance()->setBool("ShowHiddenFiles", hidden_files->getState()); });
435 
436 #ifdef _RPI_
437 	// Video Player - VideoOmxPlayer
438 	auto omx_player = std::make_shared<SwitchComponent>(mWindow);
439 	omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer"));
440 	s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player);
441 	s->addSaveFunc([omx_player]
442 	{
443 		// need to reload all views to re-create the right video components
444 		bool needReload = false;
445 		if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState())
446 			needReload = true;
447 
448 		Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState());
449 
450 		if(needReload)
451 			ViewController::get()->reloadAll();
452 	});
453 
454 #endif
455 
456 	// framerate
457 	auto framerate = std::make_shared<SwitchComponent>(mWindow);
458 	framerate->setState(Settings::getInstance()->getBool("DrawFramerate"));
459 	s->addWithLabel("SHOW FRAMERATE", framerate);
460 	s->addSaveFunc([framerate] { Settings::getInstance()->setBool("DrawFramerate", framerate->getState()); });
461 
462 
463 	mWindow->pushGui(s);
464 
465 }
466 
openConfigInput()467 void GuiMenu::openConfigInput()
468 {
469 	Window* window = mWindow;
470 	window->pushGui(new GuiMsgBox(window, "ARE YOU SURE YOU WANT TO CONFIGURE INPUT?", "YES",
471 		[window] {
472 		window->pushGui(new GuiDetectDevice(window, false, nullptr));
473 	}, "NO", nullptr)
474 	);
475 
476 }
477 
openQuitMenu()478 void GuiMenu::openQuitMenu()
479 {
480 	auto s = new GuiSettings(mWindow, "QUIT");
481 
482 	Window* window = mWindow;
483 
484 	ComponentListRow row;
485 	if (UIModeController::getInstance()->isUIModeFull())
486 	{
487 		row.makeAcceptInputHandler([window] {
488 			window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES",
489 				[] {
490 				Scripting::fireEvent("quit");
491 				if(quitES(QuitMode::RESTART) != 0)
492 					LOG(LogWarning) << "Restart terminated with non-zero result!";
493 			}, "NO", nullptr));
494 		});
495 		row.addElement(std::make_shared<TextComponent>(window, "RESTART EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
496 		s->addRow(row);
497 
498 
499 
500 		if(Settings::getInstance()->getBool("ShowExit"))
501 		{
502 			row.elements.clear();
503 			row.makeAcceptInputHandler([window] {
504 				window->pushGui(new GuiMsgBox(window, "REALLY QUIT?", "YES",
505 					[] {
506 					Scripting::fireEvent("quit");
507 					quitES();
508 				}, "NO", nullptr));
509 			});
510 			row.addElement(std::make_shared<TextComponent>(window, "QUIT EMULATIONSTATION", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
511 			s->addRow(row);
512 		}
513 	}
514 	row.elements.clear();
515 	row.makeAcceptInputHandler([window] {
516 		window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES",
517 			[] {
518 			Scripting::fireEvent("quit", "reboot");
519 			Scripting::fireEvent("reboot");
520 			if (quitES(QuitMode::REBOOT) != 0)
521 				LOG(LogWarning) << "Restart terminated with non-zero result!";
522 		}, "NO", nullptr));
523 	});
524 	row.addElement(std::make_shared<TextComponent>(window, "RESTART SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
525 	s->addRow(row);
526 
527 	row.elements.clear();
528 	row.makeAcceptInputHandler([window] {
529 		window->pushGui(new GuiMsgBox(window, "REALLY SHUTDOWN?", "YES",
530 			[] {
531 			Scripting::fireEvent("quit", "shutdown");
532 			Scripting::fireEvent("shutdown");
533 			if (quitES(QuitMode::SHUTDOWN) != 0)
534 				LOG(LogWarning) << "Shutdown terminated with non-zero result!";
535 		}, "NO", nullptr));
536 	});
537 	row.addElement(std::make_shared<TextComponent>(window, "SHUTDOWN SYSTEM", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
538 	s->addRow(row);
539 
540 	mWindow->pushGui(s);
541 }
542 
addVersionInfo()543 void GuiMenu::addVersionInfo()
544 {
545 	std::string  buildDate = (Settings::getInstance()->getBool("Debug") ? std::string( "   (" + Utils::String::toUpper(PROGRAM_BUILT_STRING) + ")") : (""));
546 
547 	mVersion.setFont(Font::get(FONT_SIZE_SMALL));
548 	mVersion.setColor(0x5E5E5EFF);
549 	mVersion.setText("EMULATIONSTATION V" + Utils::String::toUpper(PROGRAM_VERSION_STRING) + buildDate);
550 	mVersion.setHorizontalAlignment(ALIGN_CENTER);
551 	addChild(&mVersion);
552 }
553 
openScreensaverOptions()554 void GuiMenu::openScreensaverOptions() {
555 	mWindow->pushGui(new GuiGeneralScreensaverOptions(mWindow, "SCREENSAVER SETTINGS"));
556 }
557 
openCollectionSystemSettings()558 void GuiMenu::openCollectionSystemSettings() {
559 	mWindow->pushGui(new GuiCollectionSystemsOptions(mWindow));
560 }
561 
onSizeChanged()562 void GuiMenu::onSizeChanged()
563 {
564 	mVersion.setSize(mSize.x(), 0);
565 	mVersion.setPosition(0, mSize.y() - mVersion.getSize().y());
566 }
567 
addEntry(const char * name,unsigned int color,bool add_arrow,const std::function<void ()> & func)568 void GuiMenu::addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func)
569 {
570 	std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
571 
572 	// populate the list
573 	ComponentListRow row;
574 	row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
575 
576 	if(add_arrow)
577 	{
578 		std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
579 		row.addElement(bracket, false);
580 	}
581 
582 	row.makeAcceptInputHandler(func);
583 
584 	mMenu.addRow(row);
585 }
586 
input(InputConfig * config,Input input)587 bool GuiMenu::input(InputConfig* config, Input input)
588 {
589 	if(GuiComponent::input(config, input))
590 		return true;
591 
592 	if((config->isMappedTo("b", input) || config->isMappedTo("start", input)) && input.value != 0)
593 	{
594 		delete this;
595 		return true;
596 	}
597 
598 	return false;
599 }
600 
getHelpStyle()601 HelpStyle GuiMenu::getHelpStyle()
602 {
603 	HelpStyle style = HelpStyle();
604 	style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
605 	return style;
606 }
607 
getHelpPrompts()608 std::vector<HelpPrompt> GuiMenu::getHelpPrompts()
609 {
610 	std::vector<HelpPrompt> prompts;
611 	prompts.push_back(HelpPrompt("up/down", "choose"));
612 	prompts.push_back(HelpPrompt("a", "select"));
613 	prompts.push_back(HelpPrompt("start", "close"));
614 	return prompts;
615 }
616