Made game launching on Windows much more seamless.

Also added an option to hide the taskbar.
This commit is contained in:
Leon Styhre 2020-07-18 13:21:44 +02:00
parent 6a0682b833
commit 8fcb56cfb3
19 changed files with 246 additions and 46 deletions

View file

@ -357,6 +357,7 @@ audio_output\libwaveout_plugin.dll
codec\libavcodec_plugin.dll codec\libavcodec_plugin.dll
codec\libx264_plugin.dll codec\libx264_plugin.dll
codec\libx265_plugin.dll codec\libx265_plugin.dll
logger\libconsole_logger_plugin.dll
text_renderer\libfreetype_plugin.dll text_renderer\libfreetype_plugin.dll
video_chroma\libswscale_plugin.dll video_chroma\libswscale_plugin.dll
video_output\libvmem_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 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 --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 --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 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. 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.

View file

@ -20,7 +20,7 @@ BEGIN
BLOCK "040904E4" BLOCK "040904E4"
BEGIN BEGIN
VALUE "Comments", "\0" VALUE "Comments", "\0"
VALUE "FileDescription", "EmulationStation - emulator frontend\0" VALUE "FileDescription", "EmulationStation - Emulator Front-end\0"
VALUE "FileVersion", RESOURCE_VERSION_STRING VALUE "FileVersion", RESOURCE_VERSION_STRING
VALUE "InternalName", "emulationstation.exe\0" VALUE "InternalName", "emulationstation.exe\0"
VALUE "LegalCopyright", "\0" VALUE "LegalCopyright", "\0"

View file

@ -8,6 +8,7 @@
#include "FileData.h" #include "FileData.h"
#include "guis/GuiInfoPopup.h"
#include "utils/FileSystemUtil.h" #include "utils/FileSystemUtil.h"
#include "utils/StringUtil.h" #include "utils/StringUtil.h"
#include "utils/TimeUtil.h" #include "utils/TimeUtil.h"
@ -435,15 +436,6 @@ void FileData::launchGame(Window* window)
{ {
LOG(LogInfo) << "Attempting to launch game..."; 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 = ""; std::string command = "";
// Check if there is a launch command override for the game // Check if there is a launch command override for the game
@ -544,21 +536,21 @@ void FileData::launchGame(Window* window)
exitCode = launchEmulatorUnix(command); exitCode = launchEmulatorUnix(command);
#endif #endif
// Notify the user in case of a failed game launch using a popup window.
if (exitCode != 0) { if (exitCode != 0) {
LOG(LogWarning) << "...launch terminated with nonzero exit code " << exitCode << "!"; 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"); 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. // Update number of times the game has been launched.
FileData* gameToUpdate = getSourceFileData(); FileData* gameToUpdate = getSourceFileData();

View file

@ -485,6 +485,7 @@ void GuiMenu::openOtherSettings()
s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM",
(int)Math::round(max_vram->getValue())); }); (int)Math::round(max_vram->getValue())); });
#ifdef __unix__
// Fullscreen mode. // Fullscreen mode.
auto fullscreen_mode = std::make_shared<OptionListComponent<std::string>> auto fullscreen_mode = std::make_shared<OptionListComponent<std::string>>
(mWindow, getHelpStyle(), "FULLSCREEN MODE", false); (mWindow, getHelpStyle(), "FULLSCREEN MODE", false);
@ -502,6 +503,7 @@ void GuiMenu::openOtherSettings()
} }
Settings::getInstance()->setString("FullscreenMode", fullscreen_mode->getSelected()); Settings::getInstance()->setString("FullscreenMode", fullscreen_mode->getSelected());
}); });
#endif
// Power saver. // Power saver.
auto power_saver = std::make_shared<OptionListComponent<std::string>> auto power_saver = std::make_shared<OptionListComponent<std::string>>
@ -541,7 +543,6 @@ void GuiMenu::openOtherSettings()
if (needReload) if (needReload)
ViewController::get()->reloadAll(); ViewController::get()->reloadAll();
}); });
#endif #endif
// When to save game metadata. // When to save game metadata.
@ -593,6 +594,15 @@ void GuiMenu::openOtherSettings()
}); });
s->addRow(row); s->addRow(row);
#ifdef _WIN64
// Hide taskbar during ES program session.
auto hide_taskbar = std::make_shared<SwitchComponent>(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 // Allow overriding of the launch command per game (the option to disable this is
// intended primarily for testing purposes). // intended primarily for testing purposes).
auto launchcommand_override = std::make_shared<SwitchComponent>(mWindow); auto launchcommand_override = std::make_shared<SwitchComponent>(mWindow);

View file

@ -245,6 +245,8 @@ bool parseArgs(int argc, char* argv[])
Settings::getInstance()->setBool("Debug", true); Settings::getInstance()->setBool("Debug", true);
Log::setReportingLevel(LogDebug); Log::setReportingLevel(LogDebug);
} }
// Windowed mode is always selected on Windows.
#ifndef _WIN64
else if (strcmp(argv[i], "--fullscreen-normal") == 0) { else if (strcmp(argv[i], "--fullscreen-normal") == 0) {
Settings::getInstance()->setString("FullscreenMode", "normal"); Settings::getInstance()->setString("FullscreenMode", "normal");
} }
@ -254,6 +256,7 @@ bool parseArgs(int argc, char* argv[])
else if (strcmp(argv[i], "--windowed") == 0) { else if (strcmp(argv[i], "--windowed") == 0) {
Settings::getInstance()->setBool("Windowed", true); Settings::getInstance()->setBool("Windowed", true);
} }
#endif
else if (strcmp(argv[i], "--vsync") == 0) { else if (strcmp(argv[i], "--vsync") == 0) {
bool vsync = (strcmp(argv[i + 1], "on") == 0 || bool vsync = (strcmp(argv[i + 1], "on") == 0 ||
strcmp(argv[i + 1], "1") == 0) ? true : false; 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-exit Don't show the exit option in the menu\n"
" --no-splash Don't show the splash screen\n" " --no-splash Don't show the splash screen\n"
" --debug Print debug information\n" " --debug Print debug information\n"
#ifndef _WIN64
" --windowed Windowed mode, should be combined with --resolution\n" " --windowed Windowed mode, should be combined with --resolution\n"
" --fullscreen-normal Normal fullscreen mode\n" " --fullscreen-normal Normal fullscreen mode\n"
" --fullscreen-borderless Borderless fullscreen mode (always on top)\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" " --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" " --max-vram [size] Max VRAM to use in Mb before swapping\n"
" Set to at least 20 to avoid unpredictable behavior\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.)"; "(Check that the file extensions are supported.)";
errorMsg = "THE SYSTEMS CONFIGURATION FILE EXISTS, BUT NO\n" errorMsg = "THE SYSTEMS CONFIGURATION FILE EXISTS, BUT NO\n"
"GAME FILES WERE FOUND. PLEASE MAKE SURE THAT\n" "GAME FILES WERE FOUND. PLEASE MAKE SURE THAT\n"
"THE 'ROMDIRECTORY' SETTING IN ES_SETTINGS.CFG IS\n" "THE \"ROMDIRECTORY\" SETTING IN ES_SETTINGS.CFG\n"
"POINTING TO YOUR ROM DIRECTORY AND THAT YOUR\n" "IS POINTING TO YOUR ROM DIRECTORY AND THAT YOUR\n"
"GAME FILES ARE USING SUPPORTED FILE EXTENSIONS.\n" "GAME FILES ARE USING SUPPORTED FILE EXTENSIONS.\n"
"THE GAME SYSTEMS SUBDIRECTORIES ALSO NEED TO\n" "THE GAME SYSTEMS SUBDIRECTORIES ALSO NEED TO\n"
"MATCH THE PLATFORM TAGS IN ES_SYSTEMS.CFG.\n" "MATCH THE PLATFORM TAGS IN ES_SYSTEMS.CFG.\n"
@ -391,6 +396,18 @@ int main(int argc, char* argv[])
outputToConsole(true); outputToConsole(true);
#endif #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. // Call this ONLY when linking with FreeImage as a static library.
#ifdef FREEIMAGE_LIB #ifdef FREEIMAGE_LIB
FreeImage_Initialise(); FreeImage_Initialise();
@ -586,6 +603,12 @@ int main(int argc, char* argv[])
FreeImage_DeInitialise(); FreeImage_DeInitialise();
#endif #endif
#ifdef _WIN64
// If the taskbar state was changed (taskbar was hidden), then revert it.
if (taskbarStateChanged)
revertTaskbarState(taskbarState);
#endif
processQuitMode(); processQuitMode();
LOG(LogInfo) << "EmulationStation cleanly shutting down."; LOG(LogInfo) << "EmulationStation cleanly shutting down.";

View file

@ -408,6 +408,13 @@ bool ViewController::input(InputConfig* config, Input input)
if (mLockInput) if (mLockInput)
return true; 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. // Open menu.
if (!(UIModeController::getInstance()->isUIModeKid() && if (!(UIModeController::getInstance()->isUIModeKid() &&
!Settings::getInstance()->getBool("ShowKidStartMenu")) && !Settings::getInstance()->getBool("ShowKidStartMenu")) &&
@ -531,6 +538,11 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
break; 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. // Redisplay the current view.
if (mCurrentView) if (mCurrentView)
mCurrentView->onShow(); mCurrentView->onShow();

View file

@ -68,7 +68,6 @@ private:
TextComponent mDescription; TextComponent mDescription;
bool mVideoPlaying; bool mVideoPlaying;
}; };
#endif // ES_APP_VIEWS_GAME_LIST_VIDEO_GAME_LIST_VIEW_H #endif // ES_APP_VIEWS_GAME_LIST_VIDEO_GAME_LIST_VIEW_H

View file

@ -511,6 +511,18 @@ void GuiComponent::onScreenSaverDeactivate()
getChild(i)->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) void GuiComponent::topWindow(bool isTop)
{ {
for (unsigned int i = 0; i < getChildCount(); i++) for (unsigned int i = 0; i < getChildCount(); i++)

View file

@ -157,6 +157,8 @@ public:
virtual void onScreenSaverActivate(); virtual void onScreenSaverActivate();
virtual void onScreenSaverDeactivate(); virtual void onScreenSaverDeactivate();
virtual void onGameLaunchedActivate();
virtual void onGameLaunchedDeactivate();
virtual void topWindow(bool isTop); virtual void topWindow(bool isTop);
// Default implementation just handles <pos> and <size> tags as normalized float pairs. // Default implementation just handles <pos> and <size> tags as normalized float pairs.

View file

@ -68,6 +68,7 @@ int runSystemCommand(const std::wstring& cmd_utf16)
int launchEmulatorUnix(const std::string& cmd_utf8) int launchEmulatorUnix(const std::string& cmd_utf8)
{ {
// TODO, replace with proper child process execution.
#ifdef __unix__ #ifdef __unix__
return system(cmd_utf8.c_str()); return system(cmd_utf8.c_str());
#else #else
@ -97,10 +98,6 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
&si, // Pointer to the STARTUPINFOW structure. &si, // Pointer to the STARTUPINFOW structure.
&pi); // Pointer to the PROCESS_INFORMATION structure. &pi); // Pointer to the PROCESS_INFORMATION structure.
// Wait for the child process to exit.
WaitForSingleObject(pi.hThread, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE);
// If the return value is false, then something failed. // If the return value is false, then something failed.
if (!processReturnValue) { if (!processReturnValue) {
LPWSTR pBuffer = nullptr; LPWSTR pBuffer = nullptr;
@ -132,6 +129,37 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
#endif #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; QuitMode quitMode = QuitMode::QUIT;
int quitES(QuitMode mode) int quitES(QuitMode mode)

View file

@ -29,6 +29,10 @@ int runSystemCommand(const std::wstring& cmd_utf16);
int launchEmulatorUnix(const std::string& cmd_utf8); int launchEmulatorUnix(const std::string& cmd_utf8);
int launchEmulatorWindows(const std::wstring& cmd_utf16); int launchEmulatorWindows(const std::wstring& cmd_utf16);
unsigned int getTaskbarState();
void hideTaskbar();
void revertTaskbarState(unsigned int& state);
// Clean, normal shutdown. // Clean, normal shutdown.
int quitES(QuitMode mode = QuitMode::QUIT); int quitES(QuitMode mode = QuitMode::QUIT);
// Immediately shut down the application as cleanly as possible. // Immediately shut down the application as cleanly as possible.

View file

@ -32,7 +32,9 @@ std::vector<const char*> settings_dont_save {
"ShowExit", // --no-exit "ShowExit", // --no-exit
"SplashScreen", // --no-splash "SplashScreen", // --no-splash
"VSync", // --vsync [1/on or 0/off] "VSync", // --vsync [1/on or 0/off]
#ifndef _WIN64
"Windowed", // --windowed "Windowed", // --windowed
#endif
"WindowWidth", // Set via --resolution [width] [height] "WindowWidth", // Set via --resolution [width] [height]
"WindowHeight", // set via --resolution [width] [height] "WindowHeight", // set via --resolution [width] [height]
@ -164,7 +166,9 @@ void Settings::setDefaults()
#else #else
mIntMap["MaxVRAM"] = 100; mIntMap["MaxVRAM"] = 100;
#endif #endif
#ifdef __unix__
mStringMap["FullscreenMode"] = "normal"; mStringMap["FullscreenMode"] = "normal";
#endif
mStringMap["PowerSaverMode"] = "disabled"; mStringMap["PowerSaverMode"] = "disabled";
// This setting only applies to raspberry pi but set it for all platforms so // 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. // we don't get a warning if we encounter it on a different platform.
@ -181,6 +185,9 @@ void Settings::setDefaults()
mBoolMap["ScreenSaverOmxPlayer"] = false; mBoolMap["ScreenSaverOmxPlayer"] = false;
#endif #endif
mStringMap["SaveGamelistsMode"] = "always"; mStringMap["SaveGamelistsMode"] = "always";
#ifdef _WIN64
mBoolMap["HideTaskbar"] = false;
#endif
mStringMap["MediaDirectory"] = ""; mStringMap["MediaDirectory"] = "";
mBoolMap["LaunchCommandOverride"] = true; mBoolMap["LaunchCommandOverride"] = true;
mBoolMap["CustomEventScripts"] = false; mBoolMap["CustomEventScripts"] = false;
@ -203,7 +210,9 @@ void Settings::setDefaults()
mBoolMap["ShowExit"] = true; mBoolMap["ShowExit"] = true;
mBoolMap["SplashScreen"] = true; mBoolMap["SplashScreen"] = true;
mBoolMap["VSync"] = true; mBoolMap["VSync"] = true;
#ifndef _WIN64
mBoolMap["Windowed"] = false; mBoolMap["Windowed"] = false;
#endif
mIntMap["WindowWidth"] = 0; mIntMap["WindowWidth"] = 0;
mIntMap["WindowHeight"] = 0; mIntMap["WindowHeight"] = 0;
mIntMap["ScreenWidth"] = 0; mIntMap["ScreenWidth"] = 0;

View file

@ -56,12 +56,12 @@ void Window::pushGui(GuiComponent* gui)
void Window::removeGui(GuiComponent* gui) void Window::removeGui(GuiComponent* gui)
{ {
for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) { for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) {
if (*i == gui) { if (*it == gui) {
i = mGuiStack.erase(i); it = mGuiStack.erase(it);
// We just popped the stack and the stack is not empty. // 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()->updateHelpPrompts();
mGuiStack.back()->topWindow(true); mGuiStack.back()->topWindow(true);
} }
@ -111,8 +111,8 @@ bool Window::init()
void Window::deinit() void Window::deinit()
{ {
// Hide all GUI elements on uninitialisation - this disable. // Hide all GUI elements on uninitialisation - this disable.
for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
(*i)->onHide(); (*it)->onHide();
InputManager::getInstance()->deinit(); InputManager::getInstance()->deinit();
ResourceManager::getInstance()->unloadAll(); ResourceManager::getInstance()->unloadAll();
@ -266,8 +266,14 @@ void Window::render()
} }
unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime"); unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime");
if (mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) // 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(); startScreenSaver();
}
// Always call the screensaver render function regardless of whether the screensaver is active // Always call the screensaver render function regardless of whether the screensaver is active
// or not because it may perform a fade on transition. // or not because it may perform a fade on transition.
@ -420,12 +426,30 @@ bool Window::isProcessing()
[](GuiComponent* c) { return c->isProcessing(); }) > 0; [](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() void Window::startScreenSaver()
{ {
if (mScreenSaver && !mRenderScreenSaver) { if (mScreenSaver && !mRenderScreenSaver) {
// Tell the GUI components the screensaver is starting. // Tell the GUI components the screensaver is starting.
for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
(*i)->onScreenSaverActivate(); (*it)->onScreenSaverActivate();
mScreenSaver->startScreenSaver(); mScreenSaver->startScreenSaver();
mRenderScreenSaver = true; mRenderScreenSaver = true;
@ -440,8 +464,8 @@ bool Window::cancelScreenSaver()
mScreenSaver->resetCounts(); mScreenSaver->resetCounts();
// Tell the GUI components the screensaver has stopped. // Tell the GUI components the screensaver has stopped.
for (auto i = mGuiStack.cbegin(); i != mGuiStack.cend(); i++) for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
(*i)->onScreenSaverDeactivate(); (*it)->onScreenSaverDeactivate();
return true; return true;
} }

View file

@ -86,6 +86,10 @@ public:
void renderScreenSaver(); void renderScreenSaver();
bool isScreenSaverActive() { return mRenderScreenSaver; }; bool isScreenSaverActive() { return mRenderScreenSaver; };
void setLaunchedGame();
void unsetLaunchedGame();
bool getGameLaunchedState() { return mGameLaunchedState; };
private: private:
void onSleep(); void onSleep();
void onWake(); void onWake();
@ -98,6 +102,7 @@ private:
ScreenSaver* mScreenSaver; ScreenSaver* mScreenSaver;
InfoPopup* mInfoPopup; InfoPopup* mInfoPopup;
bool mRenderScreenSaver; bool mRenderScreenSaver;
bool mGameLaunchedState;
std::vector<GuiComponent*> mGuiStack; std::vector<GuiComponent*> mGuiStack;

View file

@ -67,8 +67,10 @@ VideoComponent::VideoComponent(
mVideoWidth(0), mVideoWidth(0),
mStartDelayed(false), mStartDelayed(false),
mIsPlaying(false), mIsPlaying(false),
mPause(false),
mShowing(false), mShowing(false),
mScreensaverActive(false), mScreensaverActive(false),
mGameLaunched(false),
mDisable(false), mDisable(false),
mScreensaverMode(false), mScreensaverMode(false),
mTargetIsMax(false), mTargetIsMax(false),
@ -174,6 +176,9 @@ void VideoComponent::render(const Transform4x4f& parentTrans)
// Handle looping of the video. // Handle looping of the video.
handleLooping(); handleLooping();
// Pause video in case a game has been launched.
pauseVideo();
} }
void VideoComponent::renderSnapshot(const Transform4x4f& parentTrans) void VideoComponent::renderSnapshot(const Transform4x4f& parentTrans)
@ -253,6 +258,8 @@ void VideoComponent::handleLooping()
void VideoComponent::startVideoWithDelay() void VideoComponent::startVideoWithDelay()
{ {
mPause = false;
// If not playing then either start the video or initiate the delay. // If not playing then either start the video or initiate the delay.
if (!mIsPlaying) { if (!mIsPlaying) {
// Set the video that we are going to be playing so we don't attempt to restart it. // 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() 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. // is not active.
bool show = mShowing && !mScreensaverActive && !mDisable; bool show = mShowing && !mScreensaverActive && !mDisable;
@ -324,6 +331,12 @@ void VideoComponent::manageState()
if (show && !mVideoPath.empty()) if (show && !mVideoPath.empty())
startVideoWithDelay(); 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() void VideoComponent::onShow()
@ -350,6 +363,19 @@ void VideoComponent::onScreenSaverDeactivate()
manageState(); manageState();
} }
void VideoComponent::onGameLaunchedActivate()
{
mGameLaunched = true;
manageState();
}
void VideoComponent::onGameLaunchedDeactivate()
{
mGameLaunched = false;
stopVideo();
manageState();
}
void VideoComponent::topWindow(bool isTop) void VideoComponent::topWindow(bool isTop)
{ {
mDisable = !isTop; mDisable = !isTop;

View file

@ -48,6 +48,8 @@ public:
virtual void onHide() override; virtual void onHide() override;
virtual void onScreenSaverActivate() override; virtual void onScreenSaverActivate() override;
virtual void onScreenSaverDeactivate() override; virtual void onScreenSaverDeactivate() override;
virtual void onGameLaunchedActivate() override;
virtual void onGameLaunchedDeactivate() override;
virtual void topWindow(bool isTop) override; virtual void topWindow(bool isTop) override;
void onOriginChanged() override; void onOriginChanged() override;
@ -83,6 +85,8 @@ private:
virtual void startVideo() = 0; virtual void startVideo() = 0;
// Stop the video. // 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. // Handle looping the video. Must be called periodically.
virtual void handleLooping(); virtual void handleLooping();
@ -109,10 +113,12 @@ protected:
bool mStartDelayed; bool mStartDelayed;
unsigned mStartTime; unsigned mStartTime;
bool mIsPlaying; bool mIsPlaying;
bool mPause;
bool mShowing; bool mShowing;
bool mDisable; bool mDisable;
bool mScreensaverActive; bool mScreensaverActive;
bool mScreensaverMode; bool mScreensaverMode;
bool mGameLaunched;
bool mTargetIsMax; bool mTargetIsMax;
Configuration mConfig; Configuration mConfig;

View file

@ -231,13 +231,25 @@ void VideoVlcComponent::handleLooping()
(Settings::getInstance()->getBool("ScreenSaverVideoMute") && mScreensaverMode)) (Settings::getInstance()->getBool("ScreenSaverVideoMute") && mScreensaverMode))
libvlc_audio_set_mute(mMediaPlayer, 1); libvlc_audio_set_mute(mMediaPlayer, 1);
//libvlc_media_player_set_position(mMediaPlayer, 0.0f);
libvlc_media_player_set_media(mMediaPlayer, mMedia); libvlc_media_player_set_media(mMediaPlayer, mMedia);
libvlc_media_player_play(mMediaPlayer); 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() void VideoVlcComponent::startVideo()
{ {
if (!mIsPlaying) { if (!mIsPlaying) {
@ -336,6 +348,7 @@ void VideoVlcComponent::stopVideo()
{ {
mIsPlaying = false; mIsPlaying = false;
mStartDelayed = false; mStartDelayed = false;
mPause = false;
// Release the media player so it stops calling back to us. // Release the media player so it stops calling back to us.
if (mMediaPlayer) { if (mMediaPlayer) {
libvlc_media_player_stop(mMediaPlayer); libvlc_media_player_stop(mMediaPlayer);

View file

@ -57,10 +57,13 @@ private:
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize). // Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
// Used internally whenever the resizing parameters or texture change. // Used internally whenever the resizing parameters or texture change.
void resize(); void resize();
// Start the video immediately. // Start the video immediately.
virtual void startVideo() override; virtual void startVideo() override;
// Stop the video. // Stop the video.
virtual void stopVideo() override; 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. // Handle looping the video. Must be called periodically.
virtual void handleLooping() override; virtual void handleLooping() override;

View file

@ -104,12 +104,20 @@ namespace Renderer
unsigned int windowFlags; 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")) if (Settings::getInstance()->getBool("Windowed"))
windowFlags = getWindowFlags(); windowFlags = getWindowFlags();
else if (Settings::getInstance()->getString("FullscreenMode") == "borderless") else if (Settings::getInstance()->getString("FullscreenMode") == "borderless")
windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | getWindowFlags(); windowFlags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP | getWindowFlags();
else else
windowFlags = SDL_WINDOW_FULLSCREEN | getWindowFlags(); windowFlags = SDL_WINDOW_FULLSCREEN | getWindowFlags();
#endif
if ((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED, if ((sdlWindow = SDL_CreateWindow("EmulationStation", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr) { SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, windowFlags)) == nullptr) {