From fa9b72ffb553b0408edb674a3155093d6b002c38 Mon Sep 17 00:00:00 2001 From: Jade <48196637+GlazedBelmont@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:34:24 -0500 Subject: [PATCH 1/4] Separate colorization into its own submenu --- es-app/src/guis/GuiMenu.cpp | 4753 ++++++++++++++++++----------------- 1 file changed, 2385 insertions(+), 2368 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 1865857..e4ebc9b 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -1601,90 +1601,589 @@ void GuiMenu::openLatencyReductionConfiguration(Window* mWindow, std::string con mWindow->pushGui(guiViewport); } */ -void GuiMenu::openRetroachievementsSettings() +void GuiMenu::openColorizationConfiguration(Window* mWindow, std::string configName) { - Window* window = mWindow; - GuiSettings* retroachievements = new GuiSettings(mWindow, _("RETROACHIEVEMENT SETTINGS").c_str()); - - retroachievements->addGroup(_("SETTINGS")); - - bool retroachievementsEnabled = SystemConf::getInstance()->getBool("global.retroachievements"); - std::string username = SystemConf::getInstance()->get("global.retroachievements.username"); - std::string password = SystemConf::getInstance()->get("global.retroachievements.password"); - - // retroachievements_enable - auto retroachievements_enabled = std::make_shared(mWindow); - retroachievements_enabled->setState(retroachievementsEnabled); - retroachievements->addWithLabel(_("RETROACHIEVEMENTS"), retroachievements_enabled); - - // retroachievements_hardcore_mode - auto retroachievements_hardcore_enabled = std::make_shared(mWindow); - retroachievements_hardcore_enabled->setState(SystemConf::getInstance()->getBool("global.retroachievements.hardcore")); - retroachievements->addWithLabel(_("HARDCORE MODE"), retroachievements_hardcore_enabled); - retroachievements->addSaveFunc([retroachievements_hardcore_enabled] { SystemConf::getInstance()->setBool("global.retroachievements.hardcore", retroachievements_hardcore_enabled->getState()); }); - - // retroachievements main menu option - auto retroachievements_menuitem = std::make_shared(mWindow); - retroachievements_menuitem->setState(Settings::getInstance()->getBool("RetroachievementsMenuitem")); - retroachievements->addWithLabel(_("SHOW RETROACHIEVEMENTS ENTRY IN MAIN MENU"), retroachievements_menuitem); - retroachievements->addSaveFunc([retroachievements_menuitem] { Settings::getInstance()->setBool("RetroachievementsMenuitem", retroachievements_menuitem->getState()); }); - - - //// retroachievements_leaderboards - //auto retroachievements_leaderboards_enabled = std::make_shared(mWindow); - //retroachievements_leaderboards_enabled->setState(SystemConf::getInstance()->getBool("global.retroachievements.leaderboards")); - //retroachievements->addWithLabel(_("LEADERBOARDS"), retroachievements_leaderboards_enabled); - //retroachievements->addSaveFunc([retroachievements_leaderboards_enabled] { SystemConf::getInstance()->setBool("global.retroachievements.///leaderboards", retroachievements_leaderboards_enabled->getState()); }); + GuiSettings* guiColorization = new GuiSettings(mWindow, _("COLORIZATION").c_str()); - // retroachievements_leaderboards list - auto retroachievements_leaderboards_list = std::make_shared< OptionListComponent >(mWindow, _("LEADERBOARDS"), false); - std::vector leader; - leader.push_back("disabled"); - leader.push_back("enabled"); - leader.push_back("trackers only"); - leader.push_back("notifications only"); + // gameboy colorize + auto colorizations_choices = std::make_shared >(mWindow, _("GB COLORIZATION"), false); + auto twb1_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 1 PALETTE"), false); + auto twb2_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 2 PALETTE"), false); + auto twb3_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 3 PALETTE"), false); + auto pixelshift1_colorizations_choices = std::make_shared >(mWindow, _("PIXELSHIFT - PACK 1 PALETTE"), false); + auto colorCorrection_enabled = std::make_shared>(mWindow, _("COLOR CORRECTION")); + auto colorCorrection_mode_choices = std::make_shared>(mWindow, _("COLOR CORRECTION MODE")); + auto colorCorrection_frontlight_choices = std::make_shared>(mWindow, _("COLOR CORRECTION - FRONTLIGHT POSITION")); + - auto currentLeader = SystemConf::getInstance()->get("global.retroachievements.leaderboards"); - if (currentLeader.empty()) - currentLeader = "disabled"; + std::string currentColorization = SystemConf::getInstance()->get(configName + ".renderer.colorization"); + std::string twb1_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb1_colorization"); + std::string twb2_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb2_colorization"); + std::string twb3_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb3_colorization"); + std::string pixelshift1_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.pixelshift1_colorization"); - for (auto it = leader.cbegin(); it != leader.cend(); it++) - retroachievements_leaderboards_list->add(_(it->c_str()), *it, currentLeader == *it); - retroachievements->addWithLabel(_("LEADERBOARDS"), retroachievements_leaderboards_list); - retroachievements->addSaveFunc([retroachievements_leaderboards_list] - { - SystemConf::getInstance()->set("global.retroachievements.leaderboards", retroachievements_leaderboards_list->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - }); - // retroachievements_challenge_indicators - auto retroachievements_challenge_indicators = std::make_shared(mWindow); - retroachievements_challenge_indicators->setState(SystemConf::getInstance()->getBool("global.retroachievements.challengeindicators")); - retroachievements->addWithLabel(_("CHALLENGE INDICATORS"), retroachievements_challenge_indicators); - retroachievements->addSaveFunc([retroachievements_challenge_indicators] { SystemConf::getInstance()->setBool("global.retroachievements.challengeindicators", retroachievements_challenge_indicators->getState()); }); + if (currentColorization.empty()) + currentColorization = std::string("default"); + if (twb1_currentColorization.empty()) + twb1_currentColorization = std::string("TWB64 001 - Aqours Blue"); + if (twb2_currentColorization.empty()) + twb2_currentColorization = std::string("TWB64 101 - 765PRO Pink"); + if (twb3_currentColorization.empty()) + twb3_currentColorization = std::string("TWB64 201 - DMG-GOLD"); + if (pixelshift1_currentColorization.empty()) + pixelshift1_currentColorization = std::string("PixelShift 01 - Arctic Green"); - // retroachievements_richpresence_enable - auto retroachievements_richpresence_enable = std::make_shared(mWindow); - retroachievements_richpresence_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.richpresence")); - retroachievements->addWithLabel(_("RICH PRESENCE"), retroachievements_richpresence_enable); - retroachievements->addSaveFunc([retroachievements_richpresence_enable] { SystemConf::getInstance()->setBool("global.retroachievements.richpresence", retroachievements_richpresence_enable->getState()); }); + colorizations_choices->add(_("DEFAULT"), "default", currentColorization == "default"); + colorizations_choices->add(_("NONE"), "none", currentColorization == "none"); + colorizations_choices->add(_("GBC"), "GBC", currentColorization == "GBC"); + colorizations_choices->add(_("SGB"), "SGB", currentColorization == "SGB"); + colorizations_choices->add(_("Best Guess"), "Best Guess", currentColorization == "Best Guess"); - // retroachievements_badges_enable - auto retroachievements_badges_enable = std::make_shared(mWindow); - retroachievements_badges_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.badges")); - retroachievements->addWithLabel(_("BADGES"), retroachievements_badges_enable); - retroachievements->addSaveFunc([retroachievements_badges_enable] { SystemConf::getInstance()->setBool("global.retroachievements.badges", retroachievements_badges_enable->getState()); }); + const char* all_gambate_gc_colors_modes[] = { "GB - DMG", + "GB - Light", + "GB - Pocket", + "GBC - Blue", + "GBC - Brown", + "GBC - Dark Blue", + "GBC - Dark Brown", + "GBC - Dark Green", + "GBC - Grayscale", + "GBC - Green", + "GBC - Inverted", + "GBC - Orange", + "GBC - Pastel Mix", + "GBC - Red", + "GBC - Yellow", + "SGB - 1A", + "SGB - 1B", + "SGB - 1C", + "SGB - 1D", + "SGB - 1E", + "SGB - 1F", + "SGB - 1G", + "SGB - 1H", + "SGB - 2A", + "SGB - 2B", + "SGB - 2C", + "SGB - 2D", + "SGB - 2E", + "SGB - 2F", + "SGB - 2G", + "SGB - 2H", + "SGB - 3A", + "SGB - 3B", + "SGB - 3C", + "SGB - 3D", + "SGB - 3E", + "SGB - 3F", + "SGB - 3G", + "SGB - 3H", + "SGB - 4A", + "SGB - 4B", + "SGB - 4C", + "SGB - 4D", + "SGB - 4E", + "SGB - 4F", + "SGB - 4G", + "SGB - 4H", + "Special 1", + "Special 2", + "Special 3", + "Special 4 (TI-83 Legacy)", + "TWB64 - Pack 1", + "TWB64 - Pack 2", + "TWB64 - Pack 3", + "PixelShift - Pack 1"}; - // retroachievements_test_unofficial - auto retroachievements_test_unofficial = std::make_shared(mWindow); - retroachievements_test_unofficial->setState(SystemConf::getInstance()->getBool("global.retroachievements.testunofficial")); - retroachievements->addWithLabel(_("TEST UNOFFICIAL ACHIEVEMENTS"), retroachievements_test_unofficial); - retroachievements->addSaveFunc([retroachievements_test_unofficial] { SystemConf::getInstance()->setBool("global.retroachievements.testunofficial", retroachievements_test_unofficial->getState()); }); + const char* twb1_colors_modes[] = { + "TWB64 001 - Aqours Blue", + "TWB64 002 - Anime Expo Ver.", + "TWB64 003 - SpongeBob Yellow", + "TWB64 004 - Patrick Star Pink", + "TWB64 005 - Neon Red", + "TWB64 006 - Neon Blue", + "TWB64 007 - Neon Yellow", + "TWB64 008 - Neon Green", + "TWB64 009 - Neon Pink", + "TWB64 010 - Mario Red", + "TWB64 011 - Nick Orange", + "TWB64 012 - Virtual Vision", + "TWB64 013 - Golden Wild", + "TWB64 014 - Builder Yellow", + "TWB64 015 - Classic Blurple", + "TWB64 016 - 765 Production Ver.", + "TWB64 017 - Superball Ivory", + "TWB64 018 - Crunchyroll Orange", + "TWB64 019 - Muse Pink", + "TWB64 020 - Nijigasaki Yellow", + "TWB64 021 - Gamate Ver.", + "TWB64 022 - Greenscale Ver.", + "TWB64 023 - Odyssey Gold", + "TWB64 024 - Super Saiyan God", + "TWB64 025 - Super Saiyan Blue", + "TWB64 026 - Bizarre Pink", + "TWB64 027 - Nintendo Switch Lite Ver.", + "TWB64 028 - Game.com Ver.", + "TWB64 029 - Sanrio Pink", + "TWB64 030 - BANDAI NAMCO Ver.", + "TWB64 031 - Cosmo Green", + "TWB64 032 - Wanda Pink", + "TWB64 033 - Link's Awakening DX Ver.", + "TWB64 034 - Travel Wood", + "TWB64 035 - Pokemon Ver.", + "TWB64 036 - Game Grump Orange", + "TWB64 037 - Scooby-Doo Mystery Ver.", + "TWB64 038 - Pokemon mini Ver.", + "TWB64 039 - Supervision Ver.", + "TWB64 040 - DMG Ver.", + "TWB64 041 - Pocket Ver.", + "TWB64 042 - Light Ver.", + "TWB64 043 - Miraitowa Blue", + "TWB64 044 - Someity Pink", + "TWB64 045 - Pikachu Yellow", + "TWB64 046 - Eevee Brown", + "TWB64 047 - Microvision Ver.", + "TWB64 048 - TI-83 Ver.", + "TWB64 049 - Aegis Cherry", + "TWB64 050 - Labo Fawn", + "TWB64 051 - MILLION LIVE GOLD!", + "TWB64 052 - Tokyo Midtown Ver.", + "TWB64 053 - VMU Ver.", + "TWB64 054 - Game Master Ver.", + "TWB64 055 - Android Green", + "TWB64 056 - Walmart Discount Blue", + "TWB64 057 - Google Red", + "TWB64 058 - Google Blue", + "TWB64 059 - Google Yellow", + "TWB64 060 - Google Green", + "TWB64 061 - WonderSwan Ver.", + "TWB64 062 - Neo Geo Pocket Ver.", + "TWB64 063 - Dew Green", + "TWB64 064 - Coca-Cola Red", + "TWB64 065 - GameKing Ver.", + "TWB64 066 - Do The Dew Ver.", + "TWB64 067 - Digivice Ver.", + "TWB64 068 - Bikini Bottom Ver.", + "TWB64 069 - Blossom Pink", + "TWB64 070 - Bubbles Blue", + "TWB64 071 - Buttercup Green", + "TWB64 072 - NASCAR Ver.", + "TWB64 073 - Lemon-Lime Green", + "TWB64 074 - Mega Man V Ver.", + "TWB64 075 - Tamagotchi Ver.", + "TWB64 076 - Phantom Red", + "TWB64 077 - Halloween Ver.", + "TWB64 078 - Christmas Ver.", + "TWB64 079 - Cardcaptor Pink", + "TWB64 080 - Pretty Guardian Gold", + "TWB64 081 - Camouflage Ver.", + "TWB64 082 - Legendary Super Saiyan", + "TWB64 083 - Super Saiyan Rose", + "TWB64 084 - Super Saiyan", + "TWB64 085 - Perfected Ultra Instinct", + "TWB64 086 - Saint Snow Red", + "TWB64 087 - Yellow Banana", + "TWB64 088 - Green Banana", + "TWB64 089 - Super Saiyan 3", + "TWB64 090 - Super Saiyan Blue Evolved", + "TWB64 091 - Pocket Tales Ver.", + "TWB64 092 - Investigation Yellow", + "TWB64 093 - S.E.E.S. Blue", + "TWB64 094 - Game Awards Cyan", + "TWB64 095 - Hokage Orange", + "TWB64 096 - Straw Hat Red", + "TWB64 097 - Sword Art Cyan", + "TWB64 098 - Deku Alpha Emerald", + "TWB64 099 - Blue Stripes Ver.", + "TWB64 100 - Stone Orange"}; - // retroachievements_unlock_sound_enable - auto retroachievements_unlock_sound_enable = std::make_shared(mWindow); - retroachievements_unlock_sound_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.soundenable")); + const char* twb2_colors_modes[] = { + "TWB64 101 - 765PRO Pink", + "TWB64 102 - CINDERELLA Blue", + "TWB64 103 - MILLION Yellow!", + "TWB64 104 - SideM Green", + "TWB64 105 - SHINY Sky Blue", + "TWB64 106 - Angry Volcano Ver.", + "TWB64 107 - Yo-kai Pink", + "TWB64 108 - Yo-kai Green", + "TWB64 109 - Yo-kai Blue", + "TWB64 110 - Yo-kai Purple", + "TWB64 111 - Aquatic Iro", + "TWB64 112 - Tea Midori", + "TWB64 113 - Sakura Pink", + "TWB64 114 - Wisteria Murasaki", + "TWB64 115 - Oni Aka", + "TWB64 116 - Golden Kiiro", + "TWB64 117 - Silver Shiro", + "TWB64 118 - Fruity Orange", + "TWB64 119 - AKB48 Pink", + "TWB64 120 - Miku Blue", + "TWB64 121 - Fairy Tail Red", + "TWB64 122 - Survey Corps Brown", + "TWB64 123 - Island Green", + "TWB64 124 - Mania Plus Green", + "TWB64 125 - Ninja Turtle Green", + "TWB64 126 - Slime Blue", + "TWB64 127 - Lime Midori", + "TWB64 128 - Ghostly Aoi", + "TWB64 129 - Retro Bogeda", + "TWB64 130 - Royal Blue", + "TWB64 131 - Neon Purple", + "TWB64 132 - Neon Orange", + "TWB64 133 - Moonlight Vision", + "TWB64 134 - Tokyo Red", + "TWB64 135 - Paris Gold", + "TWB64 136 - Beijing Blue", + "TWB64 137 - Pac-Man Yellow", + "TWB64 138 - Irish Green", + "TWB64 139 - Kakarot Orange", + "TWB64 140 - Dragon Ball Orange", + "TWB64 141 - Christmas Gold", + "TWB64 142 - Pepsi Vision", + "TWB64 143 - Bubblun Green", + "TWB64 144 - Bobblun Blue", + "TWB64 145 - Baja Blast Storm", + "TWB64 146 - Olympic Gold", + "TWB64 147 - Value Orange", + "TWB64 148 - Liella Purple!", + "TWB64 149 - Olympic Silver", + "TWB64 150 - Olympic Bronze", + "TWB64 151 - ANA Sky Blue", + "TWB64 152 - Nijigasaki Orange", + "TWB64 153 - holoblue", + "TWB64 154 - Wrestling Red", + "TWB64 155 - Yoshi Egg Green", + "TWB64 156 - Pokedex Red", + "TWB64 157 - Disney Dream Blue", + "TWB64 158 - Xbox Green", + "TWB64 159 - Sonic Mega Blue", + "TWB64 160 - Sprite Green", + "TWB64 161 - Scarlett Green", + "TWB64 162 - Glitchy Blue", + "TWB64 163 - Classic LCD", + "TWB64 164 - 3DS Virtual Console Ver.", + "TWB64 165 - PocketStation Ver.", + "TWB64 166 - Timeless Gold and Red", + "TWB64 167 - Smurfy Blue", + "TWB64 168 - Swampy Ogre Green", + "TWB64 169 - Sailor Spinach Green", + "TWB64 170 - Shenron Green", + "TWB64 171 - Berserk Blood", + "TWB64 172 - Super Star Pink", + "TWB64 173 - Gamebuino Classic Ver.", + "TWB64 174 - Barbie Pink", + "TWB64 175 - Star Command Green", + "TWB64 176 - Nokia 3310 Ver.", + "TWB64 177 - Clover Green", + "TWB64 178 - Crash Orange", + "TWB64 179 - Famicom Disk Yellow", + "TWB64 180 - Team Rocket Red", + "TWB64 181 - SEIKO Timer Yellow", + "TWB64 182 - PINK109", + "TWB64 183 - Doraemon Tricolor", + "TWB64 184 - Fury Blue", + "TWB64 185 - Rockstar Orange", + "TWB64 186 - Puyo Puyo Green", + "TWB64 187 - Susan G. Pink", + "TWB64 188 - Pizza Hut Red", + "TWB64 189 - Plumbob Green", + "TWB64 190 - Grand Ivory", + "TWB64 191 - Demon's Gold", + "TWB64 192 - SEGA Tokyo Blue", + "TWB64 193 - Champion's Tunic", + "TWB64 194 - DK Barrel Brown", + "TWB64 195 - EVA-01", + "TWB64 196 - Equestrian Purple", + "TWB64 197 - Autobot Red", + "TWB64 198 - niconico sea green", + "TWB64 199 - Duracell Copper", + "TWB64 200 - TOKYO SKYTREE CLOUDY BLUE"}; + + const char* twb3_colors_modes[] = { + "TWB64 201 - DMG-GOLD", + "TWB64 202 - LCD Clock Green", + "TWB64 203 - Famicom Frenzy", + "TWB64 204 - DK Arcade Blue", + "TWB64 205 - Advanced Indigo", + "TWB64 206 - Ultra Black", + "TWB64 207 - Chaos Emerald Green", + "TWB64 208 - Blue Bomber Azure", + "TWB64 209 - Garry's Blue", + "TWB64 210 - Steam Gray", + "TWB64 211 - Dream Land GB Ver.", + "TWB64 212 - Pokemon Pinball Ver.", + "TWB64 213 - Poketch Ver.", + "TWB64 214 - COLLECTION of SaGa Ver.", + "TWB64 215 - Rocky-Valley Holiday", + "TWB64 216 - Giga Kiwi DMG", + "TWB64 217 - DMG Pea Green", + "TWB64 218 - Timing Hero Ver.", + "TWB64 219 - Invincible Blue", + "TWB64 220 - Grinchy Green", + "TWB64 221 - Winter Icy Blue", + "TWB64 222 - School Idol Mix", + "TWB64 223 - Green Awakening", + "TWB64 224 - Goomba Brown", + "TWB64 225 - Devil Red", + "TWB64 226 - Simpson Yellow", + "TWB64 227 - Spooky Purple", + "TWB64 228 - Treasure Gold", + "TWB64 229 - Cherry Blossom Pink", + "TWB64 230 - Golden Trophy", + "TWB64 231 - Winter Icy Blue", + "TWB64 232 - Leprechaun Green", + "TWB64 233 - SAITAMA SUPER BLUE", + "TWB64 234 - SAITAMA SUPER GREEN", + "TWB64 235 - Duolingo Green", + "TWB64 236 - Super Mushroom Vision", + "TWB64 237 - Ancient Hisuian Brown", + "TWB64 238 - Sky Pop Ivory", + "TWB64 239 - LAWSON BLUE", + "TWB64 240 - Anime Expo Red", + "TWB64 241 - Brilliant Diamond Blue", + "TWB64 242 - Shining Pearl Pink", + "TWB64 243 - Funimation Melon", + "TWB64 244 - Teyvat Brown", + "TWB64 245 - Chozo Blue", + "TWB64 246 - Spotify Green", + "TWB64 247 - Dr Pepper Red", + "TWB64 248 - NHK Silver Gray", + "TWB64 249 - Starbucks Green", + "TWB64 250 - Tokyo Disney Magic", + "TWB64 251 - Kingdom Key Gold", + "TWB64 252 - Hogwarts Goldius", + "TWB64 253 - Kentucky Fried Red", + "TWB64 254 - Cheeto Orange", + "TWB64 255 - Namco Idol Pink", + "TWB64 256 - Domino's Blue", + "TWB64 257 - Pac-Man Vision", + "TWB64 258 - Bill's PC Screen", + "TWB64 259 - Sonic Mega Blue", + "TWB64 260 - Fool's Gold and Silver", + "TWB64 261 - UTA RED", + "TWB64 262 - Metallic Paldea Brass", + "TWB64 263 - Classy Christmas", + "TWB64 264 - Winter Christmas", + "TWB64 265 - IDOL WORLD TRICOLOR!!!", + "TWB64 266 - Inkling Tricolor", + "TWB64 267 - 7-Eleven Color Combo", + "TWB64 268 - PAC-PALETTE", + "TWB64 269 - Vulnerable Blue", + "TWB64 270 - Nightvision Green", + "TWB64 271 - Bandai Namco Tricolor", + "TWB64 272 - Gold, Silver, and Bronze", + "TWB64 273 - Arendelle Winter Blue", + "TWB64 274 - Super Famicom Supreme", + "TWB64 275 - Absorbent and Yellow", + "TWB64 276 - 765PRO TRICOLOR", + "TWB64 277 - GameCube Glimmer", + "TWB64 278 - 1st Vision Pastel", + "TWB64 279 - Perfect Majin Emperor", + "TWB64 280 - J-Pop Idol Sherbet", + "TWB64 281 - Ryuuguu Sunset", + "TWB64 282 - Tropical Starfall", + "TWB64 283 - Colorful Horizons", + "TWB64 284 - BLACKPINK BLINK PINK", + "TWB64 285 - DMG-SWITCH", + "TWB64 286 - POCKET SWITCH", + "TWB64 287 - Sunny Passion Paradise", + "TWB64 288 - Saiyan Beast Silver", + "TWB64 289 - RADIANT SMILE RAMP", + "TWB64 290 - A-RISE BLUE", + "TWB64 291 - TROPICAL TWICE APRICOT", + "TWB64 292 - Odyssey Boy", + "TWB64 293 - Frog Coin Green", + "TWB64 294 - Garfield Vision", + "TWB64 295 - Bedrock Caveman Vision", + "TWB64 296 - BANGTAN ARMY PURPLE", + "TWB64 297 - Spider-Verse Red", + "TWB64 298 - Baja Blast Beach", + "TWB64 299 - 3DS Virtual Console Green", + "TWB64 300 - Wonder Purple"}; + + const char* pixelshift1_colors_modes[] = { + "PixelShift 01 - Arctic Green", + "PixelShift 02 - Arduboy", + "PixelShift 03 - BGB 0.3 Emulator", + "PixelShift 04 - Camouflage", + "PixelShift 05 - Chocolate Bar", + "PixelShift 06 - CMYK", + "PixelShift 07 - Cotton Candy", + "PixelShift 08 - Easy Greens", + "PixelShift 09 - Gamate", + "PixelShift 10 - Game Boy Light", + "PixelShift 11 - Game Boy Pocket", + "PixelShift 12 - Game Boy Pocket Alt", + "PixelShift 13 - Game Pocket Computer", + "PixelShift 14 - Game & Watch Ball", + "PixelShift 15 - GB Backlight Blue", + "PixelShift 16 - GB Backlight Faded", + "PixelShift 17 - GB Backlight Orange", + "PixelShift 18 - GB Backlight White ", + "PixelShift 19 - GB Backlight Yellow Dark", + "PixelShift 20 - GB Bootleg", + "PixelShift 21 - GB Hunter", + "PixelShift 22 - GB Kiosk", + "PixelShift 23 - GB Kiosk 2", + "PixelShift 24 - GB New", + "PixelShift 25 - GB Nuked", + "PixelShift 26 - GB Old", + "PixelShift 27 - GBP Bivert", + "PixelShift 28 - GB Washed Yellow Backlight", + "PixelShift 29 - Ghost", + "PixelShift 30 - Glow In The Dark", + "PixelShift 31 - Gold Bar", + "PixelShift 32 - Grapefruit", + "PixelShift 33 - Gray Green Mix", + "PixelShift 34 - Missingno", + "PixelShift 35 - MS-Dos", + "PixelShift 36 - Newspaper", + "PixelShift 37 - Pip-Boy", + "PixelShift 38 - Pocket Girl", + "PixelShift 39 - Silhouette", + "PixelShift 40 - Sunburst", + "PixelShift 41 - Technicolor", + "PixelShift 42 - Tron", + "PixelShift 43 - Vaporwave", + "PixelShift 44 - Virtual Boy", + "PixelShift 45 - Wish"}; + + + + int n_all_gambate_gc_colors_modes = 55; + int n_twb1_colors_modes = 100; + int n_twb2_colors_modes = 100; + int n_twb3_colors_modes = 100; + int n_pixelshift1_colors_modes = 45; + + for (int i = 0; i < n_all_gambate_gc_colors_modes; i++) + colorizations_choices->add(all_gambate_gc_colors_modes[i], all_gambate_gc_colors_modes[i], currentColorization == std::string(all_gambate_gc_colors_modes[i])); + + for (int i = 0; i < n_twb1_colors_modes; i++) + twb1_colorizations_choices->add(twb1_colors_modes[i], twb1_colors_modes[i], twb1_currentColorization == std::string(twb1_colors_modes[i])); + + for (int i = 0; i < n_twb2_colors_modes; i++) + twb2_colorizations_choices->add(twb2_colors_modes[i], twb2_colors_modes[i], twb2_currentColorization == std::string(twb2_colors_modes[i])); + + for (int i = 0; i < n_twb3_colors_modes; i++) + twb3_colorizations_choices->add(twb3_colors_modes[i], twb3_colors_modes[i], twb3_currentColorization == std::string(twb3_colors_modes[i])); + + for (int i = 0; i < n_pixelshift1_colors_modes; i++) + pixelshift1_colorizations_choices->add(pixelshift1_colors_modes[i], pixelshift1_colors_modes[i], pixelshift1_currentColorization == std::string(pixelshift1_colors_modes[i])); + + colorCorrection_enabled->addRange({ { _("DEFAULT"), "" }, {_("GBC Only"), "GBC only"}, {_("Always"), "always"}, {_("Disabled"), ""} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection")); + colorCorrection_mode_choices->addRange({ { _("DEFAULT"), "" }, {_("Accurate"), "accurate"}, {_("Fast"), "fast"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_mode")); + colorCorrection_frontlight_choices->addRange({ { _("DEFAULT"), "" }, {_("Central"), "central"}, {_("Above Screen"), "above screen"}, {_("Below screen"), "below screen"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_frontlightposition")); + + + guiColorization->addWithLabel(_("GB COLORIZATION"), colorizations_choices); + guiColorization->addWithLabel(_("TWB64 - PACK 1 PALETTE"), twb1_colorizations_choices); + guiColorization->addWithLabel(_("TWB64 - PACK 2 PALETTE"), twb2_colorizations_choices); + guiColorization->addWithLabel(_("TWB64 - PACK 3 PALETTE"), twb3_colorizations_choices); + guiColorization->addWithLabel(_("PIXELSHIFT - PACK 1 PALETTE"), pixelshift1_colorizations_choices); + guiColorization->addWithLabel(_("COLOR CORRECTION"), colorCorrection_enabled); + guiColorization->addWithLabel(_("COLOR CORRECTION MODE"), colorCorrection_mode_choices); + guiColorization->addWithLabel(_("COLOR CORRECTION - FRONTLIGHT POSITION"), colorCorrection_frontlight_choices); + + + guiColorization->addSaveFunc([colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorization", colorizations_choices->getSelected()); }); + guiColorization->addSaveFunc([twb1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb1_colorization", twb1_colorizations_choices->getSelected()); }); + guiColorization->addSaveFunc([twb2_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb2_colorization", twb2_colorizations_choices->getSelected()); }); + guiColorization->addSaveFunc([twb3_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb3_colorization", twb3_colorizations_choices->getSelected()); }); + guiColorization->addSaveFunc([pixelshift1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.pixelshift1_colorization", pixelshift1_colorizations_choices->getSelected()); }); + guiColorization->addSaveFunc([colorCorrection_enabled, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection", colorCorrection_enabled->getSelected()); }); + guiColorization->addSaveFunc([colorCorrection_mode_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection_mode", colorCorrection_mode_choices->getSelected()); }); + guiColorization->addSaveFunc([colorCorrection_frontlight_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection_frontlightposition", colorCorrection_frontlight_choices->getSelected()); }); + + mWindow->pushGui(guiColorization); +} + +void GuiMenu::openRetroachievementsSettings() +{ + Window* window = mWindow; + GuiSettings* retroachievements = new GuiSettings(mWindow, _("RETROACHIEVEMENT SETTINGS").c_str()); + + retroachievements->addGroup(_("SETTINGS")); + + bool retroachievementsEnabled = SystemConf::getInstance()->getBool("global.retroachievements"); + std::string username = SystemConf::getInstance()->get("global.retroachievements.username"); + std::string password = SystemConf::getInstance()->get("global.retroachievements.password"); + + // retroachievements_enable + auto retroachievements_enabled = std::make_shared(mWindow); + retroachievements_enabled->setState(retroachievementsEnabled); + retroachievements->addWithLabel(_("RETROACHIEVEMENTS"), retroachievements_enabled); + + // retroachievements_hardcore_mode + auto retroachievements_hardcore_enabled = std::make_shared(mWindow); + retroachievements_hardcore_enabled->setState(SystemConf::getInstance()->getBool("global.retroachievements.hardcore")); + retroachievements->addWithLabel(_("HARDCORE MODE"), retroachievements_hardcore_enabled); + retroachievements->addSaveFunc([retroachievements_hardcore_enabled] { SystemConf::getInstance()->setBool("global.retroachievements.hardcore", retroachievements_hardcore_enabled->getState()); }); + + // retroachievements main menu option + auto retroachievements_menuitem = std::make_shared(mWindow); + retroachievements_menuitem->setState(Settings::getInstance()->getBool("RetroachievementsMenuitem")); + retroachievements->addWithLabel(_("SHOW RETROACHIEVEMENTS ENTRY IN MAIN MENU"), retroachievements_menuitem); + retroachievements->addSaveFunc([retroachievements_menuitem] { Settings::getInstance()->setBool("RetroachievementsMenuitem", retroachievements_menuitem->getState()); }); + + + //// retroachievements_leaderboards + //auto retroachievements_leaderboards_enabled = std::make_shared(mWindow); + //retroachievements_leaderboards_enabled->setState(SystemConf::getInstance()->getBool("global.retroachievements.leaderboards")); + //retroachievements->addWithLabel(_("LEADERBOARDS"), retroachievements_leaderboards_enabled); + //retroachievements->addSaveFunc([retroachievements_leaderboards_enabled] { SystemConf::getInstance()->setBool("global.retroachievements.///leaderboards", retroachievements_leaderboards_enabled->getState()); }); + + // retroachievements_leaderboards list + auto retroachievements_leaderboards_list = std::make_shared< OptionListComponent >(mWindow, _("LEADERBOARDS"), false); + std::vector leader; + leader.push_back("disabled"); + leader.push_back("enabled"); + leader.push_back("trackers only"); + leader.push_back("notifications only"); + + auto currentLeader = SystemConf::getInstance()->get("global.retroachievements.leaderboards"); + if (currentLeader.empty()) + currentLeader = "disabled"; + + for (auto it = leader.cbegin(); it != leader.cend(); it++) + retroachievements_leaderboards_list->add(_(it->c_str()), *it, currentLeader == *it); + + retroachievements->addWithLabel(_("LEADERBOARDS"), retroachievements_leaderboards_list); + retroachievements->addSaveFunc([retroachievements_leaderboards_list] + { + SystemConf::getInstance()->set("global.retroachievements.leaderboards", retroachievements_leaderboards_list->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + }); + + // retroachievements_challenge_indicators + auto retroachievements_challenge_indicators = std::make_shared(mWindow); + retroachievements_challenge_indicators->setState(SystemConf::getInstance()->getBool("global.retroachievements.challengeindicators")); + retroachievements->addWithLabel(_("CHALLENGE INDICATORS"), retroachievements_challenge_indicators); + retroachievements->addSaveFunc([retroachievements_challenge_indicators] { SystemConf::getInstance()->setBool("global.retroachievements.challengeindicators", retroachievements_challenge_indicators->getState()); }); + + // retroachievements_richpresence_enable + auto retroachievements_richpresence_enable = std::make_shared(mWindow); + retroachievements_richpresence_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.richpresence")); + retroachievements->addWithLabel(_("RICH PRESENCE"), retroachievements_richpresence_enable); + retroachievements->addSaveFunc([retroachievements_richpresence_enable] { SystemConf::getInstance()->setBool("global.retroachievements.richpresence", retroachievements_richpresence_enable->getState()); }); + + // retroachievements_badges_enable + auto retroachievements_badges_enable = std::make_shared(mWindow); + retroachievements_badges_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.badges")); + retroachievements->addWithLabel(_("BADGES"), retroachievements_badges_enable); + retroachievements->addSaveFunc([retroachievements_badges_enable] { SystemConf::getInstance()->setBool("global.retroachievements.badges", retroachievements_badges_enable->getState()); }); + + // retroachievements_test_unofficial + auto retroachievements_test_unofficial = std::make_shared(mWindow); + retroachievements_test_unofficial->setState(SystemConf::getInstance()->getBool("global.retroachievements.testunofficial")); + retroachievements->addWithLabel(_("TEST UNOFFICIAL ACHIEVEMENTS"), retroachievements_test_unofficial); + retroachievements->addSaveFunc([retroachievements_test_unofficial] { SystemConf::getInstance()->setBool("global.retroachievements.testunofficial", retroachievements_test_unofficial->getState()); }); + + // retroachievements_unlock_sound_enable + auto retroachievements_unlock_sound_enable = std::make_shared(mWindow); + retroachievements_unlock_sound_enable->setState(SystemConf::getInstance()->getBool("global.retroachievements.soundenable")); retroachievements->addWithLabel(_("UNLOCK SOUND"), retroachievements_unlock_sound_enable); retroachievements->addSaveFunc([retroachievements_unlock_sound_enable] { SystemConf::getInstance()->setBool("global.retroachievements.soundenable", retroachievements_unlock_sound_enable->getState()); }); @@ -2427,2652 +2926,2170 @@ void GuiMenu::openControllersSettings_batocera(int autoSel) bool found = false; // For each available and configured input - for (auto config : configList) - { - // create name - std::stringstream dispNameSS; - dispNameSS << "#" << config->getDeviceIndex() << " "; - - std::string deviceName = config->getDeviceName(); - if (deviceName.size() > 25) - dispNameSS << deviceName.substr(0, 16) << "..." << deviceName.substr(deviceName.size() - 5, deviceName.size() - 1); - else - dispNameSS << deviceName; - - std::string displayName = dispNameSS.str(); - - bool foundFromConfig = configuratedName == config->getDeviceName() && configuratedGuid == config->getDeviceGUIDString(); - int deviceID = config->getDeviceId(); - // Si la manette est configurée, qu'elle correspond a la configuration, et qu'elle n'est pas - // deja selectionnée on l'ajoute en séléctionnée - StrInputConfig* newInputConfig = new StrInputConfig(config->getDeviceName(), config->getDeviceGUIDString()); - mLoadedInput.push_back(newInputConfig); - - if (foundFromConfig && std::find(alreadyTaken.begin(), alreadyTaken.end(), deviceID) == alreadyTaken.end() && !found) - { - found = true; - alreadyTaken.push_back(deviceID); - - LOG(LogWarning) << "adding entry for player" << player << " (selected): " << config->getDeviceName() << " " << config->getDeviceGUIDString(); - inputOptionList->add(displayName, newInputConfig, true); - } - else - { - LOG(LogInfo) << "adding entry for player" << player << " (not selected): " << config->getDeviceName() << " " << config->getDeviceGUIDString(); - inputOptionList->add(displayName, newInputConfig, false); - } - } - - if (!inputOptionList->hasSelection()) - inputOptionList->selectFirstItem(); - - // Populate controllers list - s->addWithLabel(label, inputOptionList); - } - - s->addSaveFunc([this, options, window] - { - bool changed = false; - - for (int player = 0; player < MAX_PLAYERS; player++) - { - std::stringstream sstm; - sstm << "INPUT P" << player + 1; - std::string confName = sstm.str() + "NAME"; - std::string confGuid = sstm.str() + "GUID"; - - auto input = options.at(player); - - StrInputConfig* selected = input->getSelected(); - if (selected == nullptr) - { - changed |= Settings::getInstance()->setString(confName, "DEFAULT"); - changed |= Settings::getInstance()->setString(confGuid, ""); - } - else if (input->changed()) - { - LOG(LogWarning) << "Found the selected controller ! : name in list = " << input->getSelectedName(); - LOG(LogWarning) << "Found the selected controller ! : guid = " << selected->deviceGUIDString; - - changed |= Settings::getInstance()->setString(confName, selected->deviceName); - changed |= Settings::getInstance()->setString(confGuid, selected->deviceGUIDString); - } - } - - if (changed) - Settings::getInstance()->saveFile(); - - // this is dependant of this configuration, thus update it - InputManager::getInstance()->computeLastKnownPlayersDeviceIndexes(); - }); - - // CONTROLLER ACTIVITY - auto activity = std::make_shared(mWindow); - activity->setState(Settings::getInstance()->getBool("ShowControllerActivity")); - s->addWithLabel(_("SHOW CONTROLLER ACTIVITY"), activity, autoSel == 1); - activity->setOnChangedCallback([this, s, activity] - { - if (Settings::getInstance()->setBool("ShowControllerActivity", activity->getState())) - { - delete s; - openControllersSettings_batocera(1); - } - }); - - if (Settings::getInstance()->getBool("ShowControllerActivity")) - { - // CONTROLLER BATTERY - auto battery = std::make_shared(mWindow); - battery->setState(Settings::getInstance()->getBool("ShowControllerBattery")); - s->addWithLabel(_("SHOW CONTROLLER BATTERY LEVEL"), battery); - s->addSaveFunc([battery] { Settings::getInstance()->setBool("ShowControllerBattery", battery->getState()); }); - } - - window->pushGui(s); -} - -struct ThemeConfigOption -{ - std::string defaultSettingName; - std::string subset; - std::shared_ptr> component; -}; - -void GuiMenu::openThemeConfiguration(Window* mWindow, GuiComponent* s, std::shared_ptr> theme_set, const std::string systemTheme) -{ - if (theme_set != nullptr && Settings::getInstance()->getString("ThemeSet") != theme_set->getSelected()) - { - mWindow->pushGui(new GuiMsgBox(mWindow, _("YOU MUST APPLY THE THEME BEFORE EDITING ITS CONFIGURATION"), _("OK"))); - return; - } - - Window* window = mWindow; - - auto system = ViewController::get()->getState().getSystem(); - auto theme = system->getTheme(); - - auto themeconfig = new GuiSettings(mWindow, (systemTheme.empty() ? _("THEME CONFIGURATION") : _("VIEW CUSTOMIZATION")).c_str()); - - auto themeSubSets = theme->getSubSets(); - - std::string viewName; - bool showGridFeatures = true; - if (!systemTheme.empty()) - { - auto glv = ViewController::get()->getGameListView(system); - viewName = glv->getName(); - std::string baseType = theme->getCustomViewBaseType(viewName); - - showGridFeatures = (viewName == "grid" || baseType == "grid"); - } - - // gamelist_style - std::shared_ptr> gamelist_style = nullptr; - - if (systemTheme.empty() || showGridFeatures && system != NULL && theme->hasView("grid")) - themeconfig->addGroup(_("GAMELIST STYLE")); - - if (systemTheme.empty()) - { - gamelist_style = std::make_shared< OptionListComponent >(mWindow, _("GAMELIST VIEW STYLE"), false); - - std::vector> styles; - styles.push_back(std::pair("automatic", _("automatic"))); - - bool showViewStyle = true; - - if (system != NULL) - { - auto mViews = theme->getViewsOfTheme(); - - showViewStyle = mViews.size() > 1; - - for (auto it = mViews.cbegin(); it != mViews.cend(); ++it) - { - if (it->first == "basic" || it->first == "detailed" || it->first == "grid" || it->first == "video" || it->first == "gamecarousel") - styles.push_back(std::pair(it->first, _(it->first.c_str()))); - else - styles.push_back(*it); - } - } - else - { - styles.push_back(std::pair("basic", _("basic"))); - styles.push_back(std::pair("detailed", _("detailed"))); - } - - auto viewPreference = systemTheme.empty() ? Settings::getInstance()->getString("GamelistViewStyle") : system->getSystemViewMode(); - if (!theme->hasView(viewPreference)) - viewPreference = "automatic"; - - for (auto it = styles.cbegin(); it != styles.cend(); it++) - gamelist_style->add(it->second, it->first, viewPreference == it->first); - - if (!gamelist_style->hasSelection()) - gamelist_style->selectFirstItem(); - - if (showViewStyle) - themeconfig->addWithLabel(_("GAMELIST VIEW STYLE"), gamelist_style); - } - - // Default grid size - std::shared_ptr> mGridSize = nullptr; - if (showGridFeatures && system != NULL && theme->hasView("grid")) - { - Vector2f gridOverride = - systemTheme.empty() ? Vector2f::parseString(Settings::getInstance()->getString("DefaultGridSize")) : - system->getGridSizeOverride(); - - auto ovv = std::to_string((int)gridOverride.x()) + "x" + std::to_string((int)gridOverride.y()); - - mGridSize = std::make_shared>(mWindow, _("DEFAULT GRID SIZE"), false); - - bool found = false; - for (auto it = GuiGamelistOptions::gridSizes.cbegin(); it != GuiGamelistOptions::gridSizes.cend(); it++) - { - bool sel = (gridOverride == Vector2f(0, 0) && *it == "automatic") || ovv == *it; - if (sel) - found = true; - - mGridSize->add(_(it->c_str()), *it, sel); - } - - if (!found) - mGridSize->selectFirstItem(); - - themeconfig->addWithLabel(_("DEFAULT GRID SIZE"), mGridSize); - } - - - - std::map options; - - Utils::String::stringVector subsetNames = theme->getSubSetNames(viewName); - - // push appliesTo at end of list - std::sort(subsetNames.begin(), subsetNames.end(), [themeSubSets](const std::string& a, const std::string& b) -> bool - { - auto sa = ThemeData::getSubSet(themeSubSets, a); - auto sb = ThemeData::getSubSet(themeSubSets, b); - - bool aHasApplies = sa.size() > 0 && !sa.cbegin()->appliesTo.empty(); - bool bHasApplies = sb.size() > 0 && !sb.cbegin()->appliesTo.empty(); - - return aHasApplies < bHasApplies; - }); - - bool hasThemeOptionGroup = false; - bool hasApplyToGroup = false; - for (std::string subset : subsetNames) // theme->getSubSetNames(viewName) - { - std::string settingName = "subset." + subset; - std::string perSystemSettingName = systemTheme.empty() ? "" : "subset." + systemTheme + "." + subset; - - if (subset == "colorset") settingName = "ThemeColorSet"; - else if (subset == "iconset") settingName = "ThemeIconSet"; - else if (subset == "menu") settingName = "ThemeMenu"; - else if (subset == "systemview") settingName = "ThemeSystemView"; - else if (subset == "gamelistview") settingName = "ThemeGamelistView"; - else if (subset == "region") settingName = "ThemeRegionName"; - - auto themeColorSets = ThemeData::getSubSet(themeSubSets, subset); - - if (themeColorSets.size() > 0) + for (auto config : configList) { - auto selectedColorSet = themeColorSets.end(); - auto selectedName = !perSystemSettingName.empty() ? Settings::getInstance()->getString(perSystemSettingName) : Settings::getInstance()->getString(settingName); + // create name + std::stringstream dispNameSS; + dispNameSS << "#" << config->getDeviceIndex() << " "; - if (!perSystemSettingName.empty() && selectedName.empty()) - selectedName = Settings::getInstance()->getString(settingName); + std::string deviceName = config->getDeviceName(); + if (deviceName.size() > 25) + dispNameSS << deviceName.substr(0, 16) << "..." << deviceName.substr(deviceName.size() - 5, deviceName.size() - 1); + else + dispNameSS << deviceName; - for (auto it = themeColorSets.begin(); it != themeColorSets.end() && selectedColorSet == themeColorSets.end(); it++) - if (it->name == selectedName) - selectedColorSet = it; + std::string displayName = dispNameSS.str(); - std::shared_ptr> item = std::make_shared >(mWindow, _(("THEME " + Utils::String::toUpper(subset)).c_str()), false); - item->setTag(!perSystemSettingName.empty() ? perSystemSettingName : settingName); + bool foundFromConfig = configuratedName == config->getDeviceName() && configuratedGuid == config->getDeviceGUIDString(); + int deviceID = config->getDeviceId(); + // Si la manette est configurée, qu'elle correspond a la configuration, et qu'elle n'est pas + // deja selectionnée on l'ajoute en séléctionnée + StrInputConfig* newInputConfig = new StrInputConfig(config->getDeviceName(), config->getDeviceGUIDString()); + mLoadedInput.push_back(newInputConfig); - std::string defaultName; - for (auto it = themeColorSets.begin(); it != themeColorSets.end(); it++) + if (foundFromConfig && std::find(alreadyTaken.begin(), alreadyTaken.end(), deviceID) == alreadyTaken.end() && !found) { - std::string displayName = it->displayName; - - if (!systemTheme.empty()) - { - std::string defaultValue = Settings::getInstance()->getString(settingName); - if (defaultValue.empty()) - defaultValue = system->getTheme()->getDefaultSubSetValue(subset); - - if (it->name == defaultValue) - { - defaultName = Utils::String::toUpper(displayName); - // displayName = displayName + " (" + _("DEFAULT") + ")"; - } - } + found = true; + alreadyTaken.push_back(deviceID); - item->add(displayName, it->name, it == selectedColorSet); + LOG(LogWarning) << "adding entry for player" << player << " (selected): " << config->getDeviceName() << " " << config->getDeviceGUIDString(); + inputOptionList->add(displayName, newInputConfig, true); } - - if (selectedColorSet == themeColorSets.end()) - item->selectFirstItem(); - - if (!themeColorSets.empty()) + else { - std::string displayName = themeColorSets.cbegin()->subSetDisplayName; - if (!displayName.empty()) - { - bool hasApplyToSubset = themeColorSets.cbegin()->appliesTo.size() > 0; + LOG(LogInfo) << "adding entry for player" << player << " (not selected): " << config->getDeviceName() << " " << config->getDeviceGUIDString(); + inputOptionList->add(displayName, newInputConfig, false); + } + } - std::string prefix; + if (!inputOptionList->hasSelection()) + inputOptionList->selectFirstItem(); - if (systemTheme.empty()) - { - for (auto subsetName : themeColorSets.cbegin()->appliesTo) - { - std::string pfx = theme->getViewDisplayName(subsetName); - if (!pfx.empty()) - { - if (prefix.empty()) - prefix = pfx; - else - prefix = prefix + ", " + pfx; - } - } + // Populate controllers list + s->addWithLabel(label, inputOptionList); + } - prefix = Utils::String::toUpper(prefix); - } + s->addSaveFunc([this, options, window] + { + bool changed = false; - if (hasApplyToSubset && !hasApplyToGroup) - { - hasApplyToGroup = true; - themeconfig->addGroup(_("GAMELIST THEME OPTIONS")); - } - else if (!hasApplyToSubset && !hasThemeOptionGroup) - { - hasThemeOptionGroup = true; - themeconfig->addGroup(_("THEME OPTIONS")); - } + for (int player = 0; player < MAX_PLAYERS; player++) + { + std::stringstream sstm; + sstm << "INPUT P" << player + 1; + std::string confName = sstm.str() + "NAME"; + std::string confGuid = sstm.str() + "GUID"; - if (!prefix.empty()) - themeconfig->addWithDescription(displayName, prefix, item); - else if (!defaultName.empty()) - themeconfig->addWithDescription(displayName, _("DEFAULT VALUE") + " : " + defaultName, item); - else - themeconfig->addWithLabel(displayName + prefix, item); - } - else - { - if (!hasThemeOptionGroup) - { - hasThemeOptionGroup = true; - themeconfig->addGroup(_("THEME OPTIONS")); - } + auto input = options.at(player); - themeconfig->addWithLabel(_(("THEME " + Utils::String::toUpper(subset)).c_str()), item); - } + StrInputConfig* selected = input->getSelected(); + if (selected == nullptr) + { + changed |= Settings::getInstance()->setString(confName, "DEFAULT"); + changed |= Settings::getInstance()->setString(confGuid, ""); } + else if (input->changed()) + { + LOG(LogWarning) << "Found the selected controller ! : name in list = " << input->getSelectedName(); + LOG(LogWarning) << "Found the selected controller ! : guid = " << selected->deviceGUIDString; - ThemeConfigOption opt; - opt.component = item; - opt.subset = subset; - opt.defaultSettingName = settingName; - options[!perSystemSettingName.empty() ? perSystemSettingName : settingName] = opt; + changed |= Settings::getInstance()->setString(confName, selected->deviceName); + changed |= Settings::getInstance()->setString(confGuid, selected->deviceGUIDString); + } } - else + + if (changed) + Settings::getInstance()->saveFile(); + + // this is dependant of this configuration, thus update it + InputManager::getInstance()->computeLastKnownPlayersDeviceIndexes(); + }); + + // CONTROLLER ACTIVITY + auto activity = std::make_shared(mWindow); + activity->setState(Settings::getInstance()->getBool("ShowControllerActivity")); + s->addWithLabel(_("SHOW CONTROLLER ACTIVITY"), activity, autoSel == 1); + activity->setOnChangedCallback([this, s, activity] + { + if (Settings::getInstance()->setBool("ShowControllerActivity", activity->getState())) { - ThemeConfigOption opt; - opt.component = nullptr; - options[!perSystemSettingName.empty() ? perSystemSettingName : settingName] = opt; + delete s; + openControllersSettings_batocera(1); } - } - + }); - if (!systemTheme.empty()) + if (Settings::getInstance()->getBool("ShowControllerActivity")) { - themeconfig->addGroup(_("GAMELIST OPTIONS")); + // CONTROLLER BATTERY + auto battery = std::make_shared(mWindow); + battery->setState(Settings::getInstance()->getBool("ShowControllerBattery")); + s->addWithLabel(_("SHOW CONTROLLER BATTERY LEVEL"), battery); + s->addSaveFunc([battery] { Settings::getInstance()->setBool("ShowControllerBattery", battery->getState()); }); + } - // Show favorites first in gamelists - auto fav = Settings::getInstance()->getString(system->getName() + ".FavoritesFirst"); - auto favoritesFirst = std::make_shared>(mWindow, _("SHOW FAVORITES ON TOP"), false); - std::string defFav = Settings::getInstance()->getBool("FavoritesFirst") ? _("YES") : _("NO"); - favoritesFirst->add(_("DEFAULT"), "", fav == "" || fav == "default"); - favoritesFirst->add(_("YES"), "1", fav == "1"); - favoritesFirst->add(_("NO"), "0", fav == "0"); - themeconfig->addWithDescription(_("SHOW FAVORITES ON TOP"), _("DEFAULT VALUE") + " : " + defFav, favoritesFirst); - themeconfig->addSaveFunc([themeconfig, favoritesFirst, system] - { - if (Settings::getInstance()->setString(system->getName() + ".FavoritesFirst", favoritesFirst->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + window->pushGui(s); +} - // Show favorites first in gamelists - auto defHid = Settings::ShowHiddenFiles() ? _("YES") : _("NO"); - auto curhid = Settings::getInstance()->getString(system->getName() + ".ShowHiddenFiles"); - auto hiddenFiles = std::make_shared>(mWindow, _("SHOW HIDDEN FILES"), false); - hiddenFiles->add(_("DEFAULT"), "", curhid == "" || curhid == "default"); - hiddenFiles->add(_("YES"), "1", curhid == "1"); - hiddenFiles->add(_("NO"), "0", curhid == "0"); - themeconfig->addWithDescription(_("SHOW HIDDEN FILES"), _("DEFAULT VALUE") + " : " + defHid, hiddenFiles); - themeconfig->addSaveFunc([themeconfig, hiddenFiles, system] - { - if (Settings::getInstance()->setString(system->getName() + ".ShowHiddenFiles", hiddenFiles->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); +struct ThemeConfigOption +{ + std::string defaultSettingName; + std::string subset; + std::shared_ptr> component; +}; - // Folder View Mode - auto folderView = Settings::getInstance()->getString("FolderViewMode"); - auto defFol = folderView.empty() ? "" : Utils::String::toUpper(_(folderView.c_str())); - auto curFol = Settings::getInstance()->getString(system->getName() + ".FolderViewMode"); +void GuiMenu::openThemeConfiguration(Window* mWindow, GuiComponent* s, std::shared_ptr> theme_set, const std::string systemTheme) +{ + if (theme_set != nullptr && Settings::getInstance()->getString("ThemeSet") != theme_set->getSelected()) + { + mWindow->pushGui(new GuiMsgBox(mWindow, _("YOU MUST APPLY THE THEME BEFORE EDITING ITS CONFIGURATION"), _("OK"))); + return; + } - auto foldersBehavior = std::make_shared>(mWindow, _("SHOW FOLDERS"), false); - foldersBehavior->add(_("DEFAULT"), "", curFol == "" || curFol == "default"); // + " (" + defFol + ")" - foldersBehavior->add(_("always"), "always", curFol == "always"); - foldersBehavior->add(_("never"), "never", curFol == "never"); - foldersBehavior->add(_("having multiple games"), "having multiple games", curFol == "having multiple games"); + Window* window = mWindow; - themeconfig->addWithDescription(_("SHOW FOLDERS"), _("DEFAULT VALUE") + " : " + defFol, foldersBehavior); - themeconfig->addSaveFunc([themeconfig, foldersBehavior, system] - { - if (Settings::getInstance()->setString(system->getName() + ".FolderViewMode", foldersBehavior->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + auto system = ViewController::get()->getState().getSystem(); + auto theme = system->getTheme(); - // Show parent folder in gamelists - auto defPf = Settings::getInstance()->getBool("ShowParentFolder") ? _("YES") : _("NO"); - auto curPf = Settings::getInstance()->getString(system->getName() + ".ShowParentFolder"); - auto parentFolder = std::make_shared>(mWindow, _("SHOW '..' PARENT FOLDER"), false); - parentFolder->add(_("DEFAULT"), "", curPf == "" || curPf == "default"); - parentFolder->add(_("YES"), "1", curPf == "1"); - parentFolder->add(_("NO"), "0", curPf == "0"); - themeconfig->addWithDescription(_("SHOW '..' PARENT FOLDER"), _("DEFAULT VALUE") + " : " + defPf, parentFolder); - themeconfig->addSaveFunc([themeconfig, parentFolder, system] - { - if (Settings::getInstance()->setString(system->getName() + ".ShowParentFolder", parentFolder->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + auto themeconfig = new GuiSettings(mWindow, (systemTheme.empty() ? _("THEME CONFIGURATION") : _("VIEW CUSTOMIZATION")).c_str()); - // Show flags + auto themeSubSets = theme->getSubSets(); - auto defSF = Settings::getInstance()->getString("ShowFlags"); - if (defSF == "1") - defSF = _("BEFORE NAME"); - else if (defSF == "2") - defSF = _("AFTER NAME"); - else - defSF = _("NO"); + std::string viewName; + bool showGridFeatures = true; + if (!systemTheme.empty()) + { + auto glv = ViewController::get()->getGameListView(system); + viewName = glv->getName(); + std::string baseType = theme->getCustomViewBaseType(viewName); - auto curSF = Settings::getInstance()->getString(system->getName() + ".ShowFlags"); - auto showRegionFlags = std::make_shared>(mWindow, _("SHOW REGION FLAG"), false); + showGridFeatures = (viewName == "grid" || baseType == "grid"); + } - showRegionFlags->addRange({{_("DEFAULT"), "default"}, - {_("NO"), "0"}, - {_("BEFORE NAME"), "1"}, - {_("AFTER NAME"), "2"}}, - curSF); + // gamelist_style + std::shared_ptr> gamelist_style = nullptr; - themeconfig->addWithDescription(_("SHOW REGION FLAG"), _("DEFAULT VALUE") + " : " + defSF, showRegionFlags); - themeconfig->addSaveFunc([themeconfig, showRegionFlags, system] - { - if (Settings::getInstance()->setString(system->getName() + ".ShowFlags", showRegionFlags->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + if (systemTheme.empty() || showGridFeatures && system != NULL && theme->hasView("grid")) + themeconfig->addGroup(_("GAMELIST STYLE")); - // Show SaveStates - auto defSS = Settings::getInstance()->getBool("ShowSaveStates") ? _("YES") : _("NO"); - auto curSS = Settings::getInstance()->getString(system->getName() + ".ShowSaveStates"); - auto showSaveStates = std::make_shared>(mWindow, _("SHOW SAVESTATE ICON"), false); - showSaveStates->add(_("DEFAULT"), "", curSS == "" || curSS == "default"); - showSaveStates->add(_("YES"), "1", curSS == "1"); - showSaveStates->add(_("NO"), "0", curSS == "0"); - themeconfig->addWithDescription(_("SHOW SAVESTATE ICON"), _("DEFAULT VALUE") + " : " + defSS, showSaveStates); - themeconfig->addSaveFunc([themeconfig, showSaveStates, system] - { - if (Settings::getInstance()->setString(system->getName() + ".ShowSaveStates", showSaveStates->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + if (systemTheme.empty()) + { + gamelist_style = std::make_shared< OptionListComponent >(mWindow, _("GAMELIST VIEW STYLE"), false); - // Show Manual - auto defMM = Settings::getInstance()->getBool("ShowManualIcon") ? _("YES") : _("NO"); - auto curMM = Settings::getInstance()->getString(system->getName() + ".ShowManualIcon"); - auto showManual = std::make_shared>(mWindow, _("SHOW MANUAL ICON"), false); - showManual->add(_("DEFAULT"), "", curMM == "" || curMM == "default"); - showManual->add(_("YES"), "1", curMM == "1"); - showManual->add(_("NO"), "0", curMM == "0"); - themeconfig->addWithDescription(_("SHOW MANUAL ICON"), _("DEFAULT VALUE") + " : " + defMM, showManual); - themeconfig->addSaveFunc([themeconfig, showManual, system] - { - if (Settings::getInstance()->setString(system->getName() + ".ShowManualIcon", showManual->getSelected())) - themeconfig->setVariable("reloadAll", true); - }); + std::vector> styles; + styles.push_back(std::pair("automatic", _("automatic"))); - // Show filenames - auto defFn = Settings::getInstance()->getBool("ShowFilenames") ? _("YES") : _("NO"); - auto curFn = Settings::getInstance()->getString(system->getName() + ".ShowFilenames"); + bool showViewStyle = true; - auto showFilenames = std::make_shared>(mWindow, _("SHOW FILENAMES INSTEAD"), false); - showFilenames->add(_("DEFAULT"), "", curFn == ""); - showFilenames->add(_("YES"), "1", curFn == "1"); - showFilenames->add(_("NO"), "0", curFn == "0"); - themeconfig->addWithDescription(_("SHOW FILENAMES INSTEAD"), _("DEFAULT VALUE") + " : " + defFn, showFilenames); - themeconfig->addSaveFunc([themeconfig, showFilenames, system] + if (system != NULL) { - if (Settings::getInstance()->setString(system->getName() + ".ShowFilenames", showFilenames->getSelected())) - { - SystemData::resetSettings(); - FileData::resetSettings(); + auto mViews = theme->getViewsOfTheme(); - // themeconfig->setVariable("reloadCollections", true); - themeconfig->setVariable("reloadAll", true); + showViewStyle = mViews.size() > 1; + + for (auto it = mViews.cbegin(); it != mViews.cend(); ++it) + { + if (it->first == "basic" || it->first == "detailed" || it->first == "grid" || it->first == "video" || it->first == "gamecarousel") + styles.push_back(std::pair(it->first, _(it->first.c_str()))); + else + styles.push_back(*it); } - }); + } + else + { + styles.push_back(std::pair("basic", _("basic"))); + styles.push_back(std::pair("detailed", _("detailed"))); + } + auto viewPreference = systemTheme.empty() ? Settings::getInstance()->getString("GamelistViewStyle") : system->getSystemViewMode(); + if (!theme->hasView(viewPreference)) + viewPreference = "automatic"; - // File extensions - if (!system->isCollection() && system->isGameSystem()) - { - auto hiddenExts = Utils::String::split(Settings::getInstance()->getString(system->getName() + ".HiddenExt"), ';'); + for (auto it = styles.cbegin(); it != styles.cend(); it++) + gamelist_style->add(it->second, it->first, viewPreference == it->first); - auto hiddenCtrl = std::make_shared>(mWindow, _("FILE EXTENSIONS"), true); + if (!gamelist_style->hasSelection()) + gamelist_style->selectFirstItem(); - for (auto ext : system->getExtensions()) - { - std::string extid = Utils::String::toLower(Utils::String::replace(ext, ".", "")); - hiddenCtrl->add(ext, extid, std::find(hiddenExts.cbegin(), hiddenExts.cend(), extid) == hiddenExts.cend()); - } + if (showViewStyle) + themeconfig->addWithLabel(_("GAMELIST VIEW STYLE"), gamelist_style); + } - themeconfig->addWithLabel(_("FILE EXTENSIONS"), hiddenCtrl); - themeconfig->addSaveFunc([themeconfig, system, hiddenCtrl] - { - std::string hiddenSystems; + // Default grid size + std::shared_ptr> mGridSize = nullptr; + if (showGridFeatures && system != NULL && theme->hasView("grid")) + { + Vector2f gridOverride = + systemTheme.empty() ? Vector2f::parseString(Settings::getInstance()->getString("DefaultGridSize")) : + system->getGridSizeOverride(); - std::vector sel = hiddenCtrl->getSelectedObjects(); + auto ovv = std::to_string((int)gridOverride.x()) + "x" + std::to_string((int)gridOverride.y()); - for (auto ext : system->getExtensions()) - { - std::string extid = Utils::String::toLower(Utils::String::replace(ext, ".", "")); - if (std::find(sel.cbegin(), sel.cend(), extid) == sel.cend()) - { - if (hiddenSystems.empty()) - hiddenSystems = extid; - else - hiddenSystems = hiddenSystems + ";" + extid; - } - } + mGridSize = std::make_shared>(mWindow, _("DEFAULT GRID SIZE"), false); - if (Settings::getInstance()->setString(system->getName() + ".HiddenExt", hiddenSystems)) - { - Settings::getInstance()->saveFile(); + bool found = false; + for (auto it = GuiGamelistOptions::gridSizes.cbegin(); it != GuiGamelistOptions::gridSizes.cend(); it++) + { + bool sel = (gridOverride == Vector2f(0, 0) && *it == "automatic") || ovv == *it; + if (sel) + found = true; - themeconfig->setVariable("reloadAll", true); - themeconfig->setVariable("forceReloadGames", true); - } - }); + mGridSize->add(_(it->c_str()), *it, sel); } + + if (!found) + mGridSize->selectFirstItem(); + + themeconfig->addWithLabel(_("DEFAULT GRID SIZE"), mGridSize); } - if (systemTheme.empty()) + + + std::map options; + + Utils::String::stringVector subsetNames = theme->getSubSetNames(viewName); + + // push appliesTo at end of list + std::sort(subsetNames.begin(), subsetNames.end(), [themeSubSets](const std::string& a, const std::string& b) -> bool { - themeconfig->addGroup(_("TOOLS")); + auto sa = ThemeData::getSubSet(themeSubSets, a); + auto sb = ThemeData::getSubSet(themeSubSets, b); - themeconfig->addEntry(_("RESET CUSTOMIZATIONS"), false, [s, themeconfig, window] - { - themeconfig->setVariable("resetTheme", true); - themeconfig->setVariable("reloadAll", true); - themeconfig->close(); - }); - } + bool aHasApplies = sa.size() > 0 && !sa.cbegin()->appliesTo.empty(); + bool bHasApplies = sb.size() > 0 && !sb.cbegin()->appliesTo.empty(); - // theme_colorset, theme_iconset, theme_menu, theme_systemview, theme_gamelistview, theme_region, - themeconfig->addSaveFunc([systemTheme, system, themeconfig, options, gamelist_style, mGridSize, window] + return aHasApplies < bHasApplies; + }); + + bool hasThemeOptionGroup = false; + bool hasApplyToGroup = false; + for (std::string subset : subsetNames) // theme->getSubSetNames(viewName) { - bool reloadAll = false; + std::string settingName = "subset." + subset; + std::string perSystemSettingName = systemTheme.empty() ? "" : "subset." + systemTheme + "." + subset; - for (auto option : options) + if (subset == "colorset") settingName = "ThemeColorSet"; + else if (subset == "iconset") settingName = "ThemeIconSet"; + else if (subset == "menu") settingName = "ThemeMenu"; + else if (subset == "systemview") settingName = "ThemeSystemView"; + else if (subset == "gamelistview") settingName = "ThemeGamelistView"; + else if (subset == "region") settingName = "ThemeRegionName"; + + auto themeColorSets = ThemeData::getSubSet(themeSubSets, subset); + + if (themeColorSets.size() > 0) { - ThemeConfigOption& opt = option.second; + auto selectedColorSet = themeColorSets.end(); + auto selectedName = !perSystemSettingName.empty() ? Settings::getInstance()->getString(perSystemSettingName) : Settings::getInstance()->getString(settingName); - std::string value; + if (!perSystemSettingName.empty() && selectedName.empty()) + selectedName = Settings::getInstance()->getString(settingName); - if (opt.component != nullptr) + for (auto it = themeColorSets.begin(); it != themeColorSets.end() && selectedColorSet == themeColorSets.end(); it++) + if (it->name == selectedName) + selectedColorSet = it; + + std::shared_ptr> item = std::make_shared >(mWindow, _(("THEME " + Utils::String::toUpper(subset)).c_str()), false); + item->setTag(!perSystemSettingName.empty() ? perSystemSettingName : settingName); + + std::string defaultName; + for (auto it = themeColorSets.begin(); it != themeColorSets.end(); it++) { - value = opt.component->getSelected(); + std::string displayName = it->displayName; - if (!systemTheme.empty() && !value.empty()) + if (!systemTheme.empty()) { - std::string defaultValue = Settings::getInstance()->getString(opt.defaultSettingName); + std::string defaultValue = Settings::getInstance()->getString(settingName); if (defaultValue.empty()) - defaultValue = system->getTheme()->getDefaultSubSetValue(opt.subset); + defaultValue = system->getTheme()->getDefaultSubSetValue(subset); - if (value == defaultValue) - value = ""; + if (it->name == defaultValue) + { + defaultName = Utils::String::toUpper(displayName); + // displayName = displayName + " (" + _("DEFAULT") + ")"; + } } - else if (systemTheme.empty() && value == system->getTheme()->getDefaultSubSetValue(opt.subset)) - value = ""; + + item->add(displayName, it->name, it == selectedColorSet); } - if (value != Settings::getInstance()->getString(option.first)) - reloadAll |= Settings::getInstance()->setString(option.first, value); - } + if (selectedColorSet == themeColorSets.end()) + item->selectFirstItem(); - Vector2f gridSizeOverride(0, 0); + if (!themeColorSets.empty()) + { + std::string displayName = themeColorSets.cbegin()->subSetDisplayName; + if (!displayName.empty()) + { + bool hasApplyToSubset = themeColorSets.cbegin()->appliesTo.size() > 0; + + std::string prefix; + + if (systemTheme.empty()) + { + for (auto subsetName : themeColorSets.cbegin()->appliesTo) + { + std::string pfx = theme->getViewDisplayName(subsetName); + if (!pfx.empty()) + { + if (prefix.empty()) + prefix = pfx; + else + prefix = prefix + ", " + pfx; + } + } + + prefix = Utils::String::toUpper(prefix); + } - if (mGridSize != nullptr) - { - std::string str = mGridSize->getSelected(); - std::string value = ""; + if (hasApplyToSubset && !hasApplyToGroup) + { + hasApplyToGroup = true; + themeconfig->addGroup(_("GAMELIST THEME OPTIONS")); + } + else if (!hasApplyToSubset && !hasThemeOptionGroup) + { + hasThemeOptionGroup = true; + themeconfig->addGroup(_("THEME OPTIONS")); + } - size_t divider = str.find('x'); - if (divider != std::string::npos) - { - std::string first = str.substr(0, divider); - std::string second = str.substr(divider + 1, std::string::npos); + if (!prefix.empty()) + themeconfig->addWithDescription(displayName, prefix, item); + else if (!defaultName.empty()) + themeconfig->addWithDescription(displayName, _("DEFAULT VALUE") + " : " + defaultName, item); + else + themeconfig->addWithLabel(displayName + prefix, item); + } + else + { + if (!hasThemeOptionGroup) + { + hasThemeOptionGroup = true; + themeconfig->addGroup(_("THEME OPTIONS")); + } - gridSizeOverride = Vector2f((float)atof(first.c_str()), (float)atof(second.c_str())); - value = Utils::String::replace(Utils::String::replace(gridSizeOverride.toString(), ".000000", ""), "0 0", ""); + themeconfig->addWithLabel(_(("THEME " + Utils::String::toUpper(subset)).c_str()), item); + } } - if (systemTheme.empty()) - reloadAll |= Settings::getInstance()->setString("DefaultGridSize", value); + ThemeConfigOption opt; + opt.component = item; + opt.subset = subset; + opt.defaultSettingName = settingName; + options[!perSystemSettingName.empty() ? perSystemSettingName : settingName] = opt; } - else if (systemTheme.empty()) - reloadAll |= Settings::getInstance()->setString("DefaultGridSize", ""); - - if (systemTheme.empty()) - reloadAll |= Settings::getInstance()->setString("GamelistViewStyle", gamelist_style == nullptr ? "" : gamelist_style->getSelected()); else { - std::string viewMode = gamelist_style == nullptr ? system->getSystemViewMode() : gamelist_style->getSelected(); - reloadAll |= system->setSystemViewMode(viewMode, gridSizeOverride); + ThemeConfigOption opt; + opt.component = nullptr; + options[!perSystemSettingName.empty() ? perSystemSettingName : settingName] = opt; } + } - if (themeconfig->getVariable("resetTheme")) - { - Settings::getInstance()->setString("GamelistViewStyle", ""); - Settings::getInstance()->setString("DefaultGridSize", ""); - Settings::getInstance()->setString("ThemeRegionName", ""); - Settings::getInstance()->setString("ThemeColorSet", ""); - Settings::getInstance()->setString("ThemeIconSet", ""); - Settings::getInstance()->setString("ThemeMenu", ""); - Settings::getInstance()->setString("ThemeSystemView", ""); - Settings::getInstance()->setString("ThemeGamelistView", ""); - Settings::getInstance()->setString("GamelistViewStyle", ""); - Settings::getInstance()->setString("DefaultGridSize", ""); - - for (auto sm : Settings::getInstance()->getStringMap()) - if (Utils::String::startsWith(sm.first, "subset.")) - Settings::getInstance()->setString(sm.first, ""); - - for (auto system : SystemData::sSystemVector) - { - system->setSystemViewMode("automatic", Vector2f(0, 0)); - - Settings::getInstance()->setString(system->getName() + ".FavoritesFirst", ""); - Settings::getInstance()->setString(system->getName() + ".ShowHiddenFiles", ""); - Settings::getInstance()->setString(system->getName() + ".FolderViewMode", ""); - Settings::getInstance()->setString(system->getName() + ".ShowFilenames", ""); - Settings::getInstance()->setString(system->getName() + ".ShowParentFolder", ""); - } - Settings::getInstance()->saveFile(); - std::string path = Utils::FileSystem::getEsConfigPath() + "/themesettings/" + Settings::getInstance()->getString("ThemeSet") + ".cfg"; - if (Utils::FileSystem::exists(path)) - Utils::FileSystem::removeFile(path); - } + if (!systemTheme.empty()) + { + themeconfig->addGroup(_("GAMELIST OPTIONS")); - if (reloadAll || themeconfig->getVariable("reloadAll")) + // Show favorites first in gamelists + auto fav = Settings::getInstance()->getString(system->getName() + ".FavoritesFirst"); + auto favoritesFirst = std::make_shared>(mWindow, _("SHOW FAVORITES ON TOP"), false); + std::string defFav = Settings::getInstance()->getBool("FavoritesFirst") ? _("YES") : _("NO"); + favoritesFirst->add(_("DEFAULT"), "", fav == "" || fav == "default"); + favoritesFirst->add(_("YES"), "1", fav == "1"); + favoritesFirst->add(_("NO"), "0", fav == "0"); + themeconfig->addWithDescription(_("SHOW FAVORITES ON TOP"), _("DEFAULT VALUE") + " : " + defFav, favoritesFirst); + themeconfig->addSaveFunc([themeconfig, favoritesFirst, system] { - if (themeconfig->getVariable("forceReloadGames")) - { - ViewController::reloadAllGames(window, false); - } - else if (systemTheme.empty()) - { - CollectionSystemManager::get()->updateSystemsList(); - ViewController::get()->reloadAll(window); - } - else - { - system->loadTheme(); - system->resetFilters(); - - ViewController::get()->reloadSystemListViewTheme(system); - ViewController::get()->reloadGameListView(system); - } - } - }); - - mWindow->pushGui(themeconfig); -} - -void GuiMenu::openUISettings() -{ - auto pthis = this; - Window* window = mWindow; + if (Settings::getInstance()->setString(system->getName() + ".FavoritesFirst", favoritesFirst->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - auto s = new GuiSettings(mWindow, _("UI SETTINGS").c_str()); + // Show favorites first in gamelists + auto defHid = Settings::ShowHiddenFiles() ? _("YES") : _("NO"); + auto curhid = Settings::getInstance()->getString(system->getName() + ".ShowHiddenFiles"); + auto hiddenFiles = std::make_shared>(mWindow, _("SHOW HIDDEN FILES"), false); + hiddenFiles->add(_("DEFAULT"), "", curhid == "" || curhid == "default"); + hiddenFiles->add(_("YES"), "1", curhid == "1"); + hiddenFiles->add(_("NO"), "0", curhid == "0"); + themeconfig->addWithDescription(_("SHOW HIDDEN FILES"), _("DEFAULT VALUE") + " : " + defHid, hiddenFiles); + themeconfig->addSaveFunc([themeconfig, hiddenFiles, system] + { + if (Settings::getInstance()->setString(system->getName() + ".ShowHiddenFiles", hiddenFiles->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - // theme set - auto theme = ThemeData::getMenuTheme(); - auto themeSets = ThemeData::getThemeSets(); - auto system = ViewController::get()->getState().getSystem(); + // Folder View Mode + auto folderView = Settings::getInstance()->getString("FolderViewMode"); + auto defFol = folderView.empty() ? "" : Utils::String::toUpper(_(folderView.c_str())); + auto curFol = Settings::getInstance()->getString(system->getName() + ".FolderViewMode"); - s->addGroup(_("APPEARANCE")); + auto foldersBehavior = std::make_shared>(mWindow, _("SHOW FOLDERS"), false); + foldersBehavior->add(_("DEFAULT"), "", curFol == "" || curFol == "default"); // + " (" + defFol + ")" + foldersBehavior->add(_("always"), "always", curFol == "always"); + foldersBehavior->add(_("never"), "never", curFol == "never"); + foldersBehavior->add(_("having multiple games"), "having multiple games", curFol == "having multiple games"); - if (system != nullptr && !themeSets.empty()) - { - auto selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet")); - if (selectedSet == themeSets.end()) - selectedSet = themeSets.begin(); + themeconfig->addWithDescription(_("SHOW FOLDERS"), _("DEFAULT VALUE") + " : " + defFol, foldersBehavior); + themeconfig->addSaveFunc([themeconfig, foldersBehavior, system] + { + if (Settings::getInstance()->setString(system->getName() + ".FolderViewMode", foldersBehavior->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - auto theme_set = std::make_shared >(mWindow, _("THEME SET"), false); + // Show parent folder in gamelists + auto defPf = Settings::getInstance()->getBool("ShowParentFolder") ? _("YES") : _("NO"); + auto curPf = Settings::getInstance()->getString(system->getName() + ".ShowParentFolder"); + auto parentFolder = std::make_shared>(mWindow, _("SHOW '..' PARENT FOLDER"), false); + parentFolder->add(_("DEFAULT"), "", curPf == "" || curPf == "default"); + parentFolder->add(_("YES"), "1", curPf == "1"); + parentFolder->add(_("NO"), "0", curPf == "0"); + themeconfig->addWithDescription(_("SHOW '..' PARENT FOLDER"), _("DEFAULT VALUE") + " : " + defPf, parentFolder); + themeconfig->addSaveFunc([themeconfig, parentFolder, system] + { + if (Settings::getInstance()->setString(system->getName() + ".ShowParentFolder", parentFolder->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - std::vector themeList; - for (auto it = themeSets.begin(); it != themeSets.end(); it++) - themeList.push_back(it->first); + // Show flags - std::sort(themeList.begin(), themeList.end(), [](const std::string& a, const std::string& b) -> bool { return Utils::String::toLower(a).compare(Utils::String::toLower(b)) < 0; }); + auto defSF = Settings::getInstance()->getString("ShowFlags"); + if (defSF == "1") + defSF = _("BEFORE NAME"); + else if (defSF == "2") + defSF = _("AFTER NAME"); + else + defSF = _("NO"); - for (auto themeName : themeList) - theme_set->add(themeName, themeName, themeName == selectedSet->first); + auto curSF = Settings::getInstance()->getString(system->getName() + ".ShowFlags"); + auto showRegionFlags = std::make_shared>(mWindow, _("SHOW REGION FLAG"), false); - //for (auto it = themeSets.begin(); it != themeSets.end(); it++) - // theme_set->add(it->first, it->first, it == selectedSet); + showRegionFlags->addRange({{_("DEFAULT"), "default"}, + {_("NO"), "0"}, + {_("BEFORE NAME"), "1"}, + {_("AFTER NAME"), "2"}}, + curSF); - s->addWithLabel(_("THEME SET"), theme_set); - s->addSaveFunc([s, theme_set, pthis, window, system] + themeconfig->addWithDescription(_("SHOW REGION FLAG"), _("DEFAULT VALUE") + " : " + defSF, showRegionFlags); + themeconfig->addSaveFunc([themeconfig, showRegionFlags, system] { - std::string oldTheme = Settings::getInstance()->getString("ThemeSet"); - if (oldTheme != theme_set->getSelected()) - { - saveSubsetSettings(); - - Settings::getInstance()->setString("ThemeSet", theme_set->getSelected()); - - // theme changed without setting options, forcing options to avoid crash/blank theme - Settings::getInstance()->setString("ThemeRegionName", ""); - Settings::getInstance()->setString("ThemeColorSet", ""); - Settings::getInstance()->setString("ThemeIconSet", ""); - Settings::getInstance()->setString("ThemeMenu", ""); - Settings::getInstance()->setString("ThemeSystemView", ""); - Settings::getInstance()->setString("ThemeGamelistView", ""); - Settings::getInstance()->setString("GamelistViewStyle", ""); - Settings::getInstance()->setString("DefaultGridSize", ""); + if (Settings::getInstance()->setString(system->getName() + ".ShowFlags", showRegionFlags->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - for(auto sm : Settings::getInstance()->getStringMap()) - if (Utils::String::startsWith(sm.first, "subset.")) - Settings::getInstance()->setString(sm.first, ""); + // Show SaveStates + auto defSS = Settings::getInstance()->getBool("ShowSaveStates") ? _("YES") : _("NO"); + auto curSS = Settings::getInstance()->getString(system->getName() + ".ShowSaveStates"); + auto showSaveStates = std::make_shared>(mWindow, _("SHOW SAVESTATE ICON"), false); + showSaveStates->add(_("DEFAULT"), "", curSS == "" || curSS == "default"); + showSaveStates->add(_("YES"), "1", curSS == "1"); + showSaveStates->add(_("NO"), "0", curSS == "0"); + themeconfig->addWithDescription(_("SHOW SAVESTATE ICON"), _("DEFAULT VALUE") + " : " + defSS, showSaveStates); + themeconfig->addSaveFunc([themeconfig, showSaveStates, system] + { + if (Settings::getInstance()->setString(system->getName() + ".ShowSaveStates", showSaveStates->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - for (auto sysIt = SystemData::sSystemVector.cbegin(); sysIt != SystemData::sSystemVector.cend(); sysIt++) - (*sysIt)->setSystemViewMode("automatic", Vector2f(0,0)); + // Show Manual + auto defMM = Settings::getInstance()->getBool("ShowManualIcon") ? _("YES") : _("NO"); + auto curMM = Settings::getInstance()->getString(system->getName() + ".ShowManualIcon"); + auto showManual = std::make_shared>(mWindow, _("SHOW MANUAL ICON"), false); + showManual->add(_("DEFAULT"), "", curMM == "" || curMM == "default"); + showManual->add(_("YES"), "1", curMM == "1"); + showManual->add(_("NO"), "0", curMM == "0"); + themeconfig->addWithDescription(_("SHOW MANUAL ICON"), _("DEFAULT VALUE") + " : " + defMM, showManual); + themeconfig->addSaveFunc([themeconfig, showManual, system] + { + if (Settings::getInstance()->setString(system->getName() + ".ShowManualIcon", showManual->getSelected())) + themeconfig->setVariable("reloadAll", true); + }); - loadSubsetSettings(theme_set->getSelected()); + // Show filenames + auto defFn = Settings::getInstance()->getBool("ShowFilenames") ? _("YES") : _("NO"); + auto curFn = Settings::getInstance()->getString(system->getName() + ".ShowFilenames"); - s->setVariable("reloadCollections", true); - s->setVariable("reloadAll", true); - s->setVariable("reloadGuiMenu", true); + auto showFilenames = std::make_shared>(mWindow, _("SHOW FILENAMES INSTEAD"), false); + showFilenames->add(_("DEFAULT"), "", curFn == ""); + showFilenames->add(_("YES"), "1", curFn == "1"); + showFilenames->add(_("NO"), "0", curFn == "0"); + themeconfig->addWithDescription(_("SHOW FILENAMES INSTEAD"), _("DEFAULT VALUE") + " : " + defFn, showFilenames); + themeconfig->addSaveFunc([themeconfig, showFilenames, system] + { + if (Settings::getInstance()->setString(system->getName() + ".ShowFilenames", showFilenames->getSelected())) + { + SystemData::resetSettings(); + FileData::resetSettings(); - Scripting::fireEvent("theme-changed", theme_set->getSelected(), oldTheme); + // themeconfig->setVariable("reloadCollections", true); + themeconfig->setVariable("reloadAll", true); } }); - bool showThemeConfiguration = system->getTheme()->hasSubsets() || system->getTheme()->hasView("grid"); - if (showThemeConfiguration) - { - s->addSubMenu(_("THEME CONFIGURATION"), [this, s, theme_set]() { openThemeConfiguration(mWindow, s, theme_set); }); - } - else // GameList view style only, acts like Retropie for simple themes + + // File extensions + if (!system->isCollection() && system->isGameSystem()) { - auto gamelist_style = std::make_shared< OptionListComponent >(mWindow, _("GAMELIST VIEW STYLE"), false); - std::vector> styles; - styles.push_back(std::pair("automatic", _("automatic"))); + auto hiddenExts = Utils::String::split(Settings::getInstance()->getString(system->getName() + ".HiddenExt"), ';'); - auto system = ViewController::get()->getState().getSystem(); - if (system != NULL) + auto hiddenCtrl = std::make_shared>(mWindow, _("FILE EXTENSIONS"), true); + + for (auto ext : system->getExtensions()) { - auto mViews = system->getTheme()->getViewsOfTheme(); - for (auto it = mViews.cbegin(); it != mViews.cend(); ++it) - styles.push_back(*it); + std::string extid = Utils::String::toLower(Utils::String::replace(ext, ".", "")); + hiddenCtrl->add(ext, extid, std::find(hiddenExts.cbegin(), hiddenExts.cend(), extid) == hiddenExts.cend()); } - else + + themeconfig->addWithLabel(_("FILE EXTENSIONS"), hiddenCtrl); + themeconfig->addSaveFunc([themeconfig, system, hiddenCtrl] { - styles.push_back(std::pair("basic", _("basic"))); - styles.push_back(std::pair("detailed", _("detailed"))); - styles.push_back(std::pair("video", _("video"))); - styles.push_back(std::pair("grid", _("grid"))); - } + std::string hiddenSystems; - auto viewPreference = Settings::getInstance()->getString("GamelistViewStyle"); - if (!system->getTheme()->hasView(viewPreference)) - viewPreference = "automatic"; + std::vector sel = hiddenCtrl->getSelectedObjects(); - for (auto it = styles.cbegin(); it != styles.cend(); it++) - gamelist_style->add(it->second, it->first, viewPreference == it->first); + for (auto ext : system->getExtensions()) + { + std::string extid = Utils::String::toLower(Utils::String::replace(ext, ".", "")); + if (std::find(sel.cbegin(), sel.cend(), extid) == sel.cend()) + { + if (hiddenSystems.empty()) + hiddenSystems = extid; + else + hiddenSystems = hiddenSystems + ";" + extid; + } + } - s->addWithLabel(_("GAMELIST VIEW STYLE"), gamelist_style); - s->addSaveFunc([s, gamelist_style, window] { - if (Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected())) + if (Settings::getInstance()->setString(system->getName() + ".HiddenExt", hiddenSystems)) { - s->setVariable("reloadAll", true); - s->setVariable("reloadGuiMenu", true); + Settings::getInstance()->saveFile(); + + themeconfig->setVariable("reloadAll", true); + themeconfig->setVariable("forceReloadGames", true); } }); } } - // language choice - auto language_choice = std::make_shared >(window, _("LANGUAGE"), false); - - std::string language = SystemConf::getInstance()->get("system.language"); - if (language.empty()) - language = "en_US"; - - language_choice->add("ARABIC", "ar_YE", language == "ar_YE"); - language_choice->add("CATALÀ", "ca_ES", language == "ca_ES"); - language_choice->add("CYMRAEG", "cy_GB", language == "cy_GB"); - language_choice->add("DEUTSCH", "de_DE", language == "de_DE"); - language_choice->add("GREEK", "el_GR", language == "el_GR"); - language_choice->add("ENGLISH", "en_US", language == "en_US" || language == "en"); - language_choice->add("ESPAÑOL", "es_ES", language == "es_ES" || language == "es"); - language_choice->add("ESPAÑOL MEXICANO", "es_MX", language == "es_MX"); - language_choice->add("BASQUE", "eu_ES", language == "eu_ES"); - language_choice->add("FRANÇAIS", "fr_FR", language == "fr_FR" || language == "fr"); - language_choice->add("עברית", "he_IL", language == "he_IL"); - language_choice->add("HUNGARIAN", "hu_HU", language == "hu_HU"); - language_choice->add("ITALIANO", "it_IT", language == "it_IT"); - language_choice->add("JAPANESE", "ja_JP", language == "ja_JP"); - language_choice->add("KOREAN", "ko_KR", language == "ko_KR" || language == "ko"); - language_choice->add("NORWEGIAN BOKMAL", "nb_NO", language == "nb_NO"); - language_choice->add("DUTCH", "nl_NL", language == "nl_NL"); - language_choice->add("NORWEGIAN", "nn_NO", language == "nn_NO"); - language_choice->add("OCCITAN", "oc_FR", language == "oc_FR"); - language_choice->add("POLISH", "pl_PL", language == "pl_PL"); - language_choice->add("PORTUGUES BRASILEIRO", "pt_BR", language == "pt_BR"); - language_choice->add("PORTUGUES PORTUGAL", "pt_PT", language == "pt_PT"); - language_choice->add("РУССКИЙ", "ru_RU", language == "ru_RU"); - language_choice->add("SVENSKA", "sv_SE", language == "sv_SE"); - language_choice->add("TÜRKÇE", "tr_TR", language == "tr_TR"); - language_choice->add("Українська", "uk_UA", language == "uk_UA"); - language_choice->add("简体中文", "zh_CN", language == "zh_CN"); - language_choice->add("正體中文", "zh_TW", language == "zh_TW"); - s->addWithLabel(_("LANGUAGE"), language_choice); - - s->addSaveFunc([window, language_choice, language, s] + if (systemTheme.empty()) { - bool reboot = false; + themeconfig->addGroup(_("TOOLS")); - if (language_choice->changed()) + themeconfig->addEntry(_("RESET CUSTOMIZATIONS"), false, [s, themeconfig, window] { - std::string selectedLanguage = language_choice->getSelected(); - std::string msg = _("You are about to set your language to:") +"\n" + selectedLanguage + "\n"; - msg += _("Emulationstation will restart")+"\n"; - msg += _("Do you want to proceed ?"); - window->pushGui(new GuiMsgBox(window, msg, _("YES"), [selectedLanguage] { - SystemConf::getInstance()->set("system.language", selectedLanguage); - SystemConf::getInstance()->saveSystemConf(); - quitES(QuitMode::QUIT); - }, "NO",nullptr)); -#ifdef HAVE_INTL - reboot = true; -#endif - } - - if (reboot) - window->displayNotificationMessage(_U("\uF011 ") + _("A REBOOT OF THE SYSTEM IS REQUIRED TO APPLY THE NEW CONFIGURATION")); - - }); - - // UI RESTRICTIONS - auto UImodeSelection = std::make_shared< OptionListComponent >(mWindow, _("UI MODE"), false); - std::vector UImodes = UIModeController::getInstance()->getUIModes(); - for (auto it = UImodes.cbegin(); it != UImodes.cend(); it++) - UImodeSelection->add(_(it->c_str()), *it, Settings::getInstance()->getString("UIMode") == *it); + themeconfig->setVariable("resetTheme", true); + themeconfig->setVariable("reloadAll", true); + themeconfig->close(); + }); + } - s->addWithLabel(_("UI MODE"), UImodeSelection); - s->addSaveFunc([UImodeSelection, window] + // theme_colorset, theme_iconset, theme_menu, theme_systemview, theme_gamelistview, theme_region, + themeconfig->addSaveFunc([systemTheme, system, themeconfig, options, gamelist_style, mGridSize, window] { - std::string selectedMode = UImodeSelection->getSelected(); - if (selectedMode != "Full") - { - std::string msg = _("You are changing the UI to a restricted mode:\nThis will hide most menu-options to prevent changes to the system.\nTo unlock and return to the full UI, enter this code:") + "\n"; - msg += "\"" + UIModeController::getInstance()->getFormattedPassKeyStr() + "\"\n\n"; - msg += _("Do you want to proceed ?"); - window->pushGui(new GuiMsgBox(window, msg, - _("YES"), [selectedMode] { - LOG(LogDebug) << "Setting UI mode to " << selectedMode; - Settings::getInstance()->setString("UIMode", selectedMode); - Settings::getInstance()->saveFile(); - }, _("NO"), nullptr)); - } - }); - - // retroarch.menu_driver choose from 'auto' (default), 'xmb', 'rgui', 'ozone', 'glui' - auto retroarchRgui = std::make_shared< OptionListComponent >(mWindow, _("RETROARCH MENU DRIVER"), false); - std::vector driver; - driver.push_back("default"); - driver.push_back("xmb"); - driver.push_back("rgui"); - driver.push_back("ozone"); - driver.push_back("glui"); - - auto currentDriver = SystemConf::getInstance()->get("global.retroarch.menu_driver"); - if (currentDriver.empty()) - currentDriver = "default"; + bool reloadAll = false; - for (auto it = driver.cbegin(); it != driver.cend(); it++) - retroarchRgui->add(_(it->c_str()), *it, currentDriver == *it); + for (auto option : options) + { + ThemeConfigOption& opt = option.second; - s->addWithLabel(_("RETROARCH MENU DRIVER"), retroarchRgui); - s->addSaveFunc([retroarchRgui] - { - SystemConf::getInstance()->set("global.retroarch.menu_driver", retroarchRgui->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - }); + std::string value; - auto invertJoy = std::make_shared(mWindow); - invertJoy->setState(Settings::getInstance()->getBool("InvertButtons")); - s->addWithLabel(_("SWITCH A & B BUTTONS IN EMULATIONSTATION"), invertJoy); - s->addSaveFunc([this, s, invertJoy] - { - if (Settings::getInstance()->setBool("InvertButtons", invertJoy->getState())) - { - std::string trueFalse = "false"; - if ( invertJoy->getState() == true ) { - trueFalse = "true"; - } - Settings::getInstance()->setString("subset.swap-a-b", trueFalse); - SystemConf::getInstance()->saveSystemConf(); - InputConfig::AssignActionButtons(); - s->setVariable("reloadAll", true); - } - }); + if (opt.component != nullptr) + { + value = opt.component->getSelected(); - auto fps_enabled = std::make_shared(mWindow); - bool fpsEnabled = SystemConf::getInstance()->get("global.showFPS") == "1"; - fps_enabled->setState(fpsEnabled); - s->addWithLabel(_("SHOW RETROARCH FPS"), fps_enabled); - s->addSaveFunc([fps_enabled] { - bool fpsenabled = fps_enabled->getState(); - SystemConf::getInstance()->set("global.showFPS", fpsenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); + if (!systemTheme.empty() && !value.empty()) + { + std::string defaultValue = Settings::getInstance()->getString(opt.defaultSettingName); + if (defaultValue.empty()) + defaultValue = system->getTheme()->getDefaultSubSetValue(opt.subset); - auto desktop_enabled = std::make_shared(mWindow); - bool desktopEnabled = SystemConf::getInstance()->get("desktop.enabled") == "1"; - desktop_enabled->setState(desktopEnabled); - s->addWithLabel(_("DESKTOP MODE"), desktop_enabled); - s->addSaveFunc([this,desktop_enabled] { - if (desktop_enabled->changed()) { - std::string msg = _("The system will restart")+"\n"; - msg += _("Do you want to continue?"); - mWindow->pushGui(new GuiMsgBox(mWindow,msg, _("YES"), - [this,desktop_enabled] { - bool desktopenabled = desktop_enabled->getState(); - SystemConf::getInstance()->set("desktop.enabled", desktopenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - quitES(QuitMode::REBOOT); - }, "NO",nullptr)); + if (value == defaultValue) + value = ""; + } + else if (systemTheme.empty() && value == system->getTheme()->getDefaultSubSetValue(opt.subset)) + value = ""; + } + + if (value != Settings::getInstance()->getString(option.first)) + reloadAll |= Settings::getInstance()->setString(option.first, value); } - }); + Vector2f gridSizeOverride(0, 0); - s->addGroup(_("DISPLAY OPTIONS")); + if (mGridSize != nullptr) + { + std::string str = mGridSize->getSelected(); + std::string value = ""; - s->addEntry(_("SCREENSAVER SETTINGS"), true, std::bind(&GuiMenu::openScreensaverOptions, this)); + size_t divider = str.find('x'); + if (divider != std::string::npos) + { + std::string first = str.substr(0, divider); + std::string second = str.substr(divider + 1, std::string::npos); - // transition style - auto transition_style = std::make_shared>(mWindow, _("LIST TRANSITION STYLE"), false); - transition_style->addRange({"default", "fade", "slide", "fade & slide", "instant"}, Settings::TransitionStyle()); - s->addWithLabel(_("LIST TRANSITION STYLE"), transition_style); - s->addSaveFunc([transition_style] { Settings::setTransitionStyle(transition_style->getSelected()); }); + gridSizeOverride = Vector2f((float)atof(first.c_str()), (float)atof(second.c_str())); + value = Utils::String::replace(Utils::String::replace(gridSizeOverride.toString(), ".000000", ""), "0 0", ""); + } - // game transition style - auto transitionOfGames_style = std::make_shared>(mWindow, _("GAME LAUNCH TRANSITION"), false); - transitionOfGames_style->addRange({"default", "fade", "slide", "instant"}, Settings::GameTransitionStyle()); - s->addWithLabel(_("GAME LAUNCH TRANSITION"), transitionOfGames_style); - s->addSaveFunc([transitionOfGames_style] { Settings::setGameTransitionStyle(transitionOfGames_style->getSelected()); }); + if (systemTheme.empty()) + reloadAll |= Settings::getInstance()->setString("DefaultGridSize", value); + } + else if (systemTheme.empty()) + reloadAll |= Settings::getInstance()->setString("DefaultGridSize", ""); - // clock - auto clock = std::make_shared(mWindow); - clock->setState(Settings::getInstance()->getBool("DrawClock")); - s->addWithLabel(_("SHOW CLOCK"), clock); - s->addSaveFunc( - [clock] { Settings::getInstance()->setBool("DrawClock", clock->getState()); }); + if (systemTheme.empty()) + reloadAll |= Settings::getInstance()->setString("GamelistViewStyle", gamelist_style == nullptr ? "" : gamelist_style->getSelected()); + else + { + std::string viewMode = gamelist_style == nullptr ? system->getSystemViewMode() : gamelist_style->getSelected(); + reloadAll |= system->setSystemViewMode(viewMode, gridSizeOverride); + } - // show help - auto show_help = std::make_shared(mWindow); - show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts")); - s->addWithLabel(_("ON-SCREEN HELP"), show_help); - s->addSaveFunc([s, show_help] - { - if (Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState())) - s->setVariable("reloadAll", true); - }); + if (themeconfig->getVariable("resetTheme")) + { + Settings::getInstance()->setString("GamelistViewStyle", ""); + Settings::getInstance()->setString("DefaultGridSize", ""); + Settings::getInstance()->setString("ThemeRegionName", ""); + Settings::getInstance()->setString("ThemeColorSet", ""); + Settings::getInstance()->setString("ThemeIconSet", ""); + Settings::getInstance()->setString("ThemeMenu", ""); + Settings::getInstance()->setString("ThemeSystemView", ""); + Settings::getInstance()->setString("ThemeGamelistView", ""); + Settings::getInstance()->setString("GamelistViewStyle", ""); + Settings::getInstance()->setString("DefaultGridSize", ""); - // Battery indicator - if (queryBatteryInformation().hasBattery) - { - auto batteryStatus = std::make_shared >(mWindow, _("SHOW BATTERY STATUS"), false); - batteryStatus->addRange({ { _("NO"), "" },{ _("ICON"), "icon" },{ _("ICON AND TEXT"), "text" } }, Settings::getInstance()->getString("ShowBattery")); - s->addWithLabel(_("SHOW BATTERY STATUS"), batteryStatus); - s->addSaveFunc([batteryStatus] { Settings::getInstance()->setString("ShowBattery", batteryStatus->getSelected()); }); - } + for (auto sm : Settings::getInstance()->getStringMap()) + if (Utils::String::startsWith(sm.first, "subset.")) + Settings::getInstance()->setString(sm.first, ""); - s->addGroup(_("GAMELIST OPTIONS")); + for (auto system : SystemData::sSystemVector) + { + system->setSystemViewMode("automatic", Vector2f(0, 0)); - // Enable Video Previews - auto enable_preview = std::make_shared(mWindow); - enable_preview->setState(Settings::getInstance()->getBool("EnableVideoPreviews")); - s->addWithLabel(_("SHOW VIDEO PREVIEWS"), enable_preview); - s->addSaveFunc([enable_preview] { Settings::getInstance()->setBool("EnableVideoPreviews", enable_preview->getState()); }); + Settings::getInstance()->setString(system->getName() + ".FavoritesFirst", ""); + Settings::getInstance()->setString(system->getName() + ".ShowHiddenFiles", ""); + Settings::getInstance()->setString(system->getName() + ".FolderViewMode", ""); + Settings::getInstance()->setString(system->getName() + ".ShowFilenames", ""); + Settings::getInstance()->setString(system->getName() + ".ShowParentFolder", ""); + } - // Show favorites first in gamelists - auto favoritesFirstSwitch = std::make_shared(mWindow); - favoritesFirstSwitch->setState(Settings::getInstance()->getBool("FavoritesFirst")); - s->addWithLabel(_("SHOW FAVORITES ON TOP"), favoritesFirstSwitch); - s->addSaveFunc([s, favoritesFirstSwitch] - { - if (Settings::getInstance()->setBool("FavoritesFirst", favoritesFirstSwitch->getState())) - s->setVariable("reloadAll", true); - }); + Settings::getInstance()->saveFile(); + std::string path = Utils::FileSystem::getEsConfigPath() + "/themesettings/" + Settings::getInstance()->getString("ThemeSet") + ".cfg"; + if (Utils::FileSystem::exists(path)) + Utils::FileSystem::removeFile(path); + } - // hidden files - auto hidden_files = std::make_shared(mWindow); - hidden_files->setState(Settings::ShowHiddenFiles()); - s->addWithLabel(_("SHOW HIDDEN FILES"), hidden_files); - s->addSaveFunc([s, hidden_files] - { - if (Settings::setShowHiddenFiles(hidden_files->getState())) - s->setVariable("reloadAll", true); + if (reloadAll || themeconfig->getVariable("reloadAll")) + { + if (themeconfig->getVariable("forceReloadGames")) + { + ViewController::reloadAllGames(window, false); + } + else if (systemTheme.empty()) + { + CollectionSystemManager::get()->updateSystemsList(); + ViewController::get()->reloadAll(window); + } + else + { + system->loadTheme(); + system->resetFilters(); + + ViewController::get()->reloadSystemListViewTheme(system); + ViewController::get()->reloadGameListView(system); + } + } }); - // Folder View Mode - auto foldersBehavior = std::make_shared< OptionListComponent >(mWindow, _("SHOW FOLDERS"), false); + mWindow->pushGui(themeconfig); +} - foldersBehavior->add(_("always"), "always", Settings::getInstance()->getString("FolderViewMode") == "always"); - foldersBehavior->add(_("never"), "never", Settings::getInstance()->getString("FolderViewMode") == "never"); - foldersBehavior->add(_("having multiple games"), "having multiple games", Settings::getInstance()->getString("FolderViewMode") == "having multiple games"); +void GuiMenu::openUISettings() +{ + auto pthis = this; + Window* window = mWindow; - s->addWithLabel(_("SHOW FOLDERS"), foldersBehavior); - s->addSaveFunc([s, foldersBehavior] - { - if (Settings::getInstance()->setString("FolderViewMode", foldersBehavior->getSelected())) - s->setVariable("reloadAll", true); - }); + auto s = new GuiSettings(mWindow, _("UI SETTINGS").c_str()); - // Show parent folder - auto parentFolder = std::make_shared(mWindow); - parentFolder->setState(Settings::getInstance()->getBool("ShowParentFolder")); - s->addWithLabel(_("SHOW '..' PARENT FOLDER"), parentFolder); - s->addSaveFunc([s, parentFolder] - { - if (Settings::getInstance()->setBool("ShowParentFolder", parentFolder->getState())) - s->setVariable("reloadAll", true); - }); + // theme set + auto theme = ThemeData::getMenuTheme(); + auto themeSets = ThemeData::getThemeSets(); + auto system = ViewController::get()->getState().getSystem(); - // Show flags - auto showRegionFlags = std::make_shared>(mWindow, _("SHOW REGION FLAG"), false); - showRegionFlags->addRange({ { _("NO"), "default" },{ _("BEFORE NAME") , "1" },{ _("AFTER NAME"), "2" } }, Settings::getInstance()->getString("ShowFlags")); - s->addWithLabel(_("SHOW REGION FLAG"), showRegionFlags); - s->addSaveFunc([s, showRegionFlags] - { - if (Settings::getInstance()->setString("ShowFlags", showRegionFlags->getSelected())) - s->setVariable("reloadAll", true); - }); + s->addGroup(_("APPEARANCE")); - // Show SaveStates - auto showSaveStates = std::make_shared(mWindow); - showSaveStates->setState(Settings::getInstance()->getBool("ShowSaveStates")); - s->addWithLabel(_("SHOW SAVESTATE ICON"), showSaveStates); - s->addSaveFunc([s, showSaveStates] + if (system != nullptr && !themeSets.empty()) { - if (Settings::getInstance()->setBool("ShowSaveStates", showSaveStates->getState())) - s->setVariable("reloadAll", true); - }); + auto selectedSet = themeSets.find(Settings::getInstance()->getString("ThemeSet")); + if (selectedSet == themeSets.end()) + selectedSet = themeSets.begin(); - // Show Manual - auto showManual = std::make_shared(mWindow); - showManual->setState(Settings::getInstance()->getBool("ShowManualIcon")); - s->addWithLabel(_("SHOW MANUAL ICON"), showManual); - s->addSaveFunc([s, showManual] - { - if (Settings::getInstance()->setBool("ShowManualIcon", showManual->getState())) - s->setVariable("reloadAll", true); - }); + auto theme_set = std::make_shared >(mWindow, _("THEME SET"), false); - // filenames - auto showFilesnames = std::make_shared(mWindow); - showFilesnames->setState(Settings::getInstance()->getBool("ShowFilenames")); - s->addWithLabel(_("SHOW FILENAMES INSTEAD"), showFilesnames); - s->addSaveFunc([showFilesnames, s] - { - if (Settings::getInstance()->setBool("ShowFilenames", showFilesnames->getState())) - { - SystemData::resetSettings(); - FileData::resetSettings(); + std::vector themeList; + for (auto it = themeSets.begin(); it != themeSets.end(); it++) + themeList.push_back(it->first); - s->setVariable("reloadCollections", true); - s->setVariable("reloadAll", true); - } - }); + std::sort(themeList.begin(), themeList.end(), [](const std::string& a, const std::string& b) -> bool { return Utils::String::toLower(a).compare(Utils::String::toLower(b)) < 0; }); - auto ignoreArticles = std::make_shared(mWindow); - ignoreArticles->setState(Settings::getInstance()->getBool("IgnoreLeadingArticles")); - s->addWithLabel(_("IGNORE LEADING ARTICLES WHEN SORTING"), ignoreArticles); - s->addSaveFunc([s, ignoreArticles] - { - if (Settings::getInstance()->setBool("IgnoreLeadingArticles", ignoreArticles->getState())) + for (auto themeName : themeList) + theme_set->add(themeName, themeName, themeName == selectedSet->first); + + //for (auto it = themeSets.begin(); it != themeSets.end(); it++) + // theme_set->add(it->first, it->first, it == selectedSet); + + s->addWithLabel(_("THEME SET"), theme_set); + s->addSaveFunc([s, theme_set, pthis, window, system] { - s->setVariable("reloadAll", true); - } - }); + std::string oldTheme = Settings::getInstance()->getString("ThemeSet"); + if (oldTheme != theme_set->getSelected()) + { + saveSubsetSettings(); + + Settings::getInstance()->setString("ThemeSet", theme_set->getSelected()); + + // theme changed without setting options, forcing options to avoid crash/blank theme + Settings::getInstance()->setString("ThemeRegionName", ""); + Settings::getInstance()->setString("ThemeColorSet", ""); + Settings::getInstance()->setString("ThemeIconSet", ""); + Settings::getInstance()->setString("ThemeMenu", ""); + Settings::getInstance()->setString("ThemeSystemView", ""); + Settings::getInstance()->setString("ThemeGamelistView", ""); + Settings::getInstance()->setString("GamelistViewStyle", ""); + Settings::getInstance()->setString("DefaultGridSize", ""); + + for(auto sm : Settings::getInstance()->getStringMap()) + if (Utils::String::startsWith(sm.first, "subset.")) + Settings::getInstance()->setString(sm.first, ""); + + for (auto sysIt = SystemData::sSystemVector.cbegin(); sysIt != SystemData::sSystemVector.cend(); sysIt++) + (*sysIt)->setSystemViewMode("automatic", Vector2f(0,0)); - s->onFinalize([s, pthis, window] - { - if (s->getVariable("reloadCollections")) - CollectionSystemManager::get()->updateSystemsList(); + loadSubsetSettings(theme_set->getSelected()); - if (s->getVariable("reloadAll")) - { - ViewController::get()->reloadAll(window); - } + s->setVariable("reloadCollections", true); + s->setVariable("reloadAll", true); + s->setVariable("reloadGuiMenu", true); - if (s->getVariable("reloadGuiMenu")) + Scripting::fireEvent("theme-changed", theme_set->getSelected(), oldTheme); + } + }); + + bool showThemeConfiguration = system->getTheme()->hasSubsets() || system->getTheme()->hasView("grid"); + if (showThemeConfiguration) { - delete pthis; - window->pushGui(new GuiMenu(window)); + s->addSubMenu(_("THEME CONFIGURATION"), [this, s, theme_set]() { openThemeConfiguration(mWindow, s, theme_set); }); } - }); + else // GameList view style only, acts like Retropie for simple themes + { + auto gamelist_style = std::make_shared< OptionListComponent >(mWindow, _("GAMELIST VIEW STYLE"), false); + std::vector> styles; + styles.push_back(std::pair("automatic", _("automatic"))); - mWindow->pushGui(s); -} + auto system = ViewController::get()->getState().getSystem(); + if (system != NULL) + { + auto mViews = system->getTheme()->getViewsOfTheme(); + for (auto it = mViews.cbegin(); it != mViews.cend(); ++it) + styles.push_back(*it); + } + else + { + styles.push_back(std::pair("basic", _("basic"))); + styles.push_back(std::pair("detailed", _("detailed"))); + styles.push_back(std::pair("video", _("video"))); + styles.push_back(std::pair("grid", _("grid"))); + } -void GuiMenu::openSoundSettings() -{ - auto s = new GuiSettings(mWindow, _("SOUND SETTINGS").c_str()); + auto viewPreference = Settings::getInstance()->getString("GamelistViewStyle"); + if (!system->getTheme()->hasView(viewPreference)) + viewPreference = "automatic"; - if (GetEnv("DEVICE_SW_HP_SWITCH") == "true") { - s->addGroup(_("OUTPUT")); + for (auto it = styles.cbegin(); it != styles.cend(); it++) + gamelist_style->add(it->second, it->first, viewPreference == it->first); - // sw headphone enable - auto sw_hp_enabled = std::make_shared(mWindow); - bool hpbaseEnabled = SystemConf::getInstance()->get("headphone.enabled") == "1"; - sw_hp_enabled->setState(hpbaseEnabled); - s->addWithLabel(_("ENABLE HEADPHONE JACK"), sw_hp_enabled); - s->addSaveFunc([sw_hp_enabled] - { - if (sw_hp_enabled->getState() == false) { - runSystemCommand("amixer -c0 sset \"Playback Mux\" \"SPK\"", "", nullptr); - } else { - runSystemCommand("amixer -c0 sset \"Playback Mux\" \"HP\"", "", nullptr); + s->addWithLabel(_("GAMELIST VIEW STYLE"), gamelist_style); + s->addSaveFunc([s, gamelist_style, window] { + if (Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected())) + { + s->setVariable("reloadAll", true); + s->setVariable("reloadGuiMenu", true); } - bool swhpenabled = sw_hp_enabled->getState(); - SystemConf::getInstance()->set("headphone.enabled", swhpenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); }); + } } + // language choice + auto language_choice = std::make_shared >(window, _("LANGUAGE"), false); - if (VolumeControl::getInstance()->isAvailable()) - { - s->addGroup(_("VOLUME")); - - // volume - auto volume = std::make_shared(mWindow, 0.f, 100.f, 10.f, "%"); - volume->setValue((float)VolumeControl::getInstance()->getVolume()); - volume->setOnValueChanged([](const float &newVal) { VolumeControl::getInstance()->setVolume((int)Math::round(newVal)); }); - s->addWithLabel(_("SYSTEM VOLUME"), volume); - s->addSaveFunc([this, volume] - { - VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); - SystemConf::getInstance()->set("audio.volume", std::to_string((int)round(volume->getValue()))); - }); - - // Music Volume - auto musicVolume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); - musicVolume->setValue(Settings::getInstance()->getInt("MusicVolume")); - musicVolume->setOnValueChanged([](const float &newVal) { Settings::getInstance()->setInt("MusicVolume", (int)round(newVal)); }); - s->addWithLabel(_("MUSIC VOLUME"), musicVolume); - //s->addSaveFunc([this, musicVolume] { Settings::getInstance()->setInt("MusicVolume", (int)round(musicVolume->getValue())); }); - - auto volumePopup = std::make_shared(mWindow); - volumePopup->setState(Settings::getInstance()->getBool("VolumePopup")); - s->addWithLabel(_("SHOW OVERLAY WHEN VOLUME CHANGES"), volumePopup); - s->addSaveFunc([volumePopup] { Settings::getInstance()->setBool("VolumePopup", volumePopup->getState()); }); - } + std::string language = SystemConf::getInstance()->get("system.language"); + if (language.empty()) + language = "en_US"; - s->addGroup(_("MUSIC")); + language_choice->add("ARABIC", "ar_YE", language == "ar_YE"); + language_choice->add("CATALÀ", "ca_ES", language == "ca_ES"); + language_choice->add("CYMRAEG", "cy_GB", language == "cy_GB"); + language_choice->add("DEUTSCH", "de_DE", language == "de_DE"); + language_choice->add("GREEK", "el_GR", language == "el_GR"); + language_choice->add("ENGLISH", "en_US", language == "en_US" || language == "en"); + language_choice->add("ESPAÑOL", "es_ES", language == "es_ES" || language == "es"); + language_choice->add("ESPAÑOL MEXICANO", "es_MX", language == "es_MX"); + language_choice->add("BASQUE", "eu_ES", language == "eu_ES"); + language_choice->add("FRANÇAIS", "fr_FR", language == "fr_FR" || language == "fr"); + language_choice->add("עברית", "he_IL", language == "he_IL"); + language_choice->add("HUNGARIAN", "hu_HU", language == "hu_HU"); + language_choice->add("ITALIANO", "it_IT", language == "it_IT"); + language_choice->add("JAPANESE", "ja_JP", language == "ja_JP"); + language_choice->add("KOREAN", "ko_KR", language == "ko_KR" || language == "ko"); + language_choice->add("NORWEGIAN BOKMAL", "nb_NO", language == "nb_NO"); + language_choice->add("DUTCH", "nl_NL", language == "nl_NL"); + language_choice->add("NORWEGIAN", "nn_NO", language == "nn_NO"); + language_choice->add("OCCITAN", "oc_FR", language == "oc_FR"); + language_choice->add("POLISH", "pl_PL", language == "pl_PL"); + language_choice->add("PORTUGUES BRASILEIRO", "pt_BR", language == "pt_BR"); + language_choice->add("PORTUGUES PORTUGAL", "pt_PT", language == "pt_PT"); + language_choice->add("РУССКИЙ", "ru_RU", language == "ru_RU"); + language_choice->add("SVENSKA", "sv_SE", language == "sv_SE"); + language_choice->add("TÜRKÇE", "tr_TR", language == "tr_TR"); + language_choice->add("Українська", "uk_UA", language == "uk_UA"); + language_choice->add("简体中文", "zh_CN", language == "zh_CN"); + language_choice->add("正體中文", "zh_TW", language == "zh_TW"); + s->addWithLabel(_("LANGUAGE"), language_choice); - // disable sounds - auto music_enabled = std::make_shared(mWindow); - music_enabled->setState(Settings::getInstance()->getBool("audio.bgmusic")); - s->addWithLabel(_("FRONTEND MUSIC"), music_enabled); - s->addSaveFunc([music_enabled] + s->addSaveFunc([window, language_choice, language, s] { - if (Settings::getInstance()->setBool("audio.bgmusic", music_enabled->getState())) + bool reboot = false; + + if (language_choice->changed()) { - if (music_enabled->getState()) - AudioManager::getInstance()->playRandomMusic(); - else - AudioManager::getInstance()->stopMusic(); + std::string selectedLanguage = language_choice->getSelected(); + std::string msg = _("You are about to set your language to:") +"\n" + selectedLanguage + "\n"; + msg += _("Emulationstation will restart")+"\n"; + msg += _("Do you want to proceed ?"); + window->pushGui(new GuiMsgBox(window, msg, _("YES"), [selectedLanguage] { + SystemConf::getInstance()->set("system.language", selectedLanguage); + SystemConf::getInstance()->saveSystemConf(); + quitES(QuitMode::QUIT); + }, "NO",nullptr)); +#ifdef HAVE_INTL + reboot = true; +#endif } - }); - - auto display_titles = std::make_shared(mWindow); - display_titles->setState(Settings::getInstance()->getBool("audio.display_titles")); - s->addWithLabel(_("DISPLAY SONG TITLES"), display_titles); - s->addSaveFunc([display_titles] { - Settings::getInstance()->setBool("audio.display_titles", display_titles->getState()); - }); - - auto titles_time = std::make_shared(mWindow, 2.f, 120.f, 2.f, "s"); - titles_time->setValue(Settings::getInstance()->getInt("audio.display_titles_time")); - s->addWithLabel(_("SONG TITLE DISPLAY DURATION"), titles_time); - s->addSaveFunc([titles_time] { - Settings::getInstance()->setInt("audio.display_titles_time", (int)Math::round(titles_time->getValue())); - }); - auto music_per_system = std::make_shared(mWindow); - music_per_system->setState(Settings::getInstance()->getBool("audio.persystem")); - s->addWithLabel(_("ONLY PLAY SYSTEM-SPECIFIC MUSIC FOLDER"), music_per_system); - s->addSaveFunc([music_per_system] { - if (Settings::getInstance()->setBool("audio.persystem", music_per_system->getState())) - AudioManager::getInstance()->changePlaylist(ViewController::get()->getState().getSystem()->getTheme(), true); - }); + if (reboot) + window->displayNotificationMessage(_U("\uF011 ") + _("A REBOOT OF THE SYSTEM IS REQUIRED TO APPLY THE NEW CONFIGURATION")); - auto enableThemeMusics = std::make_shared(mWindow); - enableThemeMusics->setState(Settings::getInstance()->getBool("audio.thememusics")); - s->addWithLabel(_("PLAY SYSTEM-SPECIFIC MUSIC"), enableThemeMusics); - s->addSaveFunc([enableThemeMusics] { - if (Settings::getInstance()->setBool("audio.thememusics", enableThemeMusics->getState())) - AudioManager::getInstance()->changePlaylist(ViewController::get()->getState().getSystem()->getTheme(), true); }); - auto videolowermusic = std::make_shared(mWindow); - videolowermusic->setState(Settings::getInstance()->getBool("VideoLowersMusic")); - s->addWithLabel(_("LOWER MUSIC WHEN PLAYING VIDEO"), videolowermusic); - s->addSaveFunc([videolowermusic] { Settings::getInstance()->setBool("VideoLowersMusic", videolowermusic->getState()); }); - - s->addGroup(_("SOUNDS")); + // UI RESTRICTIONS + auto UImodeSelection = std::make_shared< OptionListComponent >(mWindow, _("UI MODE"), false); + std::vector UImodes = UIModeController::getInstance()->getUIModes(); + for (auto it = UImodes.cbegin(); it != UImodes.cend(); it++) + UImodeSelection->add(_(it->c_str()), *it, Settings::getInstance()->getString("UIMode") == *it); - // disable sounds - auto sounds_enabled = std::make_shared(mWindow); - sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds")); - s->addWithLabel(_("ENABLE NAVIGATION SOUNDS"), sounds_enabled); - s->addSaveFunc([sounds_enabled] + s->addWithLabel(_("UI MODE"), UImodeSelection); + s->addSaveFunc([UImodeSelection, window] { - if (sounds_enabled->getState() && !Settings::getInstance()->getBool("EnableSounds") && PowerSaver::getMode() == PowerSaver::INSTANT) + std::string selectedMode = UImodeSelection->getSelected(); + if (selectedMode != "Full") { - Settings::getInstance()->setPowerSaverMode("default"); - PowerSaver::init(); + std::string msg = _("You are changing the UI to a restricted mode:\nThis will hide most menu-options to prevent changes to the system.\nTo unlock and return to the full UI, enter this code:") + "\n"; + msg += "\"" + UIModeController::getInstance()->getFormattedPassKeyStr() + "\"\n\n"; + msg += _("Do you want to proceed ?"); + window->pushGui(new GuiMsgBox(window, msg, + _("YES"), [selectedMode] { + LOG(LogDebug) << "Setting UI mode to " << selectedMode; + Settings::getInstance()->setString("UIMode", selectedMode); + Settings::getInstance()->saveFile(); + }, _("NO"), nullptr)); } - Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); - }); - - auto batteryWarning = std::make_shared(mWindow); - bool batteryWarningEnabled = SystemConf::getInstance()->get("system.battery.warning") == "1"; - batteryWarning->setState(batteryWarningEnabled); - s->addWithLabel(_("ENABLE AUDIBLE BATTERY WARNING"), batteryWarning); - s->addSaveFunc([batteryWarning] { - bool batteryWarningEnabled = batteryWarning->getState(); - SystemConf::getInstance()->set("system.battery.warning", batteryWarningEnabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); - - auto video_audio = std::make_shared(mWindow); - video_audio->setState(Settings::getInstance()->getBool("VideoAudio")); - s->addWithLabel(_("ENABLE VIDEO PREVIEW AUDIO"), video_audio); - s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); }); - - - - mWindow->pushGui(s); -} + }); -void GuiMenu::openWifiSettings(Window* win, std::string title, std::string data, const std::function& onsave) -{ - win->pushGui(new GuiWifi(win, title, data, onsave)); -} + // retroarch.menu_driver choose from 'auto' (default), 'xmb', 'rgui', 'ozone', 'glui' + auto retroarchRgui = std::make_shared< OptionListComponent >(mWindow, _("RETROARCH MENU DRIVER"), false); + std::vector driver; + driver.push_back("default"); + driver.push_back("xmb"); + driver.push_back("rgui"); + driver.push_back("ozone"); + driver.push_back("glui"); -void GuiMenu::openNetworkSettings_batocera(bool selectWifiEnable, bool selectAdhocEnable) -{ - auto theme = ThemeData::getMenuTheme(); - std::shared_ptr font = theme->Text.font; - unsigned int color = theme->Text.color; + auto currentDriver = SystemConf::getInstance()->get("global.retroarch.menu_driver"); + if (currentDriver.empty()) + currentDriver = "default"; - Window *window = mWindow; + for (auto it = driver.cbegin(); it != driver.cend(); it++) + retroarchRgui->add(_(it->c_str()), *it, currentDriver == *it); - auto s = new GuiSettings(mWindow, _("NETWORK SETTINGS").c_str()); - s->addGroup(_("INFORMATION")); + s->addWithLabel(_("RETROARCH MENU DRIVER"), retroarchRgui); + s->addSaveFunc([retroarchRgui] + { + SystemConf::getInstance()->set("global.retroarch.menu_driver", retroarchRgui->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + }); - auto ip = std::make_shared(mWindow, ApiSystem::getInstance()->getIpAdress(), font, color); - s->addWithLabel(_("IP ADDRESS"), ip); + auto invertJoy = std::make_shared(mWindow); + invertJoy->setState(Settings::getInstance()->getBool("InvertButtons")); + s->addWithLabel(_("SWITCH A & B BUTTONS IN EMULATIONSTATION"), invertJoy); + s->addSaveFunc([this, s, invertJoy] + { + if (Settings::getInstance()->setBool("InvertButtons", invertJoy->getState())) + { + std::string trueFalse = "false"; + if ( invertJoy->getState() == true ) { + trueFalse = "true"; + } + Settings::getInstance()->setString("subset.swap-a-b", trueFalse); + SystemConf::getInstance()->saveSystemConf(); + InputConfig::AssignActionButtons(); + s->setVariable("reloadAll", true); + } + }); - auto status = std::make_shared(mWindow, ApiSystem::getInstance()->ping() ? _("CONNECTED") : _("NOT CONNECTED"), font, color); - s->addWithLabel(_("INTERNET STATUS"), status); + auto fps_enabled = std::make_shared(mWindow); + bool fpsEnabled = SystemConf::getInstance()->get("global.showFPS") == "1"; + fps_enabled->setState(fpsEnabled); + s->addWithLabel(_("SHOW RETROARCH FPS"), fps_enabled); + s->addSaveFunc([fps_enabled] { + bool fpsenabled = fps_enabled->getState(); + SystemConf::getInstance()->set("global.showFPS", fpsenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - // Network Indicator - auto networkIndicator = std::make_shared(mWindow); - networkIndicator->setState(Settings::getInstance()->getBool("ShowNetworkIndicator")); - s->addWithLabel(_("SHOW NETWORK INDICATOR"), networkIndicator); - networkIndicator->setOnChangedCallback([networkIndicator] { Settings::getInstance()->setBool("ShowNetworkIndicator", networkIndicator->getState()); }); + auto desktop_enabled = std::make_shared(mWindow); + bool desktopEnabled = SystemConf::getInstance()->get("desktop.enabled") == "1"; + desktop_enabled->setState(desktopEnabled); + s->addWithLabel(_("DESKTOP MODE"), desktop_enabled); + s->addSaveFunc([this,desktop_enabled] { + if (desktop_enabled->changed()) { + std::string msg = _("The system will restart")+"\n"; + msg += _("Do you want to continue?"); + mWindow->pushGui(new GuiMsgBox(mWindow,msg, _("YES"), + [this,desktop_enabled] { + bool desktopenabled = desktop_enabled->getState(); + SystemConf::getInstance()->set("desktop.enabled", desktopenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + quitES(QuitMode::REBOOT); + }, "NO",nullptr)); + } + }); - s->addGroup(_("NETWORK CONFIGURATION")); - // Hostname - s->addInputTextRow(_("HOSTNAME"), "system.hostname", false); + s->addGroup(_("DISPLAY OPTIONS")); - // Wifi enable - auto enable_net = std::make_shared(mWindow); - bool networkEnabled = SystemConf::getInstance()->getBool("network.enabled"); - enable_net->setState(networkEnabled); + s->addEntry(_("SCREENSAVER SETTINGS"), true, std::bind(&GuiMenu::openScreensaverOptions, this)); - // Define enable_adhoc early so it is available to addSaveFunc. - auto enable_adhoc = std::make_shared(mWindow); + // transition style + auto transition_style = std::make_shared>(mWindow, _("LIST TRANSITION STYLE"), false); + transition_style->addRange({"default", "fade", "slide", "fade & slide", "instant"}, Settings::TransitionStyle()); + s->addWithLabel(_("LIST TRANSITION STYLE"), transition_style); + s->addSaveFunc([transition_style] { Settings::setTransitionStyle(transition_style->getSelected()); }); - s->addWithLabel(_("ENABLE NETWORK"), enable_net, selectWifiEnable); + // game transition style + auto transitionOfGames_style = std::make_shared>(mWindow, _("GAME LAUNCH TRANSITION"), false); + transitionOfGames_style->addRange({"default", "fade", "slide", "instant"}, Settings::GameTransitionStyle()); + s->addWithLabel(_("GAME LAUNCH TRANSITION"), transitionOfGames_style); + s->addSaveFunc([transitionOfGames_style] { Settings::setGameTransitionStyle(transitionOfGames_style->getSelected()); }); - const std::string wifiSSID = SystemConf::getInstance()->get("wifi.ssid"); - const std::string wifiKEY = SystemConf::getInstance()->get("wifi.key"); + // clock + auto clock = std::make_shared(mWindow); + clock->setState(Settings::getInstance()->getBool("DrawClock")); + s->addWithLabel(_("SHOW CLOCK"), clock); + s->addSaveFunc( + [clock] { Settings::getInstance()->setBool("DrawClock", clock->getState()); }); - s->addInputTextRow(_("WIFI SSID"), "wifi.ssid", false, false, &openWifiSettings); - s->addSaveFunc([this, enable_net, enable_adhoc, wifiSSID] { - SystemConf::getInstance()->saveSystemConf(); - const std::string wifissid = SystemConf::getInstance()->get("wifi.ssid"); - if (enable_net->getState() == true && enable_adhoc->getState() == false && wifiSSID != wifissid) - { - std::string wifikey = SystemConf::getInstance()->get("wifi.key"); - ApiSystem::getInstance()->disableWifi(); - ApiSystem::getInstance()->enableWifi(wifissid, wifikey); - } + // show help + auto show_help = std::make_shared(mWindow); + show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts")); + s->addWithLabel(_("ON-SCREEN HELP"), show_help); + s->addSaveFunc([s, show_help] + { + if (Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState())) + s->setVariable("reloadAll", true); }); - s->addInputTextRow(_("WIFI KEY"), "wifi.key", true); - s->addSaveFunc([this, enable_net, enable_adhoc, wifiKEY] { - SystemConf::getInstance()->saveSystemConf(); - const std::string wifikey = SystemConf::getInstance()->get("wifi.key"); - if (enable_net->getState() == true && enable_adhoc->getState() == false && wifiKEY != wifikey) - { - std::string wifissid = SystemConf::getInstance()->get("wifi.ssid"); - ApiSystem::getInstance()->disableWifi(); - ApiSystem::getInstance()->enableWifi(wifissid, wifikey); - } - }); + // Battery indicator + if (queryBatteryInformation().hasBattery) + { + auto batteryStatus = std::make_shared >(mWindow, _("SHOW BATTERY STATUS"), false); + batteryStatus->addRange({ { _("NO"), "" },{ _("ICON"), "icon" },{ _("ICON AND TEXT"), "text" } }, Settings::getInstance()->getString("ShowBattery")); + s->addWithLabel(_("SHOW BATTERY STATUS"), batteryStatus); + s->addSaveFunc([batteryStatus] { Settings::getInstance()->setString("ShowBattery", batteryStatus->getSelected()); }); + } - auto optionsAdhocID = std::make_shared >(mWindow, _("LOCAL PLAY ID"), false); - std::string selectedAdhocID = SystemConf::getInstance()->get("wifi.adhoc.id"); + s->addGroup(_("GAMELIST OPTIONS")); - auto optionsChannels = std::make_shared >(mWindow, _("LOCAL NETWORK CHANNEL"), false); + // Enable Video Previews + auto enable_preview = std::make_shared(mWindow); + enable_preview->setState(Settings::getInstance()->getBool("EnableVideoPreviews")); + s->addWithLabel(_("SHOW VIDEO PREVIEWS"), enable_preview); + s->addSaveFunc([enable_preview] { Settings::getInstance()->setBool("EnableVideoPreviews", enable_preview->getState()); }); - std::vector availableChannels = ApiSystem::getInstance()->getAvailableChannels(); - std::string selectedChannel = SystemConf::getInstance()->get("wifi.adhoc.channel"); + // Show favorites first in gamelists + auto favoritesFirstSwitch = std::make_shared(mWindow); + favoritesFirstSwitch->setState(Settings::getInstance()->getBool("FavoritesFirst")); + s->addWithLabel(_("SHOW FAVORITES ON TOP"), favoritesFirstSwitch); + s->addSaveFunc([s, favoritesFirstSwitch] + { + if (Settings::getInstance()->setBool("FavoritesFirst", favoritesFirstSwitch->getState())) + s->setVariable("reloadAll", true); + }); - // Enable or disable ipv6 - auto ipv6_enable = std::make_shared(mWindow); - bool ipv6Enabled = SystemConf::getInstance()->get("ipv6.enabled") == "1"; - ipv6_enable->setState(ipv6Enabled); - s->addWithLabel(_("ENABLE IPV6"), ipv6_enable); - ipv6_enable->setOnChangedCallback([ipv6_enable] { - bool ipv6Enabled = ipv6_enable->getState(); - SystemConf::getInstance()->set("ipv6.enabled", ipv6Enabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - runSystemCommand("/usr/bin/toggle-ipv6", "", nullptr); - }); + // hidden files + auto hidden_files = std::make_shared(mWindow); + hidden_files->setState(Settings::ShowHiddenFiles()); + s->addWithLabel(_("SHOW HIDDEN FILES"), hidden_files); + s->addSaveFunc([s, hidden_files] + { + if (Settings::setShowHiddenFiles(hidden_files->getState())) + s->setVariable("reloadAll", true); + }); - s->addGroup(_("LOCAL NETPLAY SETTINGS")); + // Folder View Mode + auto foldersBehavior = std::make_shared< OptionListComponent >(mWindow, _("SHOW FOLDERS"), false); - // Adhoc mode options - bool adhocEnabled = SystemConf::getInstance()->getBool("network.adhoc.enabled"); - enable_adhoc->setState(adhocEnabled); - s->addWithLabel(_("LOCAL PLAY MODE"), enable_adhoc, selectAdhocEnable); + foldersBehavior->add(_("always"), "always", Settings::getInstance()->getString("FolderViewMode") == "always"); + foldersBehavior->add(_("never"), "never", Settings::getInstance()->getString("FolderViewMode") == "never"); + foldersBehavior->add(_("having multiple games"), "having multiple games", Settings::getInstance()->getString("FolderViewMode") == "having multiple games"); - if (selectedAdhocID.empty()) + s->addWithLabel(_("SHOW FOLDERS"), foldersBehavior); + s->addSaveFunc([s, foldersBehavior] { - selectedAdhocID = "1"; - } - optionsAdhocID->add(_("1 (HOST)"),"1", selectedAdhocID == "1"); - optionsAdhocID->add(_("2 (CLIENT 1)"),"2", selectedAdhocID == "2"); - optionsAdhocID->add(_("3 (CLIENT 2)"),"3", selectedAdhocID == "3"); - optionsAdhocID->add(_("4 (CLIENT 3)"),"4", selectedAdhocID == "4"); - s->addWithLabel(_("LOCAL PLAY ID"), optionsAdhocID); - - if (selectedChannel.empty()) - selectedChannel = "6"; - - bool wfound = false; - for (auto it = availableChannels.begin(); it != availableChannels.end(); it++) - { - optionsChannels->add((*it), (*it), selectedChannel == (*it)); - if (selectedChannel == (*it)) - wfound = true; - } + if (Settings::getInstance()->setString("FolderViewMode", foldersBehavior->getSelected())) + s->setVariable("reloadAll", true); + }); - if (!wfound) - optionsChannels->add(selectedChannel, selectedChannel, true); + // Show parent folder + auto parentFolder = std::make_shared(mWindow); + parentFolder->setState(Settings::getInstance()->getBool("ShowParentFolder")); + s->addWithLabel(_("SHOW '..' PARENT FOLDER"), parentFolder); + s->addSaveFunc([s, parentFolder] + { + if (Settings::getInstance()->setBool("ShowParentFolder", parentFolder->getState())) + s->setVariable("reloadAll", true); + }); - s->addWithLabel(_("LOCAL NETWORK CHANNEL"), optionsChannels); + // Show flags + auto showRegionFlags = std::make_shared>(mWindow, _("SHOW REGION FLAG"), false); + showRegionFlags->addRange({ { _("NO"), "default" },{ _("BEFORE NAME") , "1" },{ _("AFTER NAME"), "2" } }, Settings::getInstance()->getString("ShowFlags")); + s->addWithLabel(_("SHOW REGION FLAG"), showRegionFlags); + s->addSaveFunc([s, showRegionFlags] + { + if (Settings::getInstance()->setString("ShowFlags", showRegionFlags->getSelected())) + s->setVariable("reloadAll", true); + }); - enable_adhoc->setOnChangedCallback([adhocEnabled, networkEnabled, enable_net, enable_adhoc, optionsAdhocID, selectedAdhocID, optionsChannels, selectedChannel, window] + // Show SaveStates + auto showSaveStates = std::make_shared(mWindow); + showSaveStates->setState(Settings::getInstance()->getBool("ShowSaveStates")); + s->addWithLabel(_("SHOW SAVESTATE ICON"), showSaveStates); + s->addSaveFunc([s, showSaveStates] { - SystemConf::getInstance()->set("wifi.adhoc.id", optionsAdhocID->getSelected()); - SystemConf::getInstance()->set("wifi.adhoc.channel", optionsChannels->getSelected()); + if (Settings::getInstance()->setBool("ShowSaveStates", showSaveStates->getState())) + s->setVariable("reloadAll", true); + }); - std::string newSSID = SystemConf::getInstance()->get("wifi.ssid"); - std::string newKey = SystemConf::getInstance()->get("wifi.key"); + // Show Manual + auto showManual = std::make_shared(mWindow); + showManual->setState(Settings::getInstance()->getBool("ShowManualIcon")); + s->addWithLabel(_("SHOW MANUAL ICON"), showManual); + s->addSaveFunc([s, showManual] + { + if (Settings::getInstance()->setBool("ShowManualIcon", showManual->getState())) + s->setVariable("reloadAll", true); + }); - SystemConf::getInstance()->set("global.netplay.host", "192.168.80.1"); - SystemConf::getInstance()->set("global.netplay.port", "55435"); - SystemConf::getInstance()->set("global.netplay.relay", "none"); + // filenames + auto showFilesnames = std::make_shared(mWindow); + showFilesnames->setState(Settings::getInstance()->getBool("ShowFilenames")); + s->addWithLabel(_("SHOW FILENAMES INSTEAD"), showFilesnames); + s->addSaveFunc([showFilesnames, s] + { + if (Settings::getInstance()->setBool("ShowFilenames", showFilesnames->getState())) + { + SystemData::resetSettings(); + FileData::resetSettings(); - bool adhocenabled = enable_adhoc->getState(); - SystemConf::getInstance()->setBool("network.adhoc.enabled", adhocenabled); - SystemConf::getInstance()->saveSystemConf(); + s->setVariable("reloadCollections", true); + s->setVariable("reloadAll", true); + } + }); - if (enable_net->getState() == true) + auto ignoreArticles = std::make_shared(mWindow); + ignoreArticles->setState(Settings::getInstance()->getBool("IgnoreLeadingArticles")); + s->addWithLabel(_("IGNORE LEADING ARTICLES WHEN SORTING"), ignoreArticles); + s->addSaveFunc([s, ignoreArticles] + { + if (Settings::getInstance()->setBool("IgnoreLeadingArticles", ignoreArticles->getState())) { - ApiSystem::getInstance()->disableWifi(); - ApiSystem::getInstance()->enableWifi(newSSID, newKey); + s->setVariable("reloadAll", true); } }); - enable_net->setOnChangedCallback([enable_net, enable_adhoc, networkEnabled, adhocEnabled, window] - { - if (enable_net->getState() == true && enable_adhoc->getState() == false) - { - std::string newSSID = SystemConf::getInstance()->get("wifi.ssid"); - std::string newKey = SystemConf::getInstance()->get("wifi.key"); - ApiSystem::getInstance()->enableWifi(newSSID, newKey); - } - else - { - ApiSystem::getInstance()->disableWifi(); - } - bool networkenabled = enable_net->getState(); - SystemConf::getInstance()->setBool("network.enabled", networkenabled); - SystemConf::getInstance()->saveSystemConf(); - }); - - s->addGroup(_("NETWORK SERVICES")); - - auto sshd_enabled = std::make_shared(mWindow); - bool sshbaseEnabled = SystemConf::getInstance()->get("ssh.enabled") == "1"; - sshd_enabled->setState(sshbaseEnabled); - s->addWithLabel(_("ENABLE SSH"), sshd_enabled); - sshd_enabled->setOnChangedCallback([sshd_enabled] { - if (sshd_enabled->getState() == false) { - runSystemCommand("systemctl stop sshd", "", nullptr); - runSystemCommand("systemctl disable sshd", "", nullptr); - runSystemCommand("rm /storage/.cache/services/sshd.conf", "", nullptr); - } else { - runSystemCommand("mkdir -p /storage/.cache/services/", "", nullptr); - runSystemCommand("touch /storage/.cache/services/sshd.conf", "", nullptr); - runSystemCommand("systemctl enable sshd", "", nullptr); - runSystemCommand("systemctl start sshd", "", nullptr); - } - bool sshenabled = sshd_enabled->getState(); - SystemConf::getInstance()->set("ssh.enabled", sshenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); + s->onFinalize([s, pthis, window] + { + if (s->getVariable("reloadCollections")) + CollectionSystemManager::get()->updateSystemsList(); - auto samba_enabled = std::make_shared(mWindow); - bool smbbaseEnabled = SystemConf::getInstance()->get("samba.enabled") == "1"; - samba_enabled->setState(smbbaseEnabled); - s->addWithLabel(_("ENABLE SAMBA"), samba_enabled); - samba_enabled->setOnChangedCallback([samba_enabled] { - if (samba_enabled->getState() == false) { - runSystemCommand("systemctl stop nmbd", "", nullptr); - runSystemCommand("systemctl stop smbd", "", nullptr); - runSystemCommand("rm /storage/.cache/services/smb.conf", "", nullptr); - } else { - runSystemCommand("mkdir -p /storage/.cache/services/", "", nullptr); - runSystemCommand("touch /storage/.cache/services/smb.conf", "", nullptr); - runSystemCommand("systemctl start nmbd", "", nullptr); - runSystemCommand("systemctl start smbd", "", nullptr); - } - bool sambaenabled = samba_enabled->getState(); - SystemConf::getInstance()->set("samba.enabled", sambaenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); + if (s->getVariable("reloadAll")) + { + ViewController::get()->reloadAll(window); + } - auto simple_http_enabled = std::make_shared(mWindow); - bool simplehttpEnabled = SystemConf::getInstance()->get("simplehttp.enabled") == "1"; - simple_http_enabled->setState(simplehttpEnabled); - s->addWithLabel(_("ENABLE SIMPLE HTTP SERVER"), simple_http_enabled); - simple_http_enabled->setOnChangedCallback([simple_http_enabled] { - if(simple_http_enabled->getState() == false) { - runSystemCommand("systemctl disable --now simple-http-server", "", nullptr); - } else { - runSystemCommand("systemctl enable --now simple-http-server", "", nullptr); - } - bool simplehttpenabled = simple_http_enabled->getState(); - SystemConf::getInstance()->set("simplehttp.enabled", simplehttpenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); + if (s->getVariable("reloadGuiMenu")) + { + delete pthis; + window->pushGui(new GuiMenu(window)); + } + }); - auto optionsUSBGadget = std::make_shared >(mWindow, _("USB GADGET FUNCTION"), false); - std::string selectedUSBGadget = SystemConf::getInstance()->get("usbgadget.function"); - if (selectedUSBGadget.empty()) - selectedUSBGadget = "disabled"; + mWindow->pushGui(s); +} - optionsUSBGadget->add(_("DISABLED"), "disabled", selectedUSBGadget == "disabled"); - optionsUSBGadget->add(_("MTP"), "mtp", selectedUSBGadget == "mtp"); - optionsUSBGadget->add(_("ECM"), "ecm", selectedUSBGadget == "ecm"); +void GuiMenu::openSoundSettings() +{ + auto s = new GuiSettings(mWindow, _("SOUND SETTINGS").c_str()); - s->addWithLabel(_("USB GADGET FUNCTION"), optionsUSBGadget); + if (GetEnv("DEVICE_SW_HP_SWITCH") == "true") { + s->addGroup(_("OUTPUT")); - s->addSaveFunc([this, optionsUSBGadget, selectedUSBGadget] - { - if (optionsUSBGadget->changed()) { - SystemConf::getInstance()->set("usbgadget.function", optionsUSBGadget->getSelected()); + // sw headphone enable + auto sw_hp_enabled = std::make_shared(mWindow); + bool hpbaseEnabled = SystemConf::getInstance()->get("headphone.enabled") == "1"; + sw_hp_enabled->setState(hpbaseEnabled); + s->addWithLabel(_("ENABLE HEADPHONE JACK"), sw_hp_enabled); + s->addSaveFunc([sw_hp_enabled] + { + if (sw_hp_enabled->getState() == false) { + runSystemCommand("amixer -c0 sset \"Playback Mux\" \"SPK\"", "", nullptr); + } else { + runSystemCommand("amixer -c0 sset \"Playback Mux\" \"HP\"", "", nullptr); + } + bool swhpenabled = sw_hp_enabled->getState(); + SystemConf::getInstance()->set("headphone.enabled", swhpenabled ? "1" : "0"); SystemConf::getInstance()->saveSystemConf(); - runSystemCommand("/usr/bin/usbgadget stop", "", nullptr); - if (optionsUSBGadget->getSelected() == "mtp") - runSystemCommand("/usr/bin/usbgadget start mtp", "", nullptr); - else if (optionsUSBGadget->getSelected() == "ecm") { - runSystemCommand("/usr/bin/usbgadget start cdc", "", nullptr); - std::string usbip = std::string(getShOutput(R"(cat /storage/.cache/usbgadget/ip_address.conf)")); - mWindow->pushGui(new GuiMsgBox(mWindow, _("USB Networking enabled, the device IP is ") + usbip, _("OK"), nullptr)); - } - } - }); - - - - s->addGroup(_("CLOUD SERVICES")); - - auto enable_syncthing = std::make_shared(mWindow); - bool syncthingEnabled = SystemConf::getInstance()->get("syncthing.enabled") == "1"; - enable_syncthing->setState(syncthingEnabled); - s->addWithLabel(_("ENABLE SYNCTHING"), enable_syncthing); - enable_syncthing->setOnChangedCallback([enable_syncthing] { - if (enable_syncthing->getState() == false) { - runSystemCommand("systemctl stop syncthing", "", nullptr); - } else { - runSystemCommand("systemctl start syncthing", "", nullptr); - } - bool syncthingenabled = enable_syncthing->getState(); - SystemConf::getInstance()->set("syncthing.enabled", syncthingenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); + }); + } - auto mount_cloud = std::make_shared(mWindow); - bool mntcloudEnabled = SystemConf::getInstance()->get("clouddrive.mounted") == "1"; - mount_cloud->setState(mntcloudEnabled); - s->addWithLabel(_("MOUNT CLOUD DRIVE"), mount_cloud); - mount_cloud->setOnChangedCallback([mount_cloud] { - if (mount_cloud->getState() == false) { - runSystemCommand("rclonectl unmount", "", nullptr); - } else { - runSystemCommand("rclonectl mount", "", nullptr); - } - bool cloudenabled = mount_cloud->getState(); - SystemConf::getInstance()->set("clouddrive.mounted", cloudenabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); - s->addGroup(_("VPN SERVICES")); + if (VolumeControl::getInstance()->isAvailable()) + { + s->addGroup(_("VOLUME")); - const std::string wireguardConfigFile = "/storage/.config/wireguard/wg0.conf"; - if (Utils::FileSystem::exists(wireguardConfigFile)) { - auto wireguard = std::make_shared(mWindow); - bool wgUp = SystemConf::getInstance()->get("wireguard.up") == "1"; - wireguard->setState(wgUp); - s->addWithLabel(_("WIREGUARD VPN"), wireguard); - wireguard->setOnChangedCallback([wireguard, wireguardConfigFile] { - if (wireguard->getState() == false) { - runSystemCommand("wg-quick down " + wireguardConfigFile, "", nullptr); - runSystemCommand("systemctl stop connman-vpn", "", nullptr); - } else { - runSystemCommand("systemctl start connman-vpn", "", nullptr); - runSystemCommand("wg-quick up " + wireguardConfigFile, "", nullptr); - } - SystemConf::getInstance()->set("wireguard.up", wireguard->getState() ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); + // volume + auto volume = std::make_shared(mWindow, 0.f, 100.f, 10.f, "%"); + volume->setValue((float)VolumeControl::getInstance()->getVolume()); + volume->setOnValueChanged([](const float &newVal) { VolumeControl::getInstance()->setVolume((int)Math::round(newVal)); }); + s->addWithLabel(_("SYSTEM VOLUME"), volume); + s->addSaveFunc([this, volume] + { + VolumeControl::getInstance()->setVolume((int)Math::round(volume->getValue())); + SystemConf::getInstance()->set("audio.volume", std::to_string((int)round(volume->getValue()))); }); - } - - auto tailscale = std::make_shared(mWindow); - bool tsUp = SystemConf::getInstance()->get("tailscale.up") == "1"; - tailscale->setState(tsUp); - s->addWithLabel(_("TAILSCALE VPN"), tailscale); - tailscale->setOnChangedCallback([tailscale] { - bool tsEnabled = tailscale->getState(); - if (tsEnabled) { - runSystemCommand("systemctl start tailscaled", "", nullptr); - runSystemCommand("tailscale up --timeout=7s", "", nullptr); - tsEnabled = IsTailscaleUp(); - } else { - runSystemCommand("tailscale down", "", nullptr); - runSystemCommand("systemctl stop tailscaled", "", nullptr); - } - SystemConf::getInstance()->set("tailscale.up", tsEnabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); - }); - std::string tsUrl; - if ( tsUp == true) { - if (!IsTailscaleUp(&tsUrl) && !tsUrl.empty()) { - s->addGroup("TAILSCALE REAUTHENTICATE:"); - s->addGroup(tsUrl); - } + // Music Volume + auto musicVolume = std::make_shared(mWindow, 0.f, 100.f, 1.f, "%"); + musicVolume->setValue(Settings::getInstance()->getInt("MusicVolume")); + musicVolume->setOnValueChanged([](const float &newVal) { Settings::getInstance()->setInt("MusicVolume", (int)round(newVal)); }); + s->addWithLabel(_("MUSIC VOLUME"), musicVolume); + //s->addSaveFunc([this, musicVolume] { Settings::getInstance()->setInt("MusicVolume", (int)round(musicVolume->getValue())); }); + + auto volumePopup = std::make_shared(mWindow); + volumePopup->setState(Settings::getInstance()->getBool("VolumePopup")); + s->addWithLabel(_("SHOW OVERLAY WHEN VOLUME CHANGES"), volumePopup); + s->addSaveFunc([volumePopup] { Settings::getInstance()->setBool("VolumePopup", volumePopup->getState()); }); } - auto zerotier = std::make_shared(mWindow); - bool ztUp = SystemConf::getInstance()->get("zerotier.up") == "1"; - zerotier->setState(ztUp); - s->addWithLabel(_("ZeroTier One"), zerotier); - zerotier->setOnChangedCallback([zerotier] { - bool ztEnabled = zerotier->getState(); - if(ztEnabled) { - runSystemCommand("systemctl start zerotier-one", "", nullptr); - ztEnabled = IsZeroTierUp(); - } else { - runSystemCommand("systemctl stop zerotier-one", "", nullptr); + s->addGroup(_("MUSIC")); + + // disable sounds + auto music_enabled = std::make_shared(mWindow); + music_enabled->setState(Settings::getInstance()->getBool("audio.bgmusic")); + s->addWithLabel(_("FRONTEND MUSIC"), music_enabled); + s->addSaveFunc([music_enabled] + { + if (Settings::getInstance()->setBool("audio.bgmusic", music_enabled->getState())) + { + if (music_enabled->getState()) + AudioManager::getInstance()->playRandomMusic(); + else + AudioManager::getInstance()->stopMusic(); } - SystemConf::getInstance()->set("zerotier.up", ztEnabled ? "1" : "0"); - SystemConf::getInstance()->saveSystemConf(); }); - mWindow->pushGui(s); -} + auto display_titles = std::make_shared(mWindow); + display_titles->setState(Settings::getInstance()->getBool("audio.display_titles")); + s->addWithLabel(_("DISPLAY SONG TITLES"), display_titles); + s->addSaveFunc([display_titles] { + Settings::getInstance()->setBool("audio.display_titles", display_titles->getState()); + }); -bool GuiMenu::IsTailscaleUp(std::string* loginUrl) { - bool loggedOut = false; - ApiSystem::executeScript("tailscale status", [loginUrl, &loggedOut](std::string line) { - const std::string prompt = "Log in at: "; - if (loginUrl && line.find(prompt) == 0) - *loginUrl = line.substr(prompt.length()); + auto titles_time = std::make_shared(mWindow, 2.f, 120.f, 2.f, "s"); + titles_time->setValue(Settings::getInstance()->getInt("audio.display_titles_time")); + s->addWithLabel(_("SONG TITLE DISPLAY DURATION"), titles_time); + s->addSaveFunc([titles_time] { + Settings::getInstance()->setInt("audio.display_titles_time", (int)Math::round(titles_time->getValue())); + }); - if (line.find("Logged out.") != std::string::npos) loggedOut = true; + auto music_per_system = std::make_shared(mWindow); + music_per_system->setState(Settings::getInstance()->getBool("audio.persystem")); + s->addWithLabel(_("ONLY PLAY SYSTEM-SPECIFIC MUSIC FOLDER"), music_per_system); + s->addSaveFunc([music_per_system] { + if (Settings::getInstance()->setBool("audio.persystem", music_per_system->getState())) + AudioManager::getInstance()->changePlaylist(ViewController::get()->getState().getSystem()->getTheme(), true); }); - return !loggedOut; -} -bool GuiMenu::IsZeroTierUp(std::string* networkId) { - bool running = false; - ApiSystem::executeScript("zerotier-cli -D/storage/.config/zerotier/ info", [networkId, &running](std::string line) { - if (line.find("Error connecting to the ZeroTier") != std::string::npos ) running = false; - else running = true; + auto enableThemeMusics = std::make_shared(mWindow); + enableThemeMusics->setState(Settings::getInstance()->getBool("audio.thememusics")); + s->addWithLabel(_("PLAY SYSTEM-SPECIFIC MUSIC"), enableThemeMusics); + s->addSaveFunc([enableThemeMusics] { + if (Settings::getInstance()->setBool("audio.thememusics", enableThemeMusics->getState())) + AudioManager::getInstance()->changePlaylist(ViewController::get()->getState().getSystem()->getTheme(), true); }); - return running; -} -void GuiMenu::openQuitMenu_batocera() -{ - GuiMenu::openQuitMenu_batocera_static(mWindow); -} + auto videolowermusic = std::make_shared(mWindow); + videolowermusic->setState(Settings::getInstance()->getBool("VideoLowersMusic")); + s->addWithLabel(_("LOWER MUSIC WHEN PLAYING VIDEO"), videolowermusic); + s->addSaveFunc([videolowermusic] { Settings::getInstance()->setBool("VideoLowersMusic", videolowermusic->getState()); }); -void GuiMenu::openQuitMenu_batocera_static(Window *window, bool quickAccessMenu, bool animate) -{ - auto s = new GuiSettings(window, (quickAccessMenu ? _("QUICK ACCESS") : _("QUIT")).c_str()); - s->setCloseButton("select"); + s->addGroup(_("SOUNDS")); - if (quickAccessMenu) + // disable sounds + auto sounds_enabled = std::make_shared(mWindow); + sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds")); + s->addWithLabel(_("ENABLE NAVIGATION SOUNDS"), sounds_enabled); + s->addSaveFunc([sounds_enabled] { - s->addGroup(_("QUICK ACCESS")); - - // Don't like one of the songs? Press next - if (AudioManager::getInstance()->isSongPlaying()) + if (sounds_enabled->getState() && !Settings::getInstance()->getBool("EnableSounds") && PowerSaver::getMode() == PowerSaver::INSTANT) { - auto sname = AudioManager::getInstance()->getSongName(); - if (!sname.empty()) - { - s->addWithDescription(_("SKIP TO NEXT SONG"), _("LISTENING NOW") + " : " + sname, nullptr, [s, window] - { - Window* w = window; - AudioManager::getInstance()->playRandomMusic(false); - delete s; - openQuitMenu_batocera_static(w, true, false); - }, "iconSound"); - } + Settings::getInstance()->setPowerSaverMode("default"); + PowerSaver::init(); } + Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); + }); - s->addEntry(_("LAUNCH SCREENSAVER"), false, [s, window] - { - Window* w = window; - window->postToUiThread([w]() - { - w->startScreenSaver(); - w->renderScreenSaver(); - }); - delete s; + auto batteryWarning = std::make_shared(mWindow); + bool batteryWarningEnabled = SystemConf::getInstance()->get("system.battery.warning") == "1"; + batteryWarning->setState(batteryWarningEnabled); + s->addWithLabel(_("ENABLE AUDIBLE BATTERY WARNING"), batteryWarning); + s->addSaveFunc([batteryWarning] { + bool batteryWarningEnabled = batteryWarning->getState(); + SystemConf::getInstance()->set("system.battery.warning", batteryWarningEnabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - }, "iconScraper", true); + auto video_audio = std::make_shared(mWindow); + video_audio->setState(Settings::getInstance()->getBool("VideoAudio")); + s->addWithLabel(_("ENABLE VIDEO PREVIEW AUDIO"), video_audio); + s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); }); -#define USER_MANUAL_FILE "/usr/share/doc/user_guide.pdf" - if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::ScriptId::PDFEXTRACTION) && Utils::FileSystem::exists(USER_MANUAL_FILE)) - { - s->addEntry(_("VIEW USER MANUAL"), false, [s, window] - { - GuiImageViewer::showPdf(window, USER_MANUAL_FILE); - delete s; - }, "iconManual"); - } - } - if (quickAccessMenu) - s->addGroup(_("QUIT")); + mWindow->pushGui(s); +} - s->addEntry(_("RESTART EMULATIONSTATION"), false, [window] { - window->pushGui(new GuiMsgBox(window, _("REALLY RESTART EMULATIONSTATION?"), _("YES"), - [] { - Scripting::fireEvent("quit", "restart"); - quitES(QuitMode::QUIT); - }, _("NO"), nullptr)); - }, "iconRestart"); +void GuiMenu::openWifiSettings(Window* win, std::string title, std::string data, const std::function& onsave) +{ + win->pushGui(new GuiWifi(win, title, data, onsave)); +} - s->addEntry(_("RESTART SYSTEM"), false, [window] { - window->pushGui(new GuiMsgBox(window, _("REALLY RESTART?"), - _("YES"), [] { quitES(QuitMode::REBOOT); }, - _("NO"), nullptr)); - }, "iconRestart"); +void GuiMenu::openNetworkSettings_batocera(bool selectWifiEnable, bool selectAdhocEnable) +{ + auto theme = ThemeData::getMenuTheme(); + std::shared_ptr font = theme->Text.font; + unsigned int color = theme->Text.color; + Window *window = mWindow; - s->addEntry(_("SHUTDOWN SYSTEM"), false, [window] { - window->pushGui(new GuiMsgBox(window, _("REALLY SHUTDOWN?"), - _("YES"), [] { quitES(QuitMode::SHUTDOWN); }, - _("NO"), nullptr)); - }, "iconShutdown"); + auto s = new GuiSettings(mWindow, _("NETWORK SETTINGS").c_str()); + s->addGroup(_("INFORMATION")); - if (quickAccessMenu && animate) - s->getMenu().animateTo(Vector2f((Renderer::getScreenWidth() - s->getMenu().getSize().x()) / 2, (Renderer::getScreenHeight() - s->getMenu().getSize().y()) / 2)); - else if (quickAccessMenu) - s->getMenu().setPosition((Renderer::getScreenWidth() - s->getMenu().getSize().x()) / 2, (Renderer::getScreenHeight() - s->getMenu().getSize().y()) / 2); + auto ip = std::make_shared(mWindow, ApiSystem::getInstance()->getIpAdress(), font, color); + s->addWithLabel(_("IP ADDRESS"), ip); - window->pushGui(s); -} + auto status = std::make_shared(mWindow, ApiSystem::getInstance()->ping() ? _("CONNECTED") : _("NOT CONNECTED"), font, color); + s->addWithLabel(_("INTERNET STATUS"), status); -void GuiMenu::createDecorationItemTemplate(Window* window, std::vector sets, std::string data, ComponentListRow& row) -{ - Vector2f maxSize(Renderer::getScreenWidth() * 0.14, Renderer::getScreenHeight() * 0.14); + // Network Indicator + auto networkIndicator = std::make_shared(mWindow); + networkIndicator->setState(Settings::getInstance()->getBool("ShowNetworkIndicator")); + s->addWithLabel(_("SHOW NETWORK INDICATOR"), networkIndicator); + networkIndicator->setOnChangedCallback([networkIndicator] { Settings::getInstance()->setBool("ShowNetworkIndicator", networkIndicator->getState()); }); - int IMGPADDING = Renderer::getScreenHeight()*0.01f; + s->addGroup(_("NETWORK CONFIGURATION")); - auto theme = ThemeData::getMenuTheme(); - std::shared_ptr font = theme->Text.font; - unsigned int color = theme->Text.color; + // Hostname + s->addInputTextRow(_("HOSTNAME"), "system.hostname", false); - // spacer between icon and text - auto spacer = std::make_shared(window); - spacer->setSize(IMGPADDING, 0); - row.addElement(spacer, false); - row.addElement(std::make_shared(window, Utils::String::toUpper(Utils::String::replace(data, "_", " ")), font, color, ALIGN_LEFT), true, true); + // Wifi enable + auto enable_net = std::make_shared(mWindow); + bool networkEnabled = SystemConf::getInstance()->getBool("network.enabled"); + enable_net->setState(networkEnabled); - std::string imageUrl; + // Define enable_adhoc early so it is available to addSaveFunc. + auto enable_adhoc = std::make_shared(mWindow); - for (auto set : sets) - if (set.name == data) - imageUrl = set.imageUrl; + s->addWithLabel(_("ENABLE NETWORK"), enable_net, selectWifiEnable); - // image - if (!imageUrl.empty()) - { - auto icon = std::make_shared(window); - icon->setImage(imageUrl, false, maxSize); - icon->setMaxSize(maxSize); - icon->setColorShift(theme->Text.color); - icon->setPadding(IMGPADDING); - row.addElement(icon, false); - } -} + const std::string wifiSSID = SystemConf::getInstance()->get("wifi.ssid"); + const std::string wifiKEY = SystemConf::getInstance()->get("wifi.key"); + + s->addInputTextRow(_("WIFI SSID"), "wifi.ssid", false, false, &openWifiSettings); + s->addSaveFunc([this, enable_net, enable_adhoc, wifiSSID] { + SystemConf::getInstance()->saveSystemConf(); + const std::string wifissid = SystemConf::getInstance()->get("wifi.ssid"); + if (enable_net->getState() == true && enable_adhoc->getState() == false && wifiSSID != wifissid) + { + std::string wifikey = SystemConf::getInstance()->get("wifi.key"); + ApiSystem::getInstance()->disableWifi(); + ApiSystem::getInstance()->enableWifi(wifissid, wifikey); + } + }); + + s->addInputTextRow(_("WIFI KEY"), "wifi.key", true); + s->addSaveFunc([this, enable_net, enable_adhoc, wifiKEY] { + SystemConf::getInstance()->saveSystemConf(); + const std::string wifikey = SystemConf::getInstance()->get("wifi.key"); + if (enable_net->getState() == true && enable_adhoc->getState() == false && wifiKEY != wifikey) + { + std::string wifissid = SystemConf::getInstance()->get("wifi.ssid"); + ApiSystem::getInstance()->disableWifi(); + ApiSystem::getInstance()->enableWifi(wifissid, wifikey); + } + }); -void GuiMenu::popSystemConfigurationGui(Window* mWindow, SystemData* systemData) -{ - popSpecificConfigurationGui(mWindow, - systemData->getFullName(), - systemData->getName(), - systemData, - nullptr); -} + auto optionsAdhocID = std::make_shared >(mWindow, _("LOCAL PLAY ID"), false); + std::string selectedAdhocID = SystemConf::getInstance()->get("wifi.adhoc.id"); -void GuiMenu::popGameConfigurationGui(Window* mWindow, FileData* fileData) -{ - popSpecificConfigurationGui(mWindow, - fileData->getName(), - fileData->getConfigurationName(), - fileData->getSourceFileData()->getSystem(), - fileData); -} + auto optionsChannels = std::make_shared >(mWindow, _("LOCAL NETWORK CHANNEL"), false); -void GuiMenu::popSpecificConfigurationGui(Window* mWindow, std::string title, std::string configName, SystemData *systemData, FileData* fileData, bool selectCoreLine) -{ - // The system configuration - GuiSettings* systemConfiguration = new GuiSettings(mWindow, title.c_str()); + std::vector availableChannels = ApiSystem::getInstance()->getAvailableChannels(); + std::string selectedChannel = SystemConf::getInstance()->get("wifi.adhoc.channel"); - if (fileData != nullptr) - systemConfiguration->setSubTitle(systemData->getFullName()); + // Enable or disable ipv6 + auto ipv6_enable = std::make_shared(mWindow); + bool ipv6Enabled = SystemConf::getInstance()->get("ipv6.enabled") == "1"; + ipv6_enable->setState(ipv6Enabled); + s->addWithLabel(_("ENABLE IPV6"), ipv6_enable); + ipv6_enable->setOnChangedCallback([ipv6_enable] { + bool ipv6Enabled = ipv6_enable->getState(); + SystemConf::getInstance()->set("ipv6.enabled", ipv6Enabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + runSystemCommand("/usr/bin/toggle-ipv6", "", nullptr); + }); - std::string currentEmulator = fileData != nullptr ? fileData->getEmulator(false) : systemData->getEmulator(false); - std::string currentCore = fileData != nullptr ? fileData->getCore(false) : systemData->getCore(false); + s->addGroup(_("LOCAL NETPLAY SETTINGS")); - if (systemData->hasEmulatorSelection()) + // Adhoc mode options + bool adhocEnabled = SystemConf::getInstance()->getBool("network.adhoc.enabled"); + enable_adhoc->setState(adhocEnabled); + s->addWithLabel(_("LOCAL PLAY MODE"), enable_adhoc, selectAdhocEnable); + + if (selectedAdhocID.empty()) { - auto emulChoice = std::make_shared>(mWindow, _("Emulator"), false); - emulChoice->add(_("DEFAULT"), "", false); - for (auto& emul : systemData->getEmulators()) - { - if (emul.cores.size() == 0) - emulChoice->add(emul.name, emul.name, emul.name == currentEmulator); - else - { - for (auto& core : emul.cores) - { - bool selected = (emul.name == currentEmulator && core.name == currentCore); + selectedAdhocID = "1"; + } + optionsAdhocID->add(_("1 (HOST)"),"1", selectedAdhocID == "1"); + optionsAdhocID->add(_("2 (CLIENT 1)"),"2", selectedAdhocID == "2"); + optionsAdhocID->add(_("3 (CLIENT 2)"),"3", selectedAdhocID == "3"); + optionsAdhocID->add(_("4 (CLIENT 3)"),"4", selectedAdhocID == "4"); + s->addWithLabel(_("LOCAL PLAY ID"), optionsAdhocID); - if (emul.name == core.name) - emulChoice->add(emul.name, emul.name + "/" + core.name, selected); - else - emulChoice->add(emul.name + ": " + Utils::String::replace(core.name, "_", " "), emul.name + "/" + core.name, selected); - } - } - } + if (selectedChannel.empty()) + selectedChannel = "6"; - if (!emulChoice->hasSelection()) - emulChoice->selectFirstItem(); + bool wfound = false; + for (auto it = availableChannels.begin(); it != availableChannels.end(); it++) + { + optionsChannels->add((*it), (*it), selectedChannel == (*it)); + if (selectedChannel == (*it)) + wfound = true; + } - emulChoice->setSelectedChangedCallback([mWindow, title, systemConfiguration, systemData, fileData, configName, emulChoice](std::string s) - { - std::string newEmul; - std::string newCore; + if (!wfound) + optionsChannels->add(selectedChannel, selectedChannel, true); - auto values = Utils::String::split(emulChoice->getSelected(), '/'); - if (values.size() > 0) - newEmul = values[0]; + s->addWithLabel(_("LOCAL NETWORK CHANNEL"), optionsChannels); - if (values.size() > 1) - newCore = values[1]; + enable_adhoc->setOnChangedCallback([adhocEnabled, networkEnabled, enable_net, enable_adhoc, optionsAdhocID, selectedAdhocID, optionsChannels, selectedChannel, window] + { + SystemConf::getInstance()->set("wifi.adhoc.id", optionsAdhocID->getSelected()); + SystemConf::getInstance()->set("wifi.adhoc.channel", optionsChannels->getSelected()); - if (fileData != nullptr) - { - fileData->setEmulator(newEmul); - fileData->setCore(newCore); - } - else - { - SystemConf::getInstance()->set(configName + ".emulator", newEmul); - SystemConf::getInstance()->set(configName + ".core", newCore); - } - popSpecificConfigurationGui(mWindow, title, configName, systemData, fileData); - delete systemConfiguration; + std::string newSSID = SystemConf::getInstance()->get("wifi.ssid"); + std::string newKey = SystemConf::getInstance()->get("wifi.key"); - }); + SystemConf::getInstance()->set("global.netplay.host", "192.168.80.1"); + SystemConf::getInstance()->set("global.netplay.port", "55435"); + SystemConf::getInstance()->set("global.netplay.relay", "none"); - systemConfiguration->addWithLabel(_("Emulator"), emulChoice); - } + bool adhocenabled = enable_adhoc->getState(); + SystemConf::getInstance()->setBool("network.adhoc.enabled", adhocenabled); + SystemConf::getInstance()->saveSystemConf(); - // Screen ratio choice - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::ratio)) - { - auto ratio_choice = createRatioOptionList(mWindow, configName); - systemConfiguration->addWithLabel(_("GAME ASPECT RATIO"), ratio_choice); - systemConfiguration->addSaveFunc([configName, ratio_choice] { SystemConf::getInstance()->set(configName + ".ratio", ratio_choice->getSelected()); }); -/* if (ratio_choice->getSelected() == "custom") { - systemConfiguration->addEntry(_("WIDTH/HEIGHT"), true, [mWindow, configName] { openCustomAspectRatioConfiguration(mWindow, configName); }); + if (enable_net->getState() == true) + { + ApiSystem::getInstance()->disableWifi(); + ApiSystem::getInstance()->enableWifi(newSSID, newKey); } -*/ - auto rotation_choice = std::make_shared>(mWindow, _("SCREEN ROTATION")); - rotation_choice->addRange({{_("DEFAULT"), "default"}, {_("90"), "1"}, {_("180"), "2"}, {_("270"), "3"}}, SystemConf::getInstance()->get(configName + ".rotation")); - systemConfiguration->addWithLabel(_("SCREEN ROTATION"), rotation_choice); - systemConfiguration->addSaveFunc([configName, rotation_choice] { SystemConf::getInstance()->set(configName + ".rotation", rotation_choice->getSelected()); }); - } + }); - // video resolution mode - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::videomode)) - { - auto videoResolutionMode_choice = createVideoResolutionModeOptionList(mWindow, configName); - systemConfiguration->addWithLabel(_("VIDEO MODE"), videoResolutionMode_choice); - systemConfiguration->addSaveFunc([configName, videoResolutionMode_choice] { SystemConf::getInstance()->set(configName + ".videomode", videoResolutionMode_choice->getSelected()); }); - } + enable_net->setOnChangedCallback([enable_net, enable_adhoc, networkEnabled, adhocEnabled, window] + { + if (enable_net->getState() == true && enable_adhoc->getState() == false) + { + std::string newSSID = SystemConf::getInstance()->get("wifi.ssid"); + std::string newKey = SystemConf::getInstance()->get("wifi.key"); + ApiSystem::getInstance()->enableWifi(newSSID, newKey); + } + else + { + ApiSystem::getInstance()->disableWifi(); + } + bool networkenabled = enable_net->getState(); + SystemConf::getInstance()->setBool("network.enabled", networkenabled); + SystemConf::getInstance()->saveSystemConf(); + }); - // smoothing - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::smooth)) - { - auto smoothing_enabled = std::make_shared>(mWindow, _("BILINEAR FILTERING")); - smoothing_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".smooth")); - systemConfiguration->addWithLabel(_("BILINEAR FILTERING"), smoothing_enabled); - systemConfiguration->addSaveFunc([configName, smoothing_enabled] { SystemConf::getInstance()->set(configName + ".smooth", smoothing_enabled->getSelected()); }); - } + s->addGroup(_("NETWORK SERVICES")); - // rewind - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::rewind)) - { - auto rewind_enabled = std::make_shared>(mWindow, _("REWIND")); - rewind_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".rewind")); - systemConfiguration->addWithLabel(_("REWIND"), rewind_enabled); - systemConfiguration->addSaveFunc([configName, rewind_enabled] { SystemConf::getInstance()->set(configName + ".rewind", rewind_enabled->getSelected()); }); - } + auto sshd_enabled = std::make_shared(mWindow); + bool sshbaseEnabled = SystemConf::getInstance()->get("ssh.enabled") == "1"; + sshd_enabled->setState(sshbaseEnabled); + s->addWithLabel(_("ENABLE SSH"), sshd_enabled); + sshd_enabled->setOnChangedCallback([sshd_enabled] { + if (sshd_enabled->getState() == false) { + runSystemCommand("systemctl stop sshd", "", nullptr); + runSystemCommand("systemctl disable sshd", "", nullptr); + runSystemCommand("rm /storage/.cache/services/sshd.conf", "", nullptr); + } else { + runSystemCommand("mkdir -p /storage/.cache/services/", "", nullptr); + runSystemCommand("touch /storage/.cache/services/sshd.conf", "", nullptr); + runSystemCommand("systemctl enable sshd", "", nullptr); + runSystemCommand("systemctl start sshd", "", nullptr); + } + bool sshenabled = sshd_enabled->getState(); + SystemConf::getInstance()->set("ssh.enabled", sshenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - // autosave - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::autosave)) - { - auto autosave_enabled = std::make_shared>(mWindow, _("AUTO SAVE/LOAD ON GAME LAUNCH")); - autosave_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}, {_("SHOW SAVE STATES"), "2"}, {_("SHOW SAVE STATES IF NOT EMPTY"), "3"}}, SystemConf::getInstance()->get(configName + ".autosave")); - systemConfiguration->addWithLabel(_("AUTO SAVE/LOAD ON GAME LAUNCH"), autosave_enabled); - systemConfiguration->addSaveFunc([configName, autosave_enabled] { SystemConf::getInstance()->set(configName + ".autosave", autosave_enabled->getSelected()); }); - } + auto samba_enabled = std::make_shared(mWindow); + bool smbbaseEnabled = SystemConf::getInstance()->get("samba.enabled") == "1"; + samba_enabled->setState(smbbaseEnabled); + s->addWithLabel(_("ENABLE SAMBA"), samba_enabled); + samba_enabled->setOnChangedCallback([samba_enabled] { + if (samba_enabled->getState() == false) { + runSystemCommand("systemctl stop nmbd", "", nullptr); + runSystemCommand("systemctl stop smbd", "", nullptr); + runSystemCommand("rm /storage/.cache/services/smb.conf", "", nullptr); + } else { + runSystemCommand("mkdir -p /storage/.cache/services/", "", nullptr); + runSystemCommand("touch /storage/.cache/services/smb.conf", "", nullptr); + runSystemCommand("systemctl start nmbd", "", nullptr); + runSystemCommand("systemctl start smbd", "", nullptr); + } + bool sambaenabled = samba_enabled->getState(); + SystemConf::getInstance()->set("samba.enabled", sambaenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - // Overlays preset - if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && - systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) - { - std::string a; - auto overlays_choices = std::make_shared >(mWindow, _("OVERLAY SET"),false); - std::string currentOverlay = SystemConf::getInstance()->get(configName + ".overlayset"); - if (currentOverlay.empty()) { - currentOverlay = std::string("default"); - } + auto simple_http_enabled = std::make_shared(mWindow); + bool simplehttpEnabled = SystemConf::getInstance()->get("simplehttp.enabled") == "1"; + simple_http_enabled->setState(simplehttpEnabled); + s->addWithLabel(_("ENABLE SIMPLE HTTP SERVER"), simple_http_enabled); + simple_http_enabled->setOnChangedCallback([simple_http_enabled] { + if(simple_http_enabled->getState() == false) { + runSystemCommand("systemctl disable --now simple-http-server", "", nullptr); + } else { + runSystemCommand("systemctl enable --now simple-http-server", "", nullptr); + } + bool simplehttpenabled = simple_http_enabled->getState(); + SystemConf::getInstance()->set("simplehttp.enabled", simplehttpenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); + + auto optionsUSBGadget = std::make_shared >(mWindow, _("USB GADGET FUNCTION"), false); + std::string selectedUSBGadget = SystemConf::getInstance()->get("usbgadget.function"); + if (selectedUSBGadget.empty()) + selectedUSBGadget = "disabled"; - overlays_choices->add(_("DEFAULT"), "default", currentOverlay == "default"); - overlays_choices->add(_("NONE"), "none", currentOverlay == "none"); - for(std::stringstream ss(getShOutput(R"(/usr/bin/getoverlays)")); getline(ss, a, ','); ) - overlays_choices->add(a, a, currentOverlay == a); // emuelec - systemConfiguration->addWithLabel(_("OVERLAY SET"), overlays_choices); - systemConfiguration->addSaveFunc([overlays_choices, configName] { SystemConf::getInstance()->set(configName + ".overlayset", overlays_choices->getSelected()); }); - } - + optionsUSBGadget->add(_("DISABLED"), "disabled", selectedUSBGadget == "disabled"); + optionsUSBGadget->add(_("MTP"), "mtp", selectedUSBGadget == "mtp"); + optionsUSBGadget->add(_("ECM"), "ecm", selectedUSBGadget == "ecm"); - // Shaders preset - if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && - systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) - { - std::string a; - auto shaders_choices = std::make_shared >(mWindow, _("SHADER SET"),false); - std::string currentShader = SystemConf::getInstance()->get(configName + ".shaderset"); - if (currentShader.empty()) { - currentShader = std::string("default"); - } + s->addWithLabel(_("USB GADGET FUNCTION"), optionsUSBGadget); - shaders_choices->add(_("DEFAULT"), "default", currentShader == "default"); - shaders_choices->add(_("NONE"), "none", currentShader == "none"); - for(std::stringstream ss(getShOutput(R"(/usr/bin/getshaders)")); getline(ss, a, ','); ) - shaders_choices->add(a, a, currentShader == a); // emuelec - systemConfiguration->addWithLabel(_("SHADER SET"), shaders_choices); - systemConfiguration->addSaveFunc([shaders_choices, configName] { SystemConf::getInstance()->set(configName + ".shaderset", shaders_choices->getSelected()); }); - } + s->addSaveFunc([this, optionsUSBGadget, selectedUSBGadget] + { + if (optionsUSBGadget->changed()) { + SystemConf::getInstance()->set("usbgadget.function", optionsUSBGadget->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + runSystemCommand("/usr/bin/usbgadget stop", "", nullptr); + if (optionsUSBGadget->getSelected() == "mtp") + runSystemCommand("/usr/bin/usbgadget start mtp", "", nullptr); + else if (optionsUSBGadget->getSelected() == "ecm") { + runSystemCommand("/usr/bin/usbgadget start cdc", "", nullptr); + std::string usbip = std::string(getShOutput(R"(cat /storage/.cache/usbgadget/ip_address.conf)")); + mWindow->pushGui(new GuiMsgBox(mWindow, _("USB Networking enabled, the device IP is ") + usbip, _("OK"), nullptr)); + } + } + }); - // Filters preset - if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && - systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) - { - std::string a; - auto filters_choices = std::make_shared >(mWindow, _("FILTER SET"),false); - std::string currentFilter = SystemConf::getInstance()->get(configName + ".filterset"); - if (currentFilter.empty()) { - currentFilter = std::string("default"); - } - filters_choices->add(_("DEFAULT"), "default", currentFilter == "default"); - filters_choices->add(_("NONE"), "none", currentFilter == "none"); - for(std::stringstream ss(getShOutput(R"(/usr/bin/getfilters)")); getline(ss, a, ','); ) - filters_choices->add(a, a, currentFilter == a); // emuelec - systemConfiguration->addWithLabel(_("FILTER SET"), filters_choices); - systemConfiguration->addSaveFunc([filters_choices, configName] { SystemConf::getInstance()->set(configName + ".filterset", filters_choices->getSelected()); }); - } - // Vertical Game - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::vertical)) - { - auto vertical_enabled = std::make_shared>(mWindow, _("ENABLE VERTICAL")); - vertical_enabled->add(_("OFF"), "default", SystemConf::getInstance()->get(configName + ".vertical") != "1"); - vertical_enabled->add(_("ON"), "1", SystemConf::getInstance()->get(configName + ".vertical") == "1"); - systemConfiguration->addWithLabel(_("ENABLE VERTICAL"), vertical_enabled); - systemConfiguration->addSaveFunc([configName, vertical_enabled] { SystemConf::getInstance()->set(configName + ".vertical", vertical_enabled->getSelected()); }); + s->addGroup(_("CLOUD SERVICES")); - auto vert_aspect_enabled = std::make_shared>(mWindow, _("VERTICAL ASPECT RATIO")); - vert_aspect_enabled->addRange({ { _("16:9") , "1" }, { _("3:2") , "7" }, { _("21:9"), "4" }, { _("4:3") , "0" } }, SystemConf::getInstance()->get(configName + ".vert_aspect")); - systemConfiguration->addWithLabel(_("VERTICAL ASPECT RATIO"), vert_aspect_enabled); - systemConfiguration->addSaveFunc([configName, vert_aspect_enabled] { SystemConf::getInstance()->set(configName + ".vert_aspect", vert_aspect_enabled->getSelected()); }); - } - // Integer scale - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::pixel_perfect)) - { - auto integerscale_enabled = std::make_shared>(mWindow, _("INTEGER SCALING (PIXEL PERFECT)")); - integerscale_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".integerscale")); - systemConfiguration->addWithLabel(_("INTEGER SCALING (PIXEL PERFECT)"), integerscale_enabled); - systemConfiguration->addSaveFunc([integerscale_enabled, configName] { SystemConf::getInstance()->set(configName + ".integerscale", integerscale_enabled->getSelected()); }); - } + auto enable_syncthing = std::make_shared(mWindow); + bool syncthingEnabled = SystemConf::getInstance()->get("syncthing.enabled") == "1"; + enable_syncthing->setState(syncthingEnabled); + s->addWithLabel(_("ENABLE SYNCTHING"), enable_syncthing); + enable_syncthing->setOnChangedCallback([enable_syncthing] { + if (enable_syncthing->getState() == false) { + runSystemCommand("systemctl stop syncthing", "", nullptr); + } else { + runSystemCommand("systemctl start syncthing", "", nullptr); + } + bool syncthingenabled = enable_syncthing->getState(); + SystemConf::getInstance()->set("syncthing.enabled", syncthingenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - // Integer scale overscale - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::pixel_perfect)) - { - auto integerscaleoverscale_enabled = std::make_shared>(mWindow, _("INTEGER SCALE OVERSCALE")); - integerscaleoverscale_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".integerscaleoverscale")); - systemConfiguration->addWithLabel(_("INTEGER SCALE OVERSCALE"), integerscaleoverscale_enabled); - systemConfiguration->addSaveFunc([integerscaleoverscale_enabled, configName] { SystemConf::getInstance()->set(configName + ".integerscaleoverscale", integerscaleoverscale_enabled->getSelected()); }); + auto mount_cloud = std::make_shared(mWindow); + bool mntcloudEnabled = SystemConf::getInstance()->get("clouddrive.mounted") == "1"; + mount_cloud->setState(mntcloudEnabled); + s->addWithLabel(_("MOUNT CLOUD DRIVE"), mount_cloud); + mount_cloud->setOnChangedCallback([mount_cloud] { + if (mount_cloud->getState() == false) { + runSystemCommand("rclonectl unmount", "", nullptr); + } else { + runSystemCommand("rclonectl mount", "", nullptr); + } + bool cloudenabled = mount_cloud->getState(); + SystemConf::getInstance()->set("clouddrive.mounted", cloudenabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); + + s->addGroup(_("VPN SERVICES")); + + const std::string wireguardConfigFile = "/storage/.config/wireguard/wg0.conf"; + if (Utils::FileSystem::exists(wireguardConfigFile)) { + auto wireguard = std::make_shared(mWindow); + bool wgUp = SystemConf::getInstance()->get("wireguard.up") == "1"; + wireguard->setState(wgUp); + s->addWithLabel(_("WIREGUARD VPN"), wireguard); + wireguard->setOnChangedCallback([wireguard, wireguardConfigFile] { + if (wireguard->getState() == false) { + runSystemCommand("wg-quick down " + wireguardConfigFile, "", nullptr); + runSystemCommand("systemctl stop connman-vpn", "", nullptr); + } else { + runSystemCommand("systemctl start connman-vpn", "", nullptr); + runSystemCommand("wg-quick up " + wireguardConfigFile, "", nullptr); + } + SystemConf::getInstance()->set("wireguard.up", wireguard->getState() ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); } + auto tailscale = std::make_shared(mWindow); + bool tsUp = SystemConf::getInstance()->get("tailscale.up") == "1"; + tailscale->setState(tsUp); + s->addWithLabel(_("TAILSCALE VPN"), tailscale); + tailscale->setOnChangedCallback([tailscale] { + bool tsEnabled = tailscale->getState(); + if (tsEnabled) { + runSystemCommand("systemctl start tailscaled", "", nullptr); + runSystemCommand("tailscale up --timeout=7s", "", nullptr); + tsEnabled = IsTailscaleUp(); + } else { + runSystemCommand("tailscale down", "", nullptr); + runSystemCommand("systemctl stop tailscaled", "", nullptr); + } + SystemConf::getInstance()->set("tailscale.up", tsEnabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); -#if defined(S922X) || defined(RK3588) || defined(RK3588_ACE) || defined(RK3399) - // Core chooser - auto cores_used = std::make_shared>(mWindow, _("CORES USED")); - cores_used->addRange({ { _("ALL"), "all" },{ _("BIG") , "big" },{ _("LITTLE") , "little" } }, SystemConf::getInstance()->get(configName + ".cores")); - systemConfiguration->addWithLabel(_("CORES USED"), cores_used); - systemConfiguration->addSaveFunc([cores_used, configName] { SystemConf::getInstance()->set(configName + ".cores", cores_used->getSelected()); }); -#endif - -#if defined(AMD64) + std::string tsUrl; + if ( tsUp == true) { + if (!IsTailscaleUp(&tsUrl) && !tsUrl.empty()) { + s->addGroup("TAILSCALE REAUTHENTICATE:"); + s->addGroup(tsUrl); + } + } - // Allow offlining all but n threads - auto optionsThreads = std::make_shared >(mWindow, _("AVAILABLE THREADS"), false); + auto zerotier = std::make_shared(mWindow); + bool ztUp = SystemConf::getInstance()->get("zerotier.up") == "1"; + zerotier->setState(ztUp); + s->addWithLabel(_("ZeroTier One"), zerotier); + zerotier->setOnChangedCallback([zerotier] { + bool ztEnabled = zerotier->getState(); + if(ztEnabled) { + runSystemCommand("systemctl start zerotier-one", "", nullptr); + ztEnabled = IsZeroTierUp(); + } else { + runSystemCommand("systemctl stop zerotier-one", "", nullptr); + } + SystemConf::getInstance()->set("zerotier.up", ztEnabled ? "1" : "0"); + SystemConf::getInstance()->saveSystemConf(); + }); - std::vector availableThreads = ApiSystem::getInstance()->getAvailableThreads(); - std::string selectedThreads = SystemConf::getInstance()->get(configName + ".threads"); - if (selectedThreads.empty()) - selectedThreads = "default"; + mWindow->pushGui(s); +} - bool wfound = false; - for (auto it = availableThreads.begin(); it != availableThreads.end(); it++) - { - optionsThreads->add((*it), (*it), selectedThreads == (*it)); - if (selectedThreads == (*it)) - wfound = true; - } - if (!wfound) - optionsThreads->add(selectedThreads, selectedThreads, true); +bool GuiMenu::IsTailscaleUp(std::string* loginUrl) { + bool loggedOut = false; + ApiSystem::executeScript("tailscale status", [loginUrl, &loggedOut](std::string line) { + const std::string prompt = "Log in at: "; + if (loginUrl && line.find(prompt) == 0) + *loginUrl = line.substr(prompt.length()); - systemConfiguration->addWithLabel(_("AVAILABLE THREADS"), optionsThreads); + if (line.find("Logged out.") != std::string::npos) loggedOut = true; + }); + return !loggedOut; +} - systemConfiguration->addSaveFunc([configName, optionsThreads, selectedThreads] - { - if (optionsThreads->changed()) { - SystemConf::getInstance()->set(configName +".threads", optionsThreads->getSelected()); - runSystemCommand("/usr/bin/sh -lc \". /etc/profile.d/099-freqfunctions; onlinethreads " + optionsThreads->getSelected() + " 0" + "\"" , "", nullptr); - SystemConf::getInstance()->saveSystemConf(); - } - }); +bool GuiMenu::IsZeroTierUp(std::string* networkId) { + bool running = false; + ApiSystem::executeScript("zerotier-cli -D/storage/.config/zerotier/ info", [networkId, &running](std::string line) { + if (line.find("Error connecting to the ZeroTier") != std::string::npos ) running = false; + else running = true; + }); + return running; +} -#endif +void GuiMenu::openQuitMenu_batocera() +{ + GuiMenu::openQuitMenu_batocera_static(mWindow); +} - if (GetEnv("DEVICE_HAS_FAN") == "true") { - // Provides cooling profile switching - auto optionsFanProfile = std::make_shared >(mWindow, _("COOLING PROFILE"), false); - std::string selectedFanProfile = SystemConf::getInstance()->get(configName + ".cooling.profile"); - if (selectedFanProfile.empty()) - selectedFanProfile = "default"; +void GuiMenu::openQuitMenu_batocera_static(Window *window, bool quickAccessMenu, bool animate) +{ + auto s = new GuiSettings(window, (quickAccessMenu ? _("QUICK ACCESS") : _("QUIT")).c_str()); + s->setCloseButton("select"); - optionsFanProfile->add(_("DEFAULT"),"default", selectedFanProfile == "default"); - optionsFanProfile->add(_("AUTO"),"auto", selectedFanProfile == "auto"); - optionsFanProfile->add(_("QUIET"),"quiet", selectedFanProfile == "quiet"); - optionsFanProfile->add(_("MODERATE"),"moderate", selectedFanProfile == "moderate"); - optionsFanProfile->add(_("AGGRESSIVE"),"aggressive", selectedFanProfile == "aggressive"); - optionsFanProfile->add(_("CUSTOM"),"custom", selectedFanProfile == "custom"); + if (quickAccessMenu) + { + s->addGroup(_("QUICK ACCESS")); - systemConfiguration->addWithLabel(_("COOLING PROFILE"), optionsFanProfile); + // Don't like one of the songs? Press next + if (AudioManager::getInstance()->isSongPlaying()) + { + auto sname = AudioManager::getInstance()->getSongName(); + if (!sname.empty()) + { + s->addWithDescription(_("SKIP TO NEXT SONG"), _("LISTENING NOW") + " : " + sname, nullptr, [s, window] + { + Window* w = window; + AudioManager::getInstance()->playRandomMusic(false); + delete s; + openQuitMenu_batocera_static(w, true, false); + }, "iconSound"); + } + } - systemConfiguration->addSaveFunc([optionsFanProfile, selectedFanProfile, configName] - { - if (optionsFanProfile->changed()) { - SystemConf::getInstance()->set(configName + ".cooling.profile", optionsFanProfile->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - } - }); - } + s->addEntry(_("LAUNCH SCREENSAVER"), false, [s, window] + { + Window* w = window; + window->postToUiThread([w]() + { + w->startScreenSaver(); + w->renderScreenSaver(); + }); + delete s; -// Prep for additional device support. -#if defined(AMD64) - std::vector cpuVendor = ApiSystem::getInstance()->getCPUVendor(); - std::vector tdpRange = ApiSystem::getInstance()->getTdpRange(); - auto it = cpuVendor.begin(); + }, "iconScraper", true); - if (*it == "AuthenticAMD") { - // Provides overclock profile switching - auto optionsOCProfile = std::make_shared >(mWindow, _("CPU TDP Max"), false); - std::string selectedOCProfile = SystemConf::getInstance()->get(configName + ".overclock"); - if (selectedOCProfile.empty()) - selectedOCProfile = "default"; +#define USER_MANUAL_FILE "/usr/share/doc/user_guide.pdf" - bool xfound = false; - for (auto it = tdpRange.begin(); it != tdpRange.end(); it++) + if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::ScriptId::PDFEXTRACTION) && Utils::FileSystem::exists(USER_MANUAL_FILE)) { - optionsOCProfile->add((*it), (*it), selectedOCProfile == (*it)); - if (selectedOCProfile == (*it)) - xfound = true; + s->addEntry(_("VIEW USER MANUAL"), false, [s, window] + { + GuiImageViewer::showPdf(window, USER_MANUAL_FILE); + delete s; + }, "iconManual"); } + } + if (quickAccessMenu) + s->addGroup(_("QUIT")); - if (!xfound) - optionsOCProfile->add(selectedOCProfile, selectedOCProfile, true); + s->addEntry(_("RESTART EMULATIONSTATION"), false, [window] { + window->pushGui(new GuiMsgBox(window, _("REALLY RESTART EMULATIONSTATION?"), _("YES"), + [] { + Scripting::fireEvent("quit", "restart"); + quitES(QuitMode::QUIT); + }, _("NO"), nullptr)); + }, "iconRestart"); - systemConfiguration->addWithLabel(_("CPU TDP Max"), optionsOCProfile); + s->addEntry(_("RESTART SYSTEM"), false, [window] { + window->pushGui(new GuiMsgBox(window, _("REALLY RESTART?"), + _("YES"), [] { quitES(QuitMode::REBOOT); }, + _("NO"), nullptr)); + }, "iconRestart"); - systemConfiguration->addSaveFunc([optionsOCProfile, selectedOCProfile, configName, mWindow] - { - if (optionsOCProfile->changed()) { - mWindow->pushGui(new GuiMsgBox(mWindow, _("WARNING: OVERCLOCKING YOUR DEVICE MAY RESULT IN STABILITY PROBLEMS OR CAUSE HARDWARE DAMAGE!\n\nUSING THE QUIET COOLING PROFILE WHILE USING CERTAIN OVERCLOCKS MAY CAUSE PANIC REBOOTS!\n\nJELOS IS NOT RESPONSIBLE FOR ANY DAMAGE THAT MAY OCCUR USING THESE SETTINGS!\n\nCLICK YES THAT YOU AGREE, OR NO TO CANCEL."), _("YES"), - [optionsOCProfile,configName] { - SystemConf::getInstance()->set(configName + ".overclock", optionsOCProfile->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - }, _("NO"), nullptr)); - } - }); - } - if (Utils::FileSystem::exists("/sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference")) { - // Provides EPP Profile switching - auto optionsEPP = std::make_shared >(mWindow, _("Energy Performance Preference"), false); - std::string selectedEPP = SystemConf::getInstance()->get(configName + ".power.epp"); - if (selectedEPP.empty()) - selectedEPP = "default"; + s->addEntry(_("SHUTDOWN SYSTEM"), false, [window] { + window->pushGui(new GuiMsgBox(window, _("REALLY SHUTDOWN?"), + _("YES"), [] { quitES(QuitMode::SHUTDOWN); }, + _("NO"), nullptr)); + }, "iconShutdown"); - optionsEPP->add(_("DEFAULT"), "default", selectedEPP == "default"); + if (quickAccessMenu && animate) + s->getMenu().animateTo(Vector2f((Renderer::getScreenWidth() - s->getMenu().getSize().x()) / 2, (Renderer::getScreenHeight() - s->getMenu().getSize().y()) / 2)); + else if (quickAccessMenu) + s->getMenu().setPosition((Renderer::getScreenWidth() - s->getMenu().getSize().x()) / 2, (Renderer::getScreenHeight() - s->getMenu().getSize().y()) / 2); - optionsEPP->add(_("Performance"),"performance", selectedEPP == "performance"); - optionsEPP->add(_("Balance Performance"),"balance_performance", selectedEPP == "balance_performance"); - optionsEPP->add(_("Balance Power Saving"),"balance_power", selectedEPP == "balance_power"); - optionsEPP->add(_("Power Saving"),"power", selectedEPP == "power"); + window->pushGui(s); +} - systemConfiguration->addWithLabel(_("Energy Performance Preference"), optionsEPP); +void GuiMenu::createDecorationItemTemplate(Window* window, std::vector sets, std::string data, ComponentListRow& row) +{ + Vector2f maxSize(Renderer::getScreenWidth() * 0.14, Renderer::getScreenHeight() * 0.14); - systemConfiguration->addSaveFunc([optionsEPP, selectedEPP, configName] - { - if (optionsEPP->changed()) { - SystemConf::getInstance()->set(configName + ".power.epp", optionsEPP->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - } - }); - } + int IMGPADDING = Renderer::getScreenHeight()*0.01f; -#endif + auto theme = ThemeData::getMenuTheme(); + std::shared_ptr font = theme->Text.font; + unsigned int color = theme->Text.color; - // Per game/core/emu CPU governor - auto optionsGovernors = std::make_shared >(mWindow, _("CPU SCALING GOVERNOR"), false); + // spacer between icon and text + auto spacer = std::make_shared(window); + spacer->setSize(IMGPADDING, 0); + row.addElement(spacer, false); + row.addElement(std::make_shared(window, Utils::String::toUpper(Utils::String::replace(data, "_", " ")), font, color, ALIGN_LEFT), true, true); - std::vector availableGovernors = ApiSystem::getInstance()->getAvailableGovernors(); - std::string selectedGovernors = SystemConf::getInstance()->get(configName + ".cpugovernor"); - if (selectedGovernors.empty()) - selectedGovernors = "default"; + std::string imageUrl; - bool cfound = false; - for (auto it = availableGovernors.begin(); it != availableGovernors.end(); it++) - { - optionsGovernors->add((*it), (*it), selectedGovernors == (*it)); - if (selectedGovernors == (*it)) - cfound = true; - } - if (!cfound) - optionsGovernors->add(selectedGovernors, selectedGovernors, true); + for (auto set : sets) + if (set.name == data) + imageUrl = set.imageUrl; - systemConfiguration->addWithLabel(_("CPU SCALING GOVERNOR"), optionsGovernors); + // image + if (!imageUrl.empty()) + { + auto icon = std::make_shared(window); + icon->setImage(imageUrl, false, maxSize); + icon->setMaxSize(maxSize); + icon->setColorShift(theme->Text.color); + icon->setPadding(IMGPADDING); + row.addElement(icon, false); + } +} - systemConfiguration->addSaveFunc([configName, selectedGovernors, optionsGovernors] - { - if (optionsGovernors->changed()) { - SystemConf::getInstance()->set(configName + ".cpugovernor", optionsGovernors->getSelected()); - SystemConf::getInstance()->saveSystemConf(); - } - }); +void GuiMenu::popSystemConfigurationGui(Window* mWindow, SystemData* systemData) +{ + popSpecificConfigurationGui(mWindow, + systemData->getFullName(), + systemData->getName(), + systemData, + nullptr); +} - // GPU performance mode with enhanced power savings - auto gpuPerformance = std::make_shared >(mWindow, _("GPU PERFORMANCE PROFILE"), false); - std::string gpu_performance = SystemConf::getInstance()->get(configName + ".gpuperf"); - if (gpu_performance.empty()) - gpu_performance = "default"; +void GuiMenu::popGameConfigurationGui(Window* mWindow, FileData* fileData) +{ + popSpecificConfigurationGui(mWindow, + fileData->getName(), + fileData->getConfigurationName(), + fileData->getSourceFileData()->getSystem(), + fileData); +} - gpuPerformance->add(_("DEFAULT"), "default", gpu_performance == "default"); - gpuPerformance->add(_("Balanced"), "auto", gpu_performance == "auto"); - gpuPerformance->add(_("Battery Focus"), "low", gpu_performance == "low"); -#if defined(AMD64) - gpuPerformance->add(_("Performance Focus"), "profile_standard", gpu_performance == "profile_standard"); -#endif - gpuPerformance->add(_("Best Performance"), "profile_peak", gpu_performance == "profile_peak"); +void GuiMenu::popSpecificConfigurationGui(Window* mWindow, std::string title, std::string configName, SystemData *systemData, FileData* fileData, bool selectCoreLine) +{ + // The system configuration + GuiSettings* systemConfiguration = new GuiSettings(mWindow, title.c_str()); - systemConfiguration->addWithLabel(_("GPU PERFORMANCE PROFILE"), gpuPerformance); + if (fileData != nullptr) + systemConfiguration->setSubTitle(systemData->getFullName()); - systemConfiguration->addSaveFunc([configName, gpuPerformance, gpu_performance] + std::string currentEmulator = fileData != nullptr ? fileData->getEmulator(false) : systemData->getEmulator(false); + std::string currentCore = fileData != nullptr ? fileData->getCore(false) : systemData->getCore(false); + + if (systemData->hasEmulatorSelection()) { - if (gpuPerformance->changed()) { - SystemConf::getInstance()->set(configName + ".gpuperf", gpuPerformance->getSelected()); - SystemConf::getInstance()->saveSystemConf(); + auto emulChoice = std::make_shared>(mWindow, _("Emulator"), false); + emulChoice->add(_("DEFAULT"), "", false); + for (auto& emul : systemData->getEmulators()) + { + if (emul.cores.size() == 0) + emulChoice->add(emul.name, emul.name, emul.name == currentEmulator); + else + { + for (auto& core : emul.cores) + { + bool selected = (emul.name == currentEmulator && core.name == currentCore); + + if (emul.name == core.name) + emulChoice->add(emul.name, emul.name + "/" + core.name, selected); + else + emulChoice->add(emul.name + ": " + Utils::String::replace(core.name, "_", " "), emul.name + "/" + core.name, selected); + } + } } - }); - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::latency_reduction)) - systemConfiguration->addEntry(_("LATENCY REDUCTION"), true, [mWindow, configName] { openLatencyReductionConfiguration(mWindow, configName); }); - if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::colorization)) - { + if (!emulChoice->hasSelection()) + emulChoice->selectFirstItem(); + + emulChoice->setSelectedChangedCallback([mWindow, title, systemConfiguration, systemData, fileData, configName, emulChoice](std::string s) + { + std::string newEmul; + std::string newCore; + + auto values = Utils::String::split(emulChoice->getSelected(), '/'); + if (values.size() > 0) + newEmul = values[0]; + + if (values.size() > 1) + newCore = values[1]; - std::string currentEmulator = fileData != nullptr ? fileData->getEmulator(false) : systemData->getEmulator(false); - LOG(LogError) << currentEmulator; + if (fileData != nullptr) + { + fileData->setEmulator(newEmul); + fileData->setCore(newCore); + } + else + { + SystemConf::getInstance()->set(configName + ".emulator", newEmul); + SystemConf::getInstance()->set(configName + ".core", newCore); + } + popSpecificConfigurationGui(mWindow, title, configName, systemData, fileData); + delete systemConfiguration; + }); - // gameboy colorize - auto colorizations_choices = std::make_shared >(mWindow, _("COLORIZATION"), false); - auto twb1_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 1 PALETTE"), false); - auto twb2_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 2 PALETTE"), false); - auto twb3_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 3 PALETTE"), false); - auto pixelshift1_colorizations_choices = std::make_shared >(mWindow, _("PIXELSHIFT - PACK 1 PALETTE"), false); + systemConfiguration->addWithLabel(_("Emulator"), emulChoice); + } - std::string currentColorization = SystemConf::getInstance()->get(configName + ".renderer.colorization"); - std::string twb1_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb1_colorization"); - std::string twb2_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb2_colorization"); - std::string twb3_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb3_colorization"); - std::string pixelshift1_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.pixelshift1_colorization"); + // Screen ratio choice + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::ratio)) + { + auto ratio_choice = createRatioOptionList(mWindow, configName); + systemConfiguration->addWithLabel(_("GAME ASPECT RATIO"), ratio_choice); + systemConfiguration->addSaveFunc([configName, ratio_choice] { SystemConf::getInstance()->set(configName + ".ratio", ratio_choice->getSelected()); }); +/* if (ratio_choice->getSelected() == "custom") { + systemConfiguration->addEntry(_("WIDTH/HEIGHT"), true, [mWindow, configName] { openCustomAspectRatioConfiguration(mWindow, configName); }); + } +*/ + auto rotation_choice = std::make_shared>(mWindow, _("SCREEN ROTATION")); + rotation_choice->addRange({{_("DEFAULT"), "default"}, {_("90"), "1"}, {_("180"), "2"}, {_("270"), "3"}}, SystemConf::getInstance()->get(configName + ".rotation")); + systemConfiguration->addWithLabel(_("SCREEN ROTATION"), rotation_choice); + systemConfiguration->addSaveFunc([configName, rotation_choice] { SystemConf::getInstance()->set(configName + ".rotation", rotation_choice->getSelected()); }); + } + // video resolution mode + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::videomode)) + { + auto videoResolutionMode_choice = createVideoResolutionModeOptionList(mWindow, configName); + systemConfiguration->addWithLabel(_("VIDEO MODE"), videoResolutionMode_choice); + systemConfiguration->addSaveFunc([configName, videoResolutionMode_choice] { SystemConf::getInstance()->set(configName + ".videomode", videoResolutionMode_choice->getSelected()); }); + } + // smoothing + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::smooth)) + { + auto smoothing_enabled = std::make_shared>(mWindow, _("BILINEAR FILTERING")); + smoothing_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".smooth")); + systemConfiguration->addWithLabel(_("BILINEAR FILTERING"), smoothing_enabled); + systemConfiguration->addSaveFunc([configName, smoothing_enabled] { SystemConf::getInstance()->set(configName + ".smooth", smoothing_enabled->getSelected()); }); + } + // rewind + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::rewind)) + { + auto rewind_enabled = std::make_shared>(mWindow, _("REWIND")); + rewind_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".rewind")); + systemConfiguration->addWithLabel(_("REWIND"), rewind_enabled); + systemConfiguration->addSaveFunc([configName, rewind_enabled] { SystemConf::getInstance()->set(configName + ".rewind", rewind_enabled->getSelected()); }); + } - if (currentColorization.empty()) - currentColorization = std::string("default"); - if (twb1_currentColorization.empty()) - twb1_currentColorization = std::string("TWB64 001 - Aqours Blue"); - if (twb2_currentColorization.empty()) - twb2_currentColorization = std::string("TWB64 101 - 765PRO Pink"); - if (twb3_currentColorization.empty()) - twb3_currentColorization = std::string("TWB64 201 - DMG-GOLD"); - if (pixelshift1_currentColorization.empty()) - pixelshift1_currentColorization = std::string("PixelShift 01 - Arctic Green"); + // autosave + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::autosave)) + { + auto autosave_enabled = std::make_shared>(mWindow, _("AUTO SAVE/LOAD ON GAME LAUNCH")); + autosave_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}, {_("SHOW SAVE STATES"), "2"}, {_("SHOW SAVE STATES IF NOT EMPTY"), "3"}}, SystemConf::getInstance()->get(configName + ".autosave")); + systemConfiguration->addWithLabel(_("AUTO SAVE/LOAD ON GAME LAUNCH"), autosave_enabled); + systemConfiguration->addSaveFunc([configName, autosave_enabled] { SystemConf::getInstance()->set(configName + ".autosave", autosave_enabled->getSelected()); }); + } - colorizations_choices->add(_("DEFAULT"), "default", currentColorization == "default"); - colorizations_choices->add(_("NONE"), "none", currentColorization == "none"); - colorizations_choices->add(_("GBC"), "GBC", currentColorization == "GBC"); - colorizations_choices->add(_("SGB"), "SGB", currentColorization == "SGB"); - colorizations_choices->add(_("Best Guess"), "Best Guess", currentColorization == "Best Guess"); + // Overlays preset + if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && + systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) + { + std::string a; + auto overlays_choices = std::make_shared >(mWindow, _("OVERLAY SET"),false); + std::string currentOverlay = SystemConf::getInstance()->get(configName + ".overlayset"); + if (currentOverlay.empty()) { + currentOverlay = std::string("default"); + } - const char* all_gambate_gc_colors_modes[] = { "GB - DMG", - "GB - Light", - "GB - Pocket", - "GBC - Blue", - "GBC - Brown", - "GBC - Dark Blue", - "GBC - Dark Brown", - "GBC - Dark Green", - "GBC - Grayscale", - "GBC - Green", - "GBC - Inverted", - "GBC - Orange", - "GBC - Pastel Mix", - "GBC - Red", - "GBC - Yellow", - "SGB - 1A", - "SGB - 1B", - "SGB - 1C", - "SGB - 1D", - "SGB - 1E", - "SGB - 1F", - "SGB - 1G", - "SGB - 1H", - "SGB - 2A", - "SGB - 2B", - "SGB - 2C", - "SGB - 2D", - "SGB - 2E", - "SGB - 2F", - "SGB - 2G", - "SGB - 2H", - "SGB - 3A", - "SGB - 3B", - "SGB - 3C", - "SGB - 3D", - "SGB - 3E", - "SGB - 3F", - "SGB - 3G", - "SGB - 3H", - "SGB - 4A", - "SGB - 4B", - "SGB - 4C", - "SGB - 4D", - "SGB - 4E", - "SGB - 4F", - "SGB - 4G", - "SGB - 4H", - "Special 1", - "Special 2", - "Special 3", - "Special 4 (TI-83 Legacy)", - "TWB64 - Pack 1", - "TWB64 - Pack 2", - "TWB64 - Pack 3", - "PixelShift - Pack 1"}; + overlays_choices->add(_("DEFAULT"), "default", currentOverlay == "default"); + overlays_choices->add(_("NONE"), "none", currentOverlay == "none"); + for(std::stringstream ss(getShOutput(R"(/usr/bin/getoverlays)")); getline(ss, a, ','); ) + overlays_choices->add(a, a, currentOverlay == a); // emuelec + systemConfiguration->addWithLabel(_("OVERLAY SET"), overlays_choices); + systemConfiguration->addSaveFunc([overlays_choices, configName] { SystemConf::getInstance()->set(configName + ".overlayset", overlays_choices->getSelected()); }); + } + - const char* twb1_colors_modes[] = { - "TWB64 001 - Aqours Blue", - "TWB64 002 - Anime Expo Ver.", - "TWB64 003 - SpongeBob Yellow", - "TWB64 004 - Patrick Star Pink", - "TWB64 005 - Neon Red", - "TWB64 006 - Neon Blue", - "TWB64 007 - Neon Yellow", - "TWB64 008 - Neon Green", - "TWB64 009 - Neon Pink", - "TWB64 010 - Mario Red", - "TWB64 011 - Nick Orange", - "TWB64 012 - Virtual Vision", - "TWB64 013 - Golden Wild", - "TWB64 014 - Builder Yellow", - "TWB64 015 - Classic Blurple", - "TWB64 016 - 765 Production Ver.", - "TWB64 017 - Superball Ivory", - "TWB64 018 - Crunchyroll Orange", - "TWB64 019 - Muse Pink", - "TWB64 020 - Nijigasaki Yellow", - "TWB64 021 - Gamate Ver.", - "TWB64 022 - Greenscale Ver.", - "TWB64 023 - Odyssey Gold", - "TWB64 024 - Super Saiyan God", - "TWB64 025 - Super Saiyan Blue", - "TWB64 026 - Bizarre Pink", - "TWB64 027 - Nintendo Switch Lite Ver.", - "TWB64 028 - Game.com Ver.", - "TWB64 029 - Sanrio Pink", - "TWB64 030 - BANDAI NAMCO Ver.", - "TWB64 031 - Cosmo Green", - "TWB64 032 - Wanda Pink", - "TWB64 033 - Link's Awakening DX Ver.", - "TWB64 034 - Travel Wood", - "TWB64 035 - Pokemon Ver.", - "TWB64 036 - Game Grump Orange", - "TWB64 037 - Scooby-Doo Mystery Ver.", - "TWB64 038 - Pokemon mini Ver.", - "TWB64 039 - Supervision Ver.", - "TWB64 040 - DMG Ver.", - "TWB64 041 - Pocket Ver.", - "TWB64 042 - Light Ver.", - "TWB64 043 - Miraitowa Blue", - "TWB64 044 - Someity Pink", - "TWB64 045 - Pikachu Yellow", - "TWB64 046 - Eevee Brown", - "TWB64 047 - Microvision Ver.", - "TWB64 048 - TI-83 Ver.", - "TWB64 049 - Aegis Cherry", - "TWB64 050 - Labo Fawn", - "TWB64 051 - MILLION LIVE GOLD!", - "TWB64 052 - Tokyo Midtown Ver.", - "TWB64 053 - VMU Ver.", - "TWB64 054 - Game Master Ver.", - "TWB64 055 - Android Green", - "TWB64 056 - Walmart Discount Blue", - "TWB64 057 - Google Red", - "TWB64 058 - Google Blue", - "TWB64 059 - Google Yellow", - "TWB64 060 - Google Green", - "TWB64 061 - WonderSwan Ver.", - "TWB64 062 - Neo Geo Pocket Ver.", - "TWB64 063 - Dew Green", - "TWB64 064 - Coca-Cola Red", - "TWB64 065 - GameKing Ver.", - "TWB64 066 - Do The Dew Ver.", - "TWB64 067 - Digivice Ver.", - "TWB64 068 - Bikini Bottom Ver.", - "TWB64 069 - Blossom Pink", - "TWB64 070 - Bubbles Blue", - "TWB64 071 - Buttercup Green", - "TWB64 072 - NASCAR Ver.", - "TWB64 073 - Lemon-Lime Green", - "TWB64 074 - Mega Man V Ver.", - "TWB64 075 - Tamagotchi Ver.", - "TWB64 076 - Phantom Red", - "TWB64 077 - Halloween Ver.", - "TWB64 078 - Christmas Ver.", - "TWB64 079 - Cardcaptor Pink", - "TWB64 080 - Pretty Guardian Gold", - "TWB64 081 - Camouflage Ver.", - "TWB64 082 - Legendary Super Saiyan", - "TWB64 083 - Super Saiyan Rose", - "TWB64 084 - Super Saiyan", - "TWB64 085 - Perfected Ultra Instinct", - "TWB64 086 - Saint Snow Red", - "TWB64 087 - Yellow Banana", - "TWB64 088 - Green Banana", - "TWB64 089 - Super Saiyan 3", - "TWB64 090 - Super Saiyan Blue Evolved", - "TWB64 091 - Pocket Tales Ver.", - "TWB64 092 - Investigation Yellow", - "TWB64 093 - S.E.E.S. Blue", - "TWB64 094 - Game Awards Cyan", - "TWB64 095 - Hokage Orange", - "TWB64 096 - Straw Hat Red", - "TWB64 097 - Sword Art Cyan", - "TWB64 098 - Deku Alpha Emerald", - "TWB64 099 - Blue Stripes Ver.", - "TWB64 100 - Stone Orange"}; + // Shaders preset + if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && + systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) + { + std::string a; + auto shaders_choices = std::make_shared >(mWindow, _("SHADER SET"),false); + std::string currentShader = SystemConf::getInstance()->get(configName + ".shaderset"); + if (currentShader.empty()) { + currentShader = std::string("default"); + } - const char* twb2_colors_modes[] = { - "TWB64 101 - 765PRO Pink", - "TWB64 102 - CINDERELLA Blue", - "TWB64 103 - MILLION Yellow!", - "TWB64 104 - SideM Green", - "TWB64 105 - SHINY Sky Blue", - "TWB64 106 - Angry Volcano Ver.", - "TWB64 107 - Yo-kai Pink", - "TWB64 108 - Yo-kai Green", - "TWB64 109 - Yo-kai Blue", - "TWB64 110 - Yo-kai Purple", - "TWB64 111 - Aquatic Iro", - "TWB64 112 - Tea Midori", - "TWB64 113 - Sakura Pink", - "TWB64 114 - Wisteria Murasaki", - "TWB64 115 - Oni Aka", - "TWB64 116 - Golden Kiiro", - "TWB64 117 - Silver Shiro", - "TWB64 118 - Fruity Orange", - "TWB64 119 - AKB48 Pink", - "TWB64 120 - Miku Blue", - "TWB64 121 - Fairy Tail Red", - "TWB64 122 - Survey Corps Brown", - "TWB64 123 - Island Green", - "TWB64 124 - Mania Plus Green", - "TWB64 125 - Ninja Turtle Green", - "TWB64 126 - Slime Blue", - "TWB64 127 - Lime Midori", - "TWB64 128 - Ghostly Aoi", - "TWB64 129 - Retro Bogeda", - "TWB64 130 - Royal Blue", - "TWB64 131 - Neon Purple", - "TWB64 132 - Neon Orange", - "TWB64 133 - Moonlight Vision", - "TWB64 134 - Tokyo Red", - "TWB64 135 - Paris Gold", - "TWB64 136 - Beijing Blue", - "TWB64 137 - Pac-Man Yellow", - "TWB64 138 - Irish Green", - "TWB64 139 - Kakarot Orange", - "TWB64 140 - Dragon Ball Orange", - "TWB64 141 - Christmas Gold", - "TWB64 142 - Pepsi Vision", - "TWB64 143 - Bubblun Green", - "TWB64 144 - Bobblun Blue", - "TWB64 145 - Baja Blast Storm", - "TWB64 146 - Olympic Gold", - "TWB64 147 - Value Orange", - "TWB64 148 - Liella Purple!", - "TWB64 149 - Olympic Silver", - "TWB64 150 - Olympic Bronze", - "TWB64 151 - ANA Sky Blue", - "TWB64 152 - Nijigasaki Orange", - "TWB64 153 - holoblue", - "TWB64 154 - Wrestling Red", - "TWB64 155 - Yoshi Egg Green", - "TWB64 156 - Pokedex Red", - "TWB64 157 - Disney Dream Blue", - "TWB64 158 - Xbox Green", - "TWB64 159 - Sonic Mega Blue", - "TWB64 160 - Sprite Green", - "TWB64 161 - Scarlett Green", - "TWB64 162 - Glitchy Blue", - "TWB64 163 - Classic LCD", - "TWB64 164 - 3DS Virtual Console Ver.", - "TWB64 165 - PocketStation Ver.", - "TWB64 166 - Timeless Gold and Red", - "TWB64 167 - Smurfy Blue", - "TWB64 168 - Swampy Ogre Green", - "TWB64 169 - Sailor Spinach Green", - "TWB64 170 - Shenron Green", - "TWB64 171 - Berserk Blood", - "TWB64 172 - Super Star Pink", - "TWB64 173 - Gamebuino Classic Ver.", - "TWB64 174 - Barbie Pink", - "TWB64 175 - Star Command Green", - "TWB64 176 - Nokia 3310 Ver.", - "TWB64 177 - Clover Green", - "TWB64 178 - Crash Orange", - "TWB64 179 - Famicom Disk Yellow", - "TWB64 180 - Team Rocket Red", - "TWB64 181 - SEIKO Timer Yellow", - "TWB64 182 - PINK109", - "TWB64 183 - Doraemon Tricolor", - "TWB64 184 - Fury Blue", - "TWB64 185 - Rockstar Orange", - "TWB64 186 - Puyo Puyo Green", - "TWB64 187 - Susan G. Pink", - "TWB64 188 - Pizza Hut Red", - "TWB64 189 - Plumbob Green", - "TWB64 190 - Grand Ivory", - "TWB64 191 - Demon's Gold", - "TWB64 192 - SEGA Tokyo Blue", - "TWB64 193 - Champion's Tunic", - "TWB64 194 - DK Barrel Brown", - "TWB64 195 - EVA-01", - "TWB64 196 - Equestrian Purple", - "TWB64 197 - Autobot Red", - "TWB64 198 - niconico sea green", - "TWB64 199 - Duracell Copper", - "TWB64 200 - TOKYO SKYTREE CLOUDY BLUE"}; + shaders_choices->add(_("DEFAULT"), "default", currentShader == "default"); + shaders_choices->add(_("NONE"), "none", currentShader == "none"); + for(std::stringstream ss(getShOutput(R"(/usr/bin/getshaders)")); getline(ss, a, ','); ) + shaders_choices->add(a, a, currentShader == a); // emuelec + systemConfiguration->addWithLabel(_("SHADER SET"), shaders_choices); + systemConfiguration->addSaveFunc([shaders_choices, configName] { SystemConf::getInstance()->set(configName + ".shaderset", shaders_choices->getSelected()); }); + } - const char* twb3_colors_modes[] = { - "TWB64 201 - DMG-GOLD", - "TWB64 202 - LCD Clock Green", - "TWB64 203 - Famicom Frenzy", - "TWB64 204 - DK Arcade Blue", - "TWB64 205 - Advanced Indigo", - "TWB64 206 - Ultra Black", - "TWB64 207 - Chaos Emerald Green", - "TWB64 208 - Blue Bomber Azure", - "TWB64 209 - Garry's Blue", - "TWB64 210 - Steam Gray", - "TWB64 211 - Dream Land GB Ver.", - "TWB64 212 - Pokemon Pinball Ver.", - "TWB64 213 - Poketch Ver.", - "TWB64 214 - COLLECTION of SaGa Ver.", - "TWB64 215 - Rocky-Valley Holiday", - "TWB64 216 - Giga Kiwi DMG", - "TWB64 217 - DMG Pea Green", - "TWB64 218 - Timing Hero Ver.", - "TWB64 219 - Invincible Blue", - "TWB64 220 - Grinchy Green", - "TWB64 221 - Winter Icy Blue", - "TWB64 222 - School Idol Mix", - "TWB64 223 - Green Awakening", - "TWB64 224 - Goomba Brown", - "TWB64 225 - Devil Red", - "TWB64 226 - Simpson Yellow", - "TWB64 227 - Spooky Purple", - "TWB64 228 - Treasure Gold", - "TWB64 229 - Cherry Blossom Pink", - "TWB64 230 - Golden Trophy", - "TWB64 231 - Winter Icy Blue", - "TWB64 232 - Leprechaun Green", - "TWB64 233 - SAITAMA SUPER BLUE", - "TWB64 234 - SAITAMA SUPER GREEN", - "TWB64 235 - Duolingo Green", - "TWB64 236 - Super Mushroom Vision", - "TWB64 237 - Ancient Hisuian Brown", - "TWB64 238 - Sky Pop Ivory", - "TWB64 239 - LAWSON BLUE", - "TWB64 240 - Anime Expo Red", - "TWB64 241 - Brilliant Diamond Blue", - "TWB64 242 - Shining Pearl Pink", - "TWB64 243 - Funimation Melon", - "TWB64 244 - Teyvat Brown", - "TWB64 245 - Chozo Blue", - "TWB64 246 - Spotify Green", - "TWB64 247 - Dr Pepper Red", - "TWB64 248 - NHK Silver Gray", - "TWB64 249 - Starbucks Green", - "TWB64 250 - Tokyo Disney Magic", - "TWB64 251 - Kingdom Key Gold", - "TWB64 252 - Hogwarts Goldius", - "TWB64 253 - Kentucky Fried Red", - "TWB64 254 - Cheeto Orange", - "TWB64 255 - Namco Idol Pink", - "TWB64 256 - Domino's Blue", - "TWB64 257 - Pac-Man Vision", - "TWB64 258 - Bill's PC Screen", - "TWB64 259 - Sonic Mega Blue", - "TWB64 260 - Fool's Gold and Silver", - "TWB64 261 - UTA RED", - "TWB64 262 - Metallic Paldea Brass", - "TWB64 263 - Classy Christmas", - "TWB64 264 - Winter Christmas", - "TWB64 265 - IDOL WORLD TRICOLOR!!!", - "TWB64 266 - Inkling Tricolor", - "TWB64 267 - 7-Eleven Color Combo", - "TWB64 268 - PAC-PALETTE", - "TWB64 269 - Vulnerable Blue", - "TWB64 270 - Nightvision Green", - "TWB64 271 - Bandai Namco Tricolor", - "TWB64 272 - Gold, Silver, and Bronze", - "TWB64 273 - Arendelle Winter Blue", - "TWB64 274 - Super Famicom Supreme", - "TWB64 275 - Absorbent and Yellow", - "TWB64 276 - 765PRO TRICOLOR", - "TWB64 277 - GameCube Glimmer", - "TWB64 278 - 1st Vision Pastel", - "TWB64 279 - Perfect Majin Emperor", - "TWB64 280 - J-Pop Idol Sherbet", - "TWB64 281 - Ryuuguu Sunset", - "TWB64 282 - Tropical Starfall", - "TWB64 283 - Colorful Horizons", - "TWB64 284 - BLACKPINK BLINK PINK", - "TWB64 285 - DMG-SWITCH", - "TWB64 286 - POCKET SWITCH", - "TWB64 287 - Sunny Passion Paradise", - "TWB64 288 - Saiyan Beast Silver", - "TWB64 289 - RADIANT SMILE RAMP", - "TWB64 290 - A-RISE BLUE", - "TWB64 291 - TROPICAL TWICE APRICOT", - "TWB64 292 - Odyssey Boy", - "TWB64 293 - Frog Coin Green", - "TWB64 294 - Garfield Vision", - "TWB64 295 - Bedrock Caveman Vision", - "TWB64 296 - BANGTAN ARMY PURPLE", - "TWB64 297 - Spider-Verse Red", - "TWB64 298 - Baja Blast Beach", - "TWB64 299 - 3DS Virtual Console Green", - "TWB64 300 - Wonder Purple"}; + // Filters preset + if (ApiSystem::getInstance()->isScriptingSupported(ApiSystem::SHADERS) && + systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::shaders)) + { + std::string a; + auto filters_choices = std::make_shared >(mWindow, _("FILTER SET"),false); + std::string currentFilter = SystemConf::getInstance()->get(configName + ".filterset"); + if (currentFilter.empty()) { + currentFilter = std::string("default"); + } + + filters_choices->add(_("DEFAULT"), "default", currentFilter == "default"); + filters_choices->add(_("NONE"), "none", currentFilter == "none"); + for(std::stringstream ss(getShOutput(R"(/usr/bin/getfilters)")); getline(ss, a, ','); ) + filters_choices->add(a, a, currentFilter == a); // emuelec + systemConfiguration->addWithLabel(_("FILTER SET"), filters_choices); + systemConfiguration->addSaveFunc([filters_choices, configName] { SystemConf::getInstance()->set(configName + ".filterset", filters_choices->getSelected()); }); + } + + // Vertical Game + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::vertical)) + { + auto vertical_enabled = std::make_shared>(mWindow, _("ENABLE VERTICAL")); + vertical_enabled->add(_("OFF"), "default", SystemConf::getInstance()->get(configName + ".vertical") != "1"); + vertical_enabled->add(_("ON"), "1", SystemConf::getInstance()->get(configName + ".vertical") == "1"); + systemConfiguration->addWithLabel(_("ENABLE VERTICAL"), vertical_enabled); + systemConfiguration->addSaveFunc([configName, vertical_enabled] { SystemConf::getInstance()->set(configName + ".vertical", vertical_enabled->getSelected()); }); + + auto vert_aspect_enabled = std::make_shared>(mWindow, _("VERTICAL ASPECT RATIO")); + vert_aspect_enabled->addRange({ { _("16:9") , "1" }, { _("3:2") , "7" }, { _("21:9"), "4" }, { _("4:3") , "0" } }, SystemConf::getInstance()->get(configName + ".vert_aspect")); + systemConfiguration->addWithLabel(_("VERTICAL ASPECT RATIO"), vert_aspect_enabled); + systemConfiguration->addSaveFunc([configName, vert_aspect_enabled] { SystemConf::getInstance()->set(configName + ".vert_aspect", vert_aspect_enabled->getSelected()); }); + } + // Integer scale + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::pixel_perfect)) + { + auto integerscale_enabled = std::make_shared>(mWindow, _("INTEGER SCALING (PIXEL PERFECT)")); + integerscale_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".integerscale")); + systemConfiguration->addWithLabel(_("INTEGER SCALING (PIXEL PERFECT)"), integerscale_enabled); + systemConfiguration->addSaveFunc([integerscale_enabled, configName] { SystemConf::getInstance()->set(configName + ".integerscale", integerscale_enabled->getSelected()); }); + } - const char* pixelshift1_colors_modes[] = { - "PixelShift 01 - Arctic Green", - "PixelShift 02 - Arduboy", - "PixelShift 03 - BGB 0.3 Emulator", - "PixelShift 04 - Camouflage", - "PixelShift 05 - Chocolate Bar", - "PixelShift 06 - CMYK", - "PixelShift 07 - Cotton Candy", - "PixelShift 08 - Easy Greens", - "PixelShift 09 - Gamate", - "PixelShift 10 - Game Boy Light", - "PixelShift 11 - Game Boy Pocket", - "PixelShift 12 - Game Boy Pocket Alt", - "PixelShift 13 - Game Pocket Computer", - "PixelShift 14 - Game & Watch Ball", - "PixelShift 15 - GB Backlight Blue", - "PixelShift 16 - GB Backlight Faded", - "PixelShift 17 - GB Backlight Orange", - "PixelShift 18 - GB Backlight White ", - "PixelShift 19 - GB Backlight Yellow Dark", - "PixelShift 20 - GB Bootleg", - "PixelShift 21 - GB Hunter", - "PixelShift 22 - GB Kiosk", - "PixelShift 23 - GB Kiosk 2", - "PixelShift 24 - GB New", - "PixelShift 25 - GB Nuked", - "PixelShift 26 - GB Old", - "PixelShift 27 - GBP Bivert", - "PixelShift 28 - GB Washed Yellow Backlight", - "PixelShift 29 - Ghost", - "PixelShift 30 - Glow In The Dark", - "PixelShift 31 - Gold Bar", - "PixelShift 32 - Grapefruit", - "PixelShift 33 - Gray Green Mix", - "PixelShift 34 - Missingno", - "PixelShift 35 - MS-Dos", - "PixelShift 36 - Newspaper", - "PixelShift 37 - Pip-Boy", - "PixelShift 38 - Pocket Girl", - "PixelShift 39 - Silhouette", - "PixelShift 40 - Sunburst", - "PixelShift 41 - Technicolor", - "PixelShift 42 - Tron", - "PixelShift 43 - Vaporwave", - "PixelShift 44 - Virtual Boy", - "PixelShift 45 - Wish"}; + // Integer scale overscale + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::pixel_perfect)) + { + auto integerscaleoverscale_enabled = std::make_shared>(mWindow, _("INTEGER SCALE OVERSCALE")); + integerscaleoverscale_enabled->addRange({{_("DEFAULT"), "default"}, {_("ON"), "1"}, {_("OFF"), "0"}}, SystemConf::getInstance()->get(configName + ".integerscaleoverscale")); + systemConfiguration->addWithLabel(_("INTEGER SCALE OVERSCALE"), integerscaleoverscale_enabled); + systemConfiguration->addSaveFunc([integerscaleoverscale_enabled, configName] { SystemConf::getInstance()->set(configName + ".integerscaleoverscale", integerscaleoverscale_enabled->getSelected()); }); + } + + +#if defined(S922X) || defined(RK3588) || defined(RK3588_ACE) || defined(RK3399) + // Core chooser + auto cores_used = std::make_shared>(mWindow, _("CORES USED")); + cores_used->addRange({ { _("ALL"), "all" },{ _("BIG") , "big" },{ _("LITTLE") , "little" } }, SystemConf::getInstance()->get(configName + ".cores")); + systemConfiguration->addWithLabel(_("CORES USED"), cores_used); + systemConfiguration->addSaveFunc([cores_used, configName] { SystemConf::getInstance()->set(configName + ".cores", cores_used->getSelected()); }); +#endif + +#if defined(AMD64) + // Allow offlining all but n threads + auto optionsThreads = std::make_shared >(mWindow, _("AVAILABLE THREADS"), false); + std::vector availableThreads = ApiSystem::getInstance()->getAvailableThreads(); + std::string selectedThreads = SystemConf::getInstance()->get(configName + ".threads"); + if (selectedThreads.empty()) + selectedThreads = "default"; - int n_all_gambate_gc_colors_modes = 55; - int n_twb1_colors_modes = 100; - int n_twb2_colors_modes = 100; - int n_twb3_colors_modes = 100; - int n_pixelshift1_colors_modes = 45; + bool wfound = false; + for (auto it = availableThreads.begin(); it != availableThreads.end(); it++) + { + optionsThreads->add((*it), (*it), selectedThreads == (*it)); + if (selectedThreads == (*it)) + wfound = true; + } + if (!wfound) + optionsThreads->add(selectedThreads, selectedThreads, true); - for (int i = 0; i < n_all_gambate_gc_colors_modes; i++) - colorizations_choices->add(all_gambate_gc_colors_modes[i], all_gambate_gc_colors_modes[i], currentColorization == std::string(all_gambate_gc_colors_modes[i])); - - for (int i = 0; i < n_twb1_colors_modes; i++) - twb1_colorizations_choices->add(twb1_colors_modes[i], twb1_colors_modes[i], twb1_currentColorization == std::string(twb1_colors_modes[i])); - - for (int i = 0; i < n_twb2_colors_modes; i++) - twb2_colorizations_choices->add(twb2_colors_modes[i], twb2_colors_modes[i], twb2_currentColorization == std::string(twb2_colors_modes[i])); + systemConfiguration->addWithLabel(_("AVAILABLE THREADS"), optionsThreads); - for (int i = 0; i < n_twb3_colors_modes; i++) - twb3_colorizations_choices->add(twb3_colors_modes[i], twb3_colors_modes[i], twb3_currentColorization == std::string(twb3_colors_modes[i])); - - for (int i = 0; i < n_pixelshift1_colors_modes; i++) - pixelshift1_colorizations_choices->add(pixelshift1_colors_modes[i], pixelshift1_colors_modes[i], pixelshift1_currentColorization == std::string(pixelshift1_colors_modes[i])); + systemConfiguration->addSaveFunc([configName, optionsThreads, selectedThreads] + { + if (optionsThreads->changed()) { + SystemConf::getInstance()->set(configName +".threads", optionsThreads->getSelected()); + runSystemCommand("/usr/bin/sh -lc \". /etc/profile.d/099-freqfunctions; onlinethreads " + optionsThreads->getSelected() + " 0" + "\"" , "", nullptr); + SystemConf::getInstance()->saveSystemConf(); + } + }); + +#endif + + if (GetEnv("DEVICE_HAS_FAN") == "true") { + // Provides cooling profile switching + auto optionsFanProfile = std::make_shared >(mWindow, _("COOLING PROFILE"), false); + std::string selectedFanProfile = SystemConf::getInstance()->get(configName + ".cooling.profile"); + if (selectedFanProfile.empty()) + selectedFanProfile = "default"; + + optionsFanProfile->add(_("DEFAULT"),"default", selectedFanProfile == "default"); + optionsFanProfile->add(_("AUTO"),"auto", selectedFanProfile == "auto"); + optionsFanProfile->add(_("QUIET"),"quiet", selectedFanProfile == "quiet"); + optionsFanProfile->add(_("MODERATE"),"moderate", selectedFanProfile == "moderate"); + optionsFanProfile->add(_("AGGRESSIVE"),"aggressive", selectedFanProfile == "aggressive"); + optionsFanProfile->add(_("CUSTOM"),"custom", selectedFanProfile == "custom"); + + systemConfiguration->addWithLabel(_("COOLING PROFILE"), optionsFanProfile); + + systemConfiguration->addSaveFunc([optionsFanProfile, selectedFanProfile, configName] + { + if (optionsFanProfile->changed()) { + SystemConf::getInstance()->set(configName + ".cooling.profile", optionsFanProfile->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + } + }); + } + +// Prep for additional device support. +#if defined(AMD64) + std::vector cpuVendor = ApiSystem::getInstance()->getCPUVendor(); + std::vector tdpRange = ApiSystem::getInstance()->getTdpRange(); + auto it = cpuVendor.begin(); + + if (*it == "AuthenticAMD") { + // Provides overclock profile switching + auto optionsOCProfile = std::make_shared >(mWindow, _("CPU TDP Max"), false); + std::string selectedOCProfile = SystemConf::getInstance()->get(configName + ".overclock"); + if (selectedOCProfile.empty()) + selectedOCProfile = "default"; - if (SystemData::es_features_loaded || (!SystemData::es_features_loaded && (systemData->getName() == "gb" || systemData->getName() == "gbc" || systemData->getName() == "gb2players" || systemData->getName() == "gbc2players" || systemData->getName() == "gbh" || systemData->getName() == "gbch"))) // only for gb, gbc and gb2players gbh gbch + bool xfound = false; + for (auto it = tdpRange.begin(); it != tdpRange.end(); it++) { - systemConfiguration->addWithLabel(_("COLORIZATION"), colorizations_choices); - systemConfiguration->addWithLabel(_("TWB64 - PACK 1 PALETTE"), twb1_colorizations_choices); - systemConfiguration->addWithLabel(_("TWB64 - PACK 2 PALETTE"), twb2_colorizations_choices); - systemConfiguration->addWithLabel(_("TWB64 - PACK 3 PALETTE"), twb3_colorizations_choices); - systemConfiguration->addWithLabel(_("PIXELSHIFT - PACK 1 PALETTE"), pixelshift1_colorizations_choices); - systemConfiguration->addSaveFunc([colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorization", colorizations_choices->getSelected()); }); - systemConfiguration->addSaveFunc([twb1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb1_colorization", twb1_colorizations_choices->getSelected()); }); - systemConfiguration->addSaveFunc([twb2_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb2_colorization", twb2_colorizations_choices->getSelected()); }); - systemConfiguration->addSaveFunc([twb3_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb3_colorization", twb3_colorizations_choices->getSelected()); }); - systemConfiguration->addSaveFunc([pixelshift1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.pixelshift1_colorization", pixelshift1_colorizations_choices->getSelected()); }); + optionsOCProfile->add((*it), (*it), selectedOCProfile == (*it)); + if (selectedOCProfile == (*it)) + xfound = true; + } + + + if (!xfound) + optionsOCProfile->add(selectedOCProfile, selectedOCProfile, true); + + systemConfiguration->addWithLabel(_("CPU TDP Max"), optionsOCProfile); + + systemConfiguration->addSaveFunc([optionsOCProfile, selectedOCProfile, configName, mWindow] + { + if (optionsOCProfile->changed()) { + mWindow->pushGui(new GuiMsgBox(mWindow, _("WARNING: OVERCLOCKING YOUR DEVICE MAY RESULT IN STABILITY PROBLEMS OR CAUSE HARDWARE DAMAGE!\n\nUSING THE QUIET COOLING PROFILE WHILE USING CERTAIN OVERCLOCKS MAY CAUSE PANIC REBOOTS!\n\nJELOS IS NOT RESPONSIBLE FOR ANY DAMAGE THAT MAY OCCUR USING THESE SETTINGS!\n\nCLICK YES THAT YOU AGREE, OR NO TO CANCEL."), _("YES"), + [optionsOCProfile,configName] { + SystemConf::getInstance()->set(configName + ".overclock", optionsOCProfile->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + }, _("NO"), nullptr)); + } + }); + } + + if (Utils::FileSystem::exists("/sys/devices/system/cpu/cpufreq/policy0/energy_performance_preference")) { + // Provides EPP Profile switching + auto optionsEPP = std::make_shared >(mWindow, _("Energy Performance Preference"), false); + std::string selectedEPP = SystemConf::getInstance()->get(configName + ".power.epp"); + if (selectedEPP.empty()) + selectedEPP = "default"; + + optionsEPP->add(_("DEFAULT"), "default", selectedEPP == "default"); + + optionsEPP->add(_("Performance"),"performance", selectedEPP == "performance"); + optionsEPP->add(_("Balance Performance"),"balance_performance", selectedEPP == "balance_performance"); + optionsEPP->add(_("Balance Power Saving"),"balance_power", selectedEPP == "balance_power"); + optionsEPP->add(_("Power Saving"),"power", selectedEPP == "power"); + + systemConfiguration->addWithLabel(_("Energy Performance Preference"), optionsEPP); + + systemConfiguration->addSaveFunc([optionsEPP, selectedEPP, configName] + { + if (optionsEPP->changed()) { + SystemConf::getInstance()->set(configName + ".power.epp", optionsEPP->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + } + }); + } + +#endif + + // Per game/core/emu CPU governor + auto optionsGovernors = std::make_shared >(mWindow, _("CPU SCALING GOVERNOR"), false); + + std::vector availableGovernors = ApiSystem::getInstance()->getAvailableGovernors(); + std::string selectedGovernors = SystemConf::getInstance()->get(configName + ".cpugovernor"); + if (selectedGovernors.empty()) + selectedGovernors = "default"; + + bool cfound = false; + for (auto it = availableGovernors.begin(); it != availableGovernors.end(); it++) + { + optionsGovernors->add((*it), (*it), selectedGovernors == (*it)); + if (selectedGovernors == (*it)) + cfound = true; + } + if (!cfound) + optionsGovernors->add(selectedGovernors, selectedGovernors, true); + + systemConfiguration->addWithLabel(_("CPU SCALING GOVERNOR"), optionsGovernors); + + systemConfiguration->addSaveFunc([configName, selectedGovernors, optionsGovernors] + { + if (optionsGovernors->changed()) { + SystemConf::getInstance()->set(configName + ".cpugovernor", optionsGovernors->getSelected()); + SystemConf::getInstance()->saveSystemConf(); + } + }); + + // GPU performance mode with enhanced power savings + auto gpuPerformance = std::make_shared >(mWindow, _("GPU PERFORMANCE PROFILE"), false); + std::string gpu_performance = SystemConf::getInstance()->get(configName + ".gpuperf"); + if (gpu_performance.empty()) + gpu_performance = "default"; + + gpuPerformance->add(_("DEFAULT"), "default", gpu_performance == "default"); + gpuPerformance->add(_("Balanced"), "auto", gpu_performance == "auto"); + gpuPerformance->add(_("Battery Focus"), "low", gpu_performance == "low"); +#if defined(AMD64) + gpuPerformance->add(_("Performance Focus"), "profile_standard", gpu_performance == "profile_standard"); +#endif + gpuPerformance->add(_("Best Performance"), "profile_peak", gpu_performance == "profile_peak"); + + systemConfiguration->addWithLabel(_("GPU PERFORMANCE PROFILE"), gpuPerformance); + + systemConfiguration->addSaveFunc([configName, gpuPerformance, gpu_performance] + { + if (gpuPerformance->changed()) { + SystemConf::getInstance()->set(configName + ".gpuperf", gpuPerformance->getSelected()); + SystemConf::getInstance()->saveSystemConf(); } + }); + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::latency_reduction)) + systemConfiguration->addEntry(_("LATENCY REDUCTION"), true, [mWindow, configName] { openLatencyReductionConfiguration(mWindow, configName); }); + + if (systemData->isFeatureSupported(currentEmulator, currentCore, EmulatorFeatures::colorization)) + { + systemConfiguration->addEntry(_("COLORIZATION"), true, [mWindow, configName] { openColorizationConfiguration(mWindow, configName); }); } // Load per-game / per-emulator / per-system custom features From fbc8bd207d110b06b6208f2f575b885d5bb00971 Mon Sep 17 00:00:00 2001 From: Jade <48196637+GlazedBelmont@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:35:08 -0500 Subject: [PATCH 2/4] add the new colorization menu into headers --- es-app/src/guis/GuiMenu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/es-app/src/guis/GuiMenu.h b/es-app/src/guis/GuiMenu.h index 08056d8..f234910 100644 --- a/es-app/src/guis/GuiMenu.h +++ b/es-app/src/guis/GuiMenu.h @@ -104,6 +104,8 @@ class GuiMenu : public GuiComponent static void openLatencyReductionConfiguration(Window* mWindow, std::string configName); static void openCustomAspectRatioConfiguration(Window* mWindow, std::string configName); + static void openColorizationConfiguration(Window* mWindow, std::string configName); + std::vector mLoadedInput; // used to keep information about loaded devices in case there are unpluged between device window load and save void clearLoadedInput(); From 291694a95a5a2beb8b888a107f1e53b3b4634bc4 Mon Sep 17 00:00:00 2001 From: GlaZedBelmont <48196637+GlaZedBelmont@users.noreply.github.com> Date: Thu, 7 Mar 2024 19:54:22 -0500 Subject: [PATCH 3/4] Fix up default options --- es-app/src/guis/GuiMenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index e4ebc9b..16daa41 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -2074,8 +2074,8 @@ void GuiMenu::openColorizationConfiguration(Window* mWindow, std::string configN pixelshift1_colorizations_choices->add(pixelshift1_colors_modes[i], pixelshift1_colors_modes[i], pixelshift1_currentColorization == std::string(pixelshift1_colors_modes[i])); colorCorrection_enabled->addRange({ { _("DEFAULT"), "" }, {_("GBC Only"), "GBC only"}, {_("Always"), "always"}, {_("Disabled"), ""} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection")); - colorCorrection_mode_choices->addRange({ { _("DEFAULT"), "" }, {_("Accurate"), "accurate"}, {_("Fast"), "fast"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_mode")); - colorCorrection_frontlight_choices->addRange({ { _("DEFAULT"), "" }, {_("Central"), "central"}, {_("Above Screen"), "above screen"}, {_("Below screen"), "below screen"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_frontlightposition")); + colorCorrection_mode_choices->addRange({ { _("DEFAULT"), "accurate" }, {_("Accurate"), "accurate"}, {_("Fast"), "fast"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_mode")); + colorCorrection_frontlight_choices->addRange({ { _("DEFAULT"), "central" }, {_("Central"), "central"}, {_("Above Screen"), "above screen"}, {_("Below screen"), "below screen"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_frontlightposition")); guiColorization->addWithLabel(_("GB COLORIZATION"), colorizations_choices); From c708ed177a24035bf76fedb69e257ff5e90c5c26 Mon Sep 17 00:00:00 2001 From: Jade <48196637+GlazedBelmont@users.noreply.github.com> Date: Thu, 7 Mar 2024 21:32:17 -0500 Subject: [PATCH 4/4] comment out gbc color correction --- es-app/src/guis/GuiMenu.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 16daa41..2ceae0f 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -1611,10 +1611,10 @@ void GuiMenu::openColorizationConfiguration(Window* mWindow, std::string configN auto twb2_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 2 PALETTE"), false); auto twb3_colorizations_choices = std::make_shared >(mWindow, _("TWB - PACK 3 PALETTE"), false); auto pixelshift1_colorizations_choices = std::make_shared >(mWindow, _("PIXELSHIFT - PACK 1 PALETTE"), false); - auto colorCorrection_enabled = std::make_shared>(mWindow, _("COLOR CORRECTION")); +/* auto colorCorrection_enabled = std::make_shared>(mWindow, _("COLOR CORRECTION")); auto colorCorrection_mode_choices = std::make_shared>(mWindow, _("COLOR CORRECTION MODE")); auto colorCorrection_frontlight_choices = std::make_shared>(mWindow, _("COLOR CORRECTION - FRONTLIGHT POSITION")); - +*/ std::string currentColorization = SystemConf::getInstance()->get(configName + ".renderer.colorization"); std::string twb1_currentColorization = SystemConf::getInstance()->get(configName + ".renderer.twb1_colorization"); @@ -2073,9 +2073,9 @@ void GuiMenu::openColorizationConfiguration(Window* mWindow, std::string configN for (int i = 0; i < n_pixelshift1_colors_modes; i++) pixelshift1_colorizations_choices->add(pixelshift1_colors_modes[i], pixelshift1_colors_modes[i], pixelshift1_currentColorization == std::string(pixelshift1_colors_modes[i])); - colorCorrection_enabled->addRange({ { _("DEFAULT"), "" }, {_("GBC Only"), "GBC only"}, {_("Always"), "always"}, {_("Disabled"), ""} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection")); - colorCorrection_mode_choices->addRange({ { _("DEFAULT"), "accurate" }, {_("Accurate"), "accurate"}, {_("Fast"), "fast"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_mode")); - colorCorrection_frontlight_choices->addRange({ { _("DEFAULT"), "central" }, {_("Central"), "central"}, {_("Above Screen"), "above screen"}, {_("Below screen"), "below screen"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_frontlightposition")); +// colorCorrection_enabled->addRange({ { _("DEFAULT"), "" }, {_("GBC Only"), "GBC only"}, {_("Always"), "always"}, {_("Disabled"), ""} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection")); +// colorCorrection_mode_choices->addRange({ { _("DEFAULT"), "accurate" }, {_("Accurate"), "accurate"}, {_("Fast"), "fast"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_mode")); +// colorCorrection_frontlight_choices->addRange({ { _("DEFAULT"), "central" }, {_("Central"), "central"}, {_("Above Screen"), "above screen"}, {_("Below screen"), "below screen"} }, SystemConf::getInstance()->get(configName + ".renderer.colorcorrection_frontlightposition")); guiColorization->addWithLabel(_("GB COLORIZATION"), colorizations_choices); @@ -2083,20 +2083,20 @@ void GuiMenu::openColorizationConfiguration(Window* mWindow, std::string configN guiColorization->addWithLabel(_("TWB64 - PACK 2 PALETTE"), twb2_colorizations_choices); guiColorization->addWithLabel(_("TWB64 - PACK 3 PALETTE"), twb3_colorizations_choices); guiColorization->addWithLabel(_("PIXELSHIFT - PACK 1 PALETTE"), pixelshift1_colorizations_choices); - guiColorization->addWithLabel(_("COLOR CORRECTION"), colorCorrection_enabled); +/* guiColorization->addWithLabel(_("COLOR CORRECTION"), colorCorrection_enabled); guiColorization->addWithLabel(_("COLOR CORRECTION MODE"), colorCorrection_mode_choices); guiColorization->addWithLabel(_("COLOR CORRECTION - FRONTLIGHT POSITION"), colorCorrection_frontlight_choices); - +*/ guiColorization->addSaveFunc([colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorization", colorizations_choices->getSelected()); }); guiColorization->addSaveFunc([twb1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb1_colorization", twb1_colorizations_choices->getSelected()); }); guiColorization->addSaveFunc([twb2_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb2_colorization", twb2_colorizations_choices->getSelected()); }); guiColorization->addSaveFunc([twb3_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.twb3_colorization", twb3_colorizations_choices->getSelected()); }); guiColorization->addSaveFunc([pixelshift1_colorizations_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.pixelshift1_colorization", pixelshift1_colorizations_choices->getSelected()); }); - guiColorization->addSaveFunc([colorCorrection_enabled, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection", colorCorrection_enabled->getSelected()); }); +/* guiColorization->addSaveFunc([colorCorrection_enabled, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection", colorCorrection_enabled->getSelected()); }); guiColorization->addSaveFunc([colorCorrection_mode_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection_mode", colorCorrection_mode_choices->getSelected()); }); guiColorization->addSaveFunc([colorCorrection_frontlight_choices, configName] { SystemConf::getInstance()->set(configName + ".renderer.colorcorrection_frontlightposition", colorCorrection_frontlight_choices->getSelected()); }); - +*/ mWindow->pushGui(guiColorization); }