From 8fcb56cfb3191aaa717cb1f48bb4f7414c09fa6e Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Sat, 18 Jul 2020 13:21:44 +0200 Subject: [PATCH] Made game launching on Windows much more seamless. Also added an option to hide the taskbar. --- INSTALL.md | 26 +++++++++- es-app/src/EmulationStation.rc | 2 +- es-app/src/FileData.cpp | 28 ++++------- es-app/src/guis/GuiMenu.cpp | 12 ++++- es-app/src/main.cpp | 27 ++++++++++- es-app/src/views/ViewController.cpp | 12 +++++ es-app/src/views/gamelist/VideoGameListView.h | 3 +- es-core/src/GuiComponent.cpp | 12 +++++ es-core/src/GuiComponent.h | 2 + es-core/src/Platform.cpp | 38 +++++++++++++-- es-core/src/Platform.h | 4 ++ es-core/src/Settings.cpp | 9 ++++ es-core/src/Window.cpp | 48 ++++++++++++++----- es-core/src/Window.h | 5 ++ es-core/src/components/VideoComponent.cpp | 28 ++++++++++- es-core/src/components/VideoComponent.h | 10 +++- es-core/src/components/VideoVlcComponent.cpp | 15 +++++- es-core/src/components/VideoVlcComponent.h | 3 ++ es-core/src/renderers/Renderer.cpp | 8 ++++ 19 files changed, 246 insertions(+), 46 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 256f340d6..63ac42c6d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -357,6 +357,7 @@ audio_output\libwaveout_plugin.dll codec\libavcodec_plugin.dll codec\libx264_plugin.dll codec\libx265_plugin.dll +logger\libconsole_logger_plugin.dll text_renderer\libfreetype_plugin.dll video_chroma\libswscale_plugin.dll video_output\libvmem_plugin.dll @@ -550,7 +551,9 @@ The new configuration will be added to the `~/.emulationstation/es_input.cfg` fi Command line arguments ====================== -You can use `--help` or `-h` to view a list of command line options. Briefly outlined here: +You can use `--help` or `-h` to view a list of command line options, as shown here. + +### Unix: ``` --resolution [width] [height] Try to force a particular resolution @@ -574,6 +577,27 @@ You can use `--help` or `-h` to view a list of command line options. Briefly out --help, -h Summon a sentient, angry tuba ``` +### Windows: + +``` +--resolution [width] [height] Try to force a particular resolution +--gamelist-only Skip automatic game ROM search, only read from gamelist.xml +--ignore-gamelist Ignore the gamelist files (useful for troubleshooting) +--draw-framerate Display the framerate +--no-exit Don't show the exit option in the menu +--no-splash Don't show the splash screen +--debug Print debug information +--vsync [1/on or 0/off] Turn vsync on or off (default is on) +--max-vram [size] Max VRAM to use in Mb before swapping + Set to at least 20 to avoid unpredictable behavior +--force-kid Force the UI mode to Kid +--force-kiosk Force the UI mode to Kiosk +--force-disable-filters Force the UI to ignore applied filters in gamelist +--home [path] Directory to use as home path +--version, -v Displays version information +--help, -h Summon a sentient, angry tuba +``` + As long as ES hasn't frozen, you can always press F4 to close the application. As you can see above, you can override the home directory path using the `--home` flag. So by running for instance the command `emulationstation --home ~/games/emulation`, ES will use `~/games/emulation/.emulationstation` as its base directory. diff --git a/es-app/src/EmulationStation.rc b/es-app/src/EmulationStation.rc index a8ec517ee..a461e9481 100644 --- a/es-app/src/EmulationStation.rc +++ b/es-app/src/EmulationStation.rc @@ -20,7 +20,7 @@ BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", "\0" - VALUE "FileDescription", "EmulationStation - emulator frontend\0" + VALUE "FileDescription", "EmulationStation - Emulator Front-end\0" VALUE "FileVersion", RESOURCE_VERSION_STRING VALUE "InternalName", "emulationstation.exe\0" VALUE "LegalCopyright", "\0" diff --git a/es-app/src/FileData.cpp b/es-app/src/FileData.cpp index 8da4ad139..5a9439481 100644 --- a/es-app/src/FileData.cpp +++ b/es-app/src/FileData.cpp @@ -8,6 +8,7 @@ #include "FileData.h" +#include "guis/GuiInfoPopup.h" #include "utils/FileSystemUtil.h" #include "utils/StringUtil.h" #include "utils/TimeUtil.h" @@ -435,15 +436,6 @@ void FileData::launchGame(Window* window) { LOG(LogInfo) << "Attempting to launch game..."; - AudioManager::getInstance()->deinit(); - VolumeControl::getInstance()->deinit(); - - // TEMPORARY - Windows does not like it at all if you launch a game without - // first doing a deinit(). Need to fix this properly at a later date. - #ifdef _WIN64 - window->deinit(); - #endif - std::string command = ""; // Check if there is a launch command override for the game @@ -544,21 +536,21 @@ void FileData::launchGame(Window* window) exitCode = launchEmulatorUnix(command); #endif + // Notify the user in case of a failed game launch using a popup window. if (exitCode != 0) { LOG(LogWarning) << "...launch terminated with nonzero exit code " << exitCode << "!"; + + GuiInfoPopup* s = new GuiInfoPopup(window, "ERROR LAUNCHING GAME '" + + Utils::String::toUpper(metadata.get("name")) + "' (EXIT CODE " + + Utils::String::toUpper(std::to_string(exitCode) + ")"), 4000); + window->setInfoPopup(s); + } + else { + window->setLaunchedGame(); } Scripting::fireEvent("game-end"); - // TEMPORARY - Windows does not like it at all if you launch a game without - // first doing a deinit(). Need to fix this properly at a later date. - #ifdef _WIN64 - window->init(); - #endif - - VolumeControl::getInstance()->init(); - window->normalizeNextUpdate(); - // Update number of times the game has been launched. FileData* gameToUpdate = getSourceFileData(); diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 62a11ab1c..9f0c347f2 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -485,6 +485,7 @@ void GuiMenu::openOtherSettings() s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)Math::round(max_vram->getValue())); }); + #ifdef __unix__ // Fullscreen mode. auto fullscreen_mode = std::make_shared> (mWindow, getHelpStyle(), "FULLSCREEN MODE", false); @@ -502,6 +503,7 @@ void GuiMenu::openOtherSettings() } Settings::getInstance()->setString("FullscreenMode", fullscreen_mode->getSelected()); }); + #endif // Power saver. auto power_saver = std::make_shared> @@ -541,7 +543,6 @@ void GuiMenu::openOtherSettings() if (needReload) ViewController::get()->reloadAll(); }); - #endif // When to save game metadata. @@ -593,6 +594,15 @@ void GuiMenu::openOtherSettings() }); s->addRow(row); + #ifdef _WIN64 + // Hide taskbar during ES program session. + auto hide_taskbar = std::make_shared(mWindow); + hide_taskbar->setState(Settings::getInstance()->getBool("HideTaskbar")); + s->addWithLabel("HIDE TASKBAR (REQUIRES RESTART)", hide_taskbar); + s->addSaveFunc([hide_taskbar] { Settings::getInstance()-> + setBool("HideTaskbar", hide_taskbar->getState()); }); + #endif + // Allow overriding of the launch command per game (the option to disable this is // intended primarily for testing purposes). auto launchcommand_override = std::make_shared(mWindow); diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index 554cffe50..3676c31c0 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -245,6 +245,8 @@ bool parseArgs(int argc, char* argv[]) Settings::getInstance()->setBool("Debug", true); Log::setReportingLevel(LogDebug); } + // Windowed mode is always selected on Windows. + #ifndef _WIN64 else if (strcmp(argv[i], "--fullscreen-normal") == 0) { Settings::getInstance()->setString("FullscreenMode", "normal"); } @@ -254,6 +256,7 @@ bool parseArgs(int argc, char* argv[]) else if (strcmp(argv[i], "--windowed") == 0) { Settings::getInstance()->setBool("Windowed", true); } + #endif else if (strcmp(argv[i], "--vsync") == 0) { bool vsync = (strcmp(argv[i + 1], "on") == 0 || strcmp(argv[i + 1], "1") == 0) ? true : false; @@ -286,9 +289,11 @@ bool parseArgs(int argc, char* argv[]) " --no-exit Don't show the exit option in the menu\n" " --no-splash Don't show the splash screen\n" " --debug Print debug information\n" +#ifndef _WIN64 " --windowed Windowed mode, should be combined with --resolution\n" " --fullscreen-normal Normal fullscreen mode\n" " --fullscreen-borderless Borderless fullscreen mode (always on top)\n" +#endif " --vsync [1/on or 0/off] Turn vsync on or off (default is on)\n" " --max-vram [size] Max VRAM to use in Mb before swapping\n" " Set to at least 20 to avoid unpredictable behavior\n" @@ -348,8 +353,8 @@ bool loadSystemConfigFile(std::string& errorMsg) "(Check that the file extensions are supported.)"; errorMsg = "THE SYSTEMS CONFIGURATION FILE EXISTS, BUT NO\n" "GAME FILES WERE FOUND. PLEASE MAKE SURE THAT\n" - "THE 'ROMDIRECTORY' SETTING IN ES_SETTINGS.CFG IS\n" - "POINTING TO YOUR ROM DIRECTORY AND THAT YOUR\n" + "THE \"ROMDIRECTORY\" SETTING IN ES_SETTINGS.CFG\n" + "IS POINTING TO YOUR ROM DIRECTORY AND THAT YOUR\n" "GAME FILES ARE USING SUPPORTED FILE EXTENSIONS.\n" "THE GAME SYSTEMS SUBDIRECTORIES ALSO NEED TO\n" "MATCH THE PLATFORM TAGS IN ES_SYSTEMS.CFG.\n" @@ -391,6 +396,18 @@ int main(int argc, char* argv[]) outputToConsole(true); #endif + #ifdef _WIN64 + // Hide taskbar if the setting for this is enabled. + bool taskbarStateChanged = false; + unsigned int taskbarState; + + if (Settings::getInstance()->getBool("HideTaskbar")) { + taskbarStateChanged = true; + taskbarState = getTaskbarState(); + hideTaskbar(); + } + #endif + // Call this ONLY when linking with FreeImage as a static library. #ifdef FREEIMAGE_LIB FreeImage_Initialise(); @@ -586,6 +603,12 @@ int main(int argc, char* argv[]) FreeImage_DeInitialise(); #endif + #ifdef _WIN64 + // If the taskbar state was changed (taskbar was hidden), then revert it. + if (taskbarStateChanged) + revertTaskbarState(taskbarState); + #endif + processQuitMode(); LOG(LogInfo) << "EmulationStation cleanly shutting down."; diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 556cd3b31..71570e166 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -408,6 +408,13 @@ bool ViewController::input(InputConfig* config, Input input) if (mLockInput) return true; + // If we have previously launched a game and there is now input registered, it means + // the user is back in ES, so unset the flag to indicate that a game has been launched + // and update all the GUI components to reflect this. + if (mWindow->getGameLaunchedState()) { + mWindow->unsetLaunchedGame(); + } + // Open menu. if (!(UIModeController::getInstance()->isUIModeKid() && !Settings::getInstance()->getBool("ShowKidStartMenu")) && @@ -531,6 +538,11 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme) break; } } + + // If a game has been launched, then update all the GUI components to reflect this. + if (mWindow->getGameLaunchedState()) + mWindow->setLaunchedGame(); + // Redisplay the current view. if (mCurrentView) mCurrentView->onShow(); diff --git a/es-app/src/views/gamelist/VideoGameListView.h b/es-app/src/views/gamelist/VideoGameListView.h index b9d582015..fc42672f0 100644 --- a/es-app/src/views/gamelist/VideoGameListView.h +++ b/es-app/src/views/gamelist/VideoGameListView.h @@ -67,8 +67,7 @@ private: ScrollableContainer mDescContainer; TextComponent mDescription; - bool mVideoPlaying; - + bool mVideoPlaying; }; #endif // ES_APP_VIEWS_GAME_LIST_VIDEO_GAME_LIST_VIEW_H diff --git a/es-core/src/GuiComponent.cpp b/es-core/src/GuiComponent.cpp index 6cd38b146..d796bcb9f 100644 --- a/es-core/src/GuiComponent.cpp +++ b/es-core/src/GuiComponent.cpp @@ -511,6 +511,18 @@ void GuiComponent::onScreenSaverDeactivate() getChild(i)->onScreenSaverDeactivate(); } +void GuiComponent::onGameLaunchedActivate() +{ + for (unsigned int i = 0; i < getChildCount(); i++) + getChild(i)->onGameLaunchedActivate(); +} + +void GuiComponent::onGameLaunchedDeactivate() +{ + for (unsigned int i = 0; i < getChildCount(); i++) + getChild(i)->onGameLaunchedDeactivate(); +} + void GuiComponent::topWindow(bool isTop) { for (unsigned int i = 0; i < getChildCount(); i++) diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h index fd5bf4dfd..71ad22ad5 100644 --- a/es-core/src/GuiComponent.h +++ b/es-core/src/GuiComponent.h @@ -157,6 +157,8 @@ public: virtual void onScreenSaverActivate(); virtual void onScreenSaverDeactivate(); + virtual void onGameLaunchedActivate(); + virtual void onGameLaunchedDeactivate(); virtual void topWindow(bool isTop); // Default implementation just handles and tags as normalized float pairs. diff --git a/es-core/src/Platform.cpp b/es-core/src/Platform.cpp index e117e6a65..c95bf8e4a 100644 --- a/es-core/src/Platform.cpp +++ b/es-core/src/Platform.cpp @@ -68,6 +68,7 @@ int runSystemCommand(const std::wstring& cmd_utf16) int launchEmulatorUnix(const std::string& cmd_utf8) { + // TODO, replace with proper child process execution. #ifdef __unix__ return system(cmd_utf8.c_str()); #else @@ -95,11 +96,7 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16) nullptr, // Use parent's environment block. nullptr, // Use parent's starting directory. &si, // Pointer to the STARTUPINFOW structure. - &pi ); // Pointer to the PROCESS_INFORMATION structure. - - // Wait for the child process to exit. - WaitForSingleObject(pi.hThread, INFINITE); - WaitForSingleObject(pi.hProcess, INFINITE); + &pi); // Pointer to the PROCESS_INFORMATION structure. // If the return value is false, then something failed. if (!processReturnValue) { @@ -132,6 +129,37 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16) #endif } +unsigned int getTaskbarState() +{ + #ifdef _WIN64 + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + return (UINT) SHAppBarMessage(ABM_GETSTATE, &barData); + #else + return 0; + #endif +} + +void hideTaskbar() +{ + #ifdef _WIN64 + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + barData.lParam = ABS_AUTOHIDE; + SHAppBarMessage(ABM_SETSTATE, &barData); + #endif +} + +void revertTaskbarState(unsigned int& state) +{ + #ifdef _WIN64 + APPBARDATA barData; + barData.cbSize = sizeof(APPBARDATA); + barData.lParam = state; + SHAppBarMessage(ABM_SETSTATE, &barData); + #endif +} + QuitMode quitMode = QuitMode::QUIT; int quitES(QuitMode mode) diff --git a/es-core/src/Platform.h b/es-core/src/Platform.h index 987fe9adf..0c6a65dae 100644 --- a/es-core/src/Platform.h +++ b/es-core/src/Platform.h @@ -29,6 +29,10 @@ int runSystemCommand(const std::wstring& cmd_utf16); int launchEmulatorUnix(const std::string& cmd_utf8); int launchEmulatorWindows(const std::wstring& cmd_utf16); +unsigned int getTaskbarState(); +void hideTaskbar(); +void revertTaskbarState(unsigned int& state); + // Clean, normal shutdown. int quitES(QuitMode mode = QuitMode::QUIT); // Immediately shut down the application as cleanly as possible. diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index e8e256f1d..9a2d7e87d 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -32,7 +32,9 @@ std::vector settings_dont_save { "ShowExit", // --no-exit "SplashScreen", // --no-splash "VSync", // --vsync [1/on or 0/off] + #ifndef _WIN64 "Windowed", // --windowed + #endif "WindowWidth", // Set via --resolution [width] [height] "WindowHeight", // set via --resolution [width] [height] @@ -164,7 +166,9 @@ void Settings::setDefaults() #else mIntMap["MaxVRAM"] = 100; #endif + #ifdef __unix__ mStringMap["FullscreenMode"] = "normal"; + #endif mStringMap["PowerSaverMode"] = "disabled"; // This setting only applies to raspberry pi but set it for all platforms so // we don't get a warning if we encounter it on a different platform. @@ -181,6 +185,9 @@ void Settings::setDefaults() mBoolMap["ScreenSaverOmxPlayer"] = false; #endif mStringMap["SaveGamelistsMode"] = "always"; + #ifdef _WIN64 + mBoolMap["HideTaskbar"] = false; + #endif mStringMap["MediaDirectory"] = ""; mBoolMap["LaunchCommandOverride"] = true; mBoolMap["CustomEventScripts"] = false; @@ -203,7 +210,9 @@ void Settings::setDefaults() mBoolMap["ShowExit"] = true; mBoolMap["SplashScreen"] = true; mBoolMap["VSync"] = true; + #ifndef _WIN64 mBoolMap["Windowed"] = false; + #endif mIntMap["WindowWidth"] = 0; mIntMap["WindowHeight"] = 0; mIntMap["ScreenWidth"] = 0; diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 204e1e63e..43ac9d9cc 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -56,12 +56,12 @@ void Window::pushGui(GuiComponent* gui) void Window::removeGui(GuiComponent* gui) { - for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) { - if (*i == gui) { - i = mGuiStack.erase(i); + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) { + if (*it == gui) { + it = mGuiStack.erase(it); // We just popped the stack and the stack is not empty. - if (i == mGuiStack.cend() && mGuiStack.size()) { + if (it == mGuiStack.cend() && mGuiStack.size()) { mGuiStack.back()->updateHelpPrompts(); mGuiStack.back()->topWindow(true); } @@ -111,8 +111,8 @@ bool Window::init() void Window::deinit() { // Hide all GUI elements on uninitialisation - this disable. - for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) - (*i)->onHide(); + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) + (*it)->onHide(); InputManager::getInstance()->deinit(); ResourceManager::getInstance()->unloadAll(); @@ -266,8 +266,14 @@ void Window::render() } unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime"); - if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) - startScreenSaver(); + // If a game has been launched, reset the screensaver timer when it's been reached as we + // don't want to start the screensaver in the background when running a game. + if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) { + if (mGameLaunchedState) + mTimeSinceLastInput = 0; + else + startScreenSaver(); + } // Always call the screensaver render function regardless of whether the screensaver is active // or not because it may perform a fade on transition. @@ -420,12 +426,30 @@ bool Window::isProcessing() [](GuiComponent* c) { return c->isProcessing(); }) > 0; } +void Window::setLaunchedGame() +{ + // Tell the GUI components that a game has been launched. + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) + (*it)->onGameLaunchedActivate(); + + mGameLaunchedState = true; +} + +void Window::unsetLaunchedGame() +{ + // Tell the GUI components that the user is back in ES again. + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) + (*it)->onGameLaunchedDeactivate(); + + mGameLaunchedState = false; +} + void Window::startScreenSaver() { if (mScreenSaver && !mRenderScreenSaver) { // Tell the GUI components the screensaver is starting. - for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) - (*i)->onScreenSaverActivate(); + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) + (*it)->onScreenSaverActivate(); mScreenSaver->startScreenSaver(); mRenderScreenSaver = true; @@ -440,8 +464,8 @@ bool Window::cancelScreenSaver() mScreenSaver->resetCounts(); // Tell the GUI components the screensaver has stopped. - for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) - (*i)->onScreenSaverDeactivate(); + for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) + (*it)->onScreenSaverDeactivate(); return true; } diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 567687ca2..2976bc7b9 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -86,6 +86,10 @@ public: void renderScreenSaver(); bool isScreenSaverActive() { return mRenderScreenSaver; }; + void setLaunchedGame(); + void unsetLaunchedGame(); + bool getGameLaunchedState() { return mGameLaunchedState; }; + private: void onSleep(); void onWake(); @@ -98,6 +102,7 @@ private: ScreenSaver* mScreenSaver; InfoPopup* mInfoPopup; bool mRenderScreenSaver; + bool mGameLaunchedState; std::vector mGuiStack; diff --git a/es-core/src/components/VideoComponent.cpp b/es-core/src/components/VideoComponent.cpp index a39427e17..901bf88cc 100644 --- a/es-core/src/components/VideoComponent.cpp +++ b/es-core/src/components/VideoComponent.cpp @@ -67,8 +67,10 @@ VideoComponent::VideoComponent( mVideoWidth(0), mStartDelayed(false), mIsPlaying(false), + mPause(false), mShowing(false), mScreensaverActive(false), + mGameLaunched(false), mDisable(false), mScreensaverMode(false), mTargetIsMax(false), @@ -174,6 +176,9 @@ void VideoComponent::render(const Transform4x4f& parentTrans) // Handle looping of the video. handleLooping(); + + // Pause video in case a game has been launched. + pauseVideo(); } void VideoComponent::renderSnapshot(const Transform4x4f& parentTrans) @@ -253,6 +258,8 @@ void VideoComponent::handleLooping() void VideoComponent::startVideoWithDelay() { + mPause = false; + // If not playing then either start the video or initiate the delay. if (!mIsPlaying) { // Set the video that we are going to be playing so we don't attempt to restart it. @@ -300,7 +307,7 @@ void VideoComponent::update(int deltaTime) void VideoComponent::manageState() { - // We will only show if the component is on display and the screensaver + // We will only show the video if the component is on display and the screensaver // is not active. bool show = mShowing && !mScreensaverActive && !mDisable; @@ -324,6 +331,12 @@ void VideoComponent::manageState() if (show && !mVideoPath.empty()) startVideoWithDelay(); } + + // If a game has just been launched and a video is actually shown, then request a + // pause of the video so it doesn't continue to play in the background while the + // game is running. + if (mGameLaunched && show && !mPause) + mPause = true; } void VideoComponent::onShow() @@ -350,6 +363,19 @@ void VideoComponent::onScreenSaverDeactivate() manageState(); } +void VideoComponent::onGameLaunchedActivate() +{ + mGameLaunched = true; + manageState(); +} + +void VideoComponent::onGameLaunchedDeactivate() +{ + mGameLaunched = false; + stopVideo(); + manageState(); +} + void VideoComponent::topWindow(bool isTop) { mDisable = !isTop; diff --git a/es-core/src/components/VideoComponent.h b/es-core/src/components/VideoComponent.h index ac0a97cbb..15d404c6d 100644 --- a/es-core/src/components/VideoComponent.h +++ b/es-core/src/components/VideoComponent.h @@ -48,6 +48,8 @@ public: virtual void onHide() override; virtual void onScreenSaverActivate() override; virtual void onScreenSaverDeactivate() override; + virtual void onGameLaunchedActivate() override; + virtual void onGameLaunchedDeactivate() override; virtual void topWindow(bool isTop) override; void onOriginChanged() override; @@ -82,7 +84,9 @@ private: // Start the video immediately. virtual void startVideo() = 0; // Stop the video. - virtual void stopVideo() { }; + virtual void stopVideo() {}; + // Pause the video when a game has been launched. + virtual void pauseVideo() {}; // Handle looping the video. Must be called periodically. virtual void handleLooping(); @@ -109,13 +113,15 @@ protected: bool mStartDelayed; unsigned mStartTime; bool mIsPlaying; + bool mPause; bool mShowing; bool mDisable; bool mScreensaverActive; bool mScreensaverMode; + bool mGameLaunched; bool mTargetIsMax; - Configuration mConfig; + Configuration mConfig; }; #endif // ES_CORE_COMPONENTS_VIDEO_COMPONENT_H diff --git a/es-core/src/components/VideoVlcComponent.cpp b/es-core/src/components/VideoVlcComponent.cpp index 31326a451..75ef2a8e1 100644 --- a/es-core/src/components/VideoVlcComponent.cpp +++ b/es-core/src/components/VideoVlcComponent.cpp @@ -231,13 +231,25 @@ void VideoVlcComponent::handleLooping() (Settings::getInstance()->getBool("ScreenSaverVideoMute") && mScreensaverMode)) libvlc_audio_set_mute(mMediaPlayer, 1); - //libvlc_media_player_set_position(mMediaPlayer, 0.0f); libvlc_media_player_set_media(mMediaPlayer, mMedia); libvlc_media_player_play(mMediaPlayer); } } } +void VideoVlcComponent::pauseVideo() +{ + // If a game has been launched and the flag to pause the video has been + // set, then rewind and pause. + if (!mPause || !mMediaPlayer) + return; + + if (libvlc_media_player_get_state(mMediaPlayer) == libvlc_Playing) { + libvlc_media_player_set_position(mMediaPlayer, 0.0f); + libvlc_media_player_pause(mMediaPlayer); + } +} + void VideoVlcComponent::startVideo() { if (!mIsPlaying) { @@ -336,6 +348,7 @@ void VideoVlcComponent::stopVideo() { mIsPlaying = false; mStartDelayed = false; + mPause = false; // Release the media player so it stops calling back to us. if (mMediaPlayer) { libvlc_media_player_stop(mMediaPlayer); diff --git a/es-core/src/components/VideoVlcComponent.h b/es-core/src/components/VideoVlcComponent.h index 3f556d973..e860c0c62 100644 --- a/es-core/src/components/VideoVlcComponent.h +++ b/es-core/src/components/VideoVlcComponent.h @@ -57,10 +57,13 @@ private: // Calculates the correct mSize from our resizing information (set by setResize/setMaxSize). // Used internally whenever the resizing parameters or texture change. void resize(); + // Start the video immediately. virtual void startVideo() override; // Stop the video. virtual void stopVideo() override; + // Pause the video when a game has been launched. + virtual void pauseVideo() override; // Handle looping the video. Must be called periodically. virtual void handleLooping() override; diff --git a/es-core/src/renderers/Renderer.cpp b/es-core/src/renderers/Renderer.cpp index 08b7ecf61..ea6f024c6 100644 --- a/es-core/src/renderers/Renderer.cpp +++ b/es-core/src/renderers/Renderer.cpp @@ -104,12 +104,20 @@ namespace Renderer unsigned int windowFlags; + #ifdef _WIN64 + // For Windows, always set the mode to windowed, as full screen mode seems to + // behave quite erratic. There may be a proper fix for this, but for now windowed + // mode seems to behave well and it's almost completely seamless, especially with + // a hidden taskbar. + windowFlags = getWindowFlags(); + #else if (Settings::getInstance()->getBool("Windowed")) windowFlags = getWindowFlags(); else if (Settings::getInstance()->getString("FullscreenMode") == "borderless") windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | getWindowFlags(); else windowFlags = SDL_WINDOW_FULLSCREEN | getWindowFlags(); + #endif if ((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr) {