mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Merge pull request #153 from pjft/RetroPie-ScreenSaver-Merge
Adding Random Video Screensaver/Attract Mode, plus controls
This commit is contained in:
commit
2188efd2b6
|
@ -11,6 +11,7 @@ set(ES_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemScreenSaver.h
|
||||
|
||||
# GuiComponents
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.h
|
||||
|
@ -23,6 +24,7 @@ set(ES_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMetaDataEd.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScreensaverOptions.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMenu.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.h
|
||||
|
@ -60,6 +62,7 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemScreenSaver.cpp
|
||||
|
||||
# GuiComponents
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.cpp
|
||||
|
@ -71,6 +74,7 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMetaDataEd.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScreensaverOptions.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiMenu.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp
|
||||
|
|
318
es-app/src/SystemScreenSaver.cpp
Normal file
318
es-app/src/SystemScreenSaver.cpp
Normal file
|
@ -0,0 +1,318 @@
|
|||
#include "SystemScreenSaver.h"
|
||||
#ifdef _RPI_
|
||||
#include "components/VideoPlayerComponent.h"
|
||||
#endif
|
||||
#include "components/VideoVlcComponent.h"
|
||||
#include "platform.h"
|
||||
#include "Renderer.h"
|
||||
#include "Settings.h"
|
||||
#include "SystemData.h"
|
||||
#include "Util.h"
|
||||
#include "Log.h"
|
||||
#include "views/ViewController.h"
|
||||
#include "views/gamelist/IGameListView.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define FADE_TIME 300
|
||||
#define SWAP_VIDEO_TIMEOUT 30000
|
||||
|
||||
SystemScreenSaver::SystemScreenSaver(Window* window) :
|
||||
mVideoScreensaver(NULL),
|
||||
mWindow(window),
|
||||
mCounted(false),
|
||||
mVideoCount(0),
|
||||
mState(STATE_INACTIVE),
|
||||
mOpacity(0.0f),
|
||||
mTimer(0),
|
||||
mSystemName(""),
|
||||
mGameName(""),
|
||||
mCurrentGame(NULL)
|
||||
{
|
||||
mWindow->setScreenSaver(this);
|
||||
std::string path = getTitleFolder();
|
||||
if(!boost::filesystem::exists(path))
|
||||
boost::filesystem::create_directory(path);
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
SystemScreenSaver::~SystemScreenSaver()
|
||||
{
|
||||
// Delete subtitle file, if existing
|
||||
remove(getTitlePath().c_str());
|
||||
mCurrentGame = NULL;
|
||||
delete mVideoScreensaver;
|
||||
}
|
||||
|
||||
bool SystemScreenSaver::allowSleep()
|
||||
{
|
||||
//return false;
|
||||
return (mVideoScreensaver == NULL);
|
||||
}
|
||||
|
||||
bool SystemScreenSaver::isScreenSaverActive()
|
||||
{
|
||||
return (mState != STATE_INACTIVE);
|
||||
}
|
||||
|
||||
void SystemScreenSaver::startScreenSaver()
|
||||
{
|
||||
if (!mVideoScreensaver && (Settings::getInstance()->getString("ScreenSaverBehavior") == "random video"))
|
||||
{
|
||||
// Configure to fade out the windows
|
||||
mState = STATE_FADE_OUT_WINDOW;
|
||||
mOpacity = 0.0f;
|
||||
|
||||
// Load a random video
|
||||
std::string path = "";
|
||||
pickRandomVideo(path);
|
||||
|
||||
int retry = 200;
|
||||
while(retry > 0 && ((path.empty() || !boost::filesystem::exists(path)) || mCurrentGame == NULL))
|
||||
{
|
||||
retry--;
|
||||
pickRandomVideo(path);
|
||||
}
|
||||
|
||||
if (!path.empty() && boost::filesystem::exists(path))
|
||||
{
|
||||
// Create the correct type of video component
|
||||
|
||||
#ifdef _RPI_
|
||||
if (Settings::getInstance()->getBool("ScreenSaverOmxPlayer"))
|
||||
mVideoScreensaver = new VideoPlayerComponent(mWindow, getTitlePath());
|
||||
else
|
||||
mVideoScreensaver = new VideoVlcComponent(mWindow, getTitlePath());
|
||||
#else
|
||||
mVideoScreensaver = new VideoVlcComponent(mWindow, getTitlePath());
|
||||
#endif
|
||||
|
||||
mVideoScreensaver->setOrigin(0.5f, 0.5f);
|
||||
mVideoScreensaver->setPosition(Renderer::getScreenWidth()/2, Renderer::getScreenHeight()/2);
|
||||
|
||||
if (Settings::getInstance()->getBool("StretchVideoOnScreenSaver"))
|
||||
{
|
||||
mVideoScreensaver->setResize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
mVideoScreensaver->setMaxSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
}
|
||||
mVideoScreensaver->setVideo(path);
|
||||
mVideoScreensaver->setScreensaverMode(true);
|
||||
mVideoScreensaver->onShow();
|
||||
mTimer = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// No videos. Just use a standard screensaver
|
||||
mState = STATE_SCREENSAVER_ACTIVE;
|
||||
mCurrentGame = NULL;
|
||||
}
|
||||
|
||||
void SystemScreenSaver::stopScreenSaver()
|
||||
{
|
||||
delete mVideoScreensaver;
|
||||
mVideoScreensaver = NULL;
|
||||
mState = STATE_INACTIVE;
|
||||
}
|
||||
|
||||
void SystemScreenSaver::renderScreenSaver()
|
||||
{
|
||||
if (mVideoScreensaver && Settings::getInstance()->getString("ScreenSaverBehavior") == "random video")
|
||||
{
|
||||
// Render black background
|
||||
Renderer::setMatrix(Eigen::Affine3f::Identity());
|
||||
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), (unsigned char)(255));
|
||||
|
||||
// Only render the video if the state requires it
|
||||
if ((int)mState >= STATE_FADE_IN_VIDEO)
|
||||
{
|
||||
Eigen::Affine3f transform = Eigen::Affine3f::Identity();
|
||||
mVideoScreensaver->render(transform);
|
||||
}
|
||||
}
|
||||
else if (mState != STATE_INACTIVE)
|
||||
{
|
||||
Renderer::setMatrix(Eigen::Affine3f::Identity());
|
||||
unsigned char opacity = Settings::getInstance()->getString("ScreenSaverBehavior") == "dim" ? 0xA0 : 0xFF;
|
||||
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x00000000 | opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemScreenSaver::countVideos()
|
||||
{
|
||||
if (!mCounted)
|
||||
{
|
||||
mVideoCount = 0;
|
||||
mCounted = true;
|
||||
std::vector<SystemData*>:: iterator it;
|
||||
for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node root;
|
||||
std::string xmlReadPath = (*it)->getGamelistPath(false);
|
||||
|
||||
if(boost::filesystem::exists(xmlReadPath))
|
||||
{
|
||||
pugi::xml_parse_result result = doc.load_file(xmlReadPath.c_str());
|
||||
if (!result)
|
||||
continue;
|
||||
root = doc.child("gameList");
|
||||
if (!root)
|
||||
continue;
|
||||
for(pugi::xml_node fileNode = root.child("game"); fileNode; fileNode = fileNode.next_sibling("game"))
|
||||
{
|
||||
pugi::xml_node videoNode = fileNode.child("video");
|
||||
if (videoNode)
|
||||
++mVideoCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SystemScreenSaver::pickRandomVideo(std::string& path)
|
||||
{
|
||||
countVideos();
|
||||
mCurrentGame = NULL;
|
||||
if (mVideoCount > 0)
|
||||
{
|
||||
int video = (int)(((float)rand() / float(RAND_MAX)) * (float)mVideoCount);
|
||||
|
||||
std::vector<SystemData*>:: iterator it;
|
||||
for (it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); ++it)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_node root;
|
||||
std::string xmlReadPath = (*it)->getGamelistPath(false);
|
||||
|
||||
if(boost::filesystem::exists(xmlReadPath))
|
||||
{
|
||||
pugi::xml_parse_result result = doc.load_file(xmlReadPath.c_str());
|
||||
if (!result)
|
||||
continue;
|
||||
root = doc.child("gameList");
|
||||
if (!root)
|
||||
continue;
|
||||
for(pugi::xml_node fileNode = root.child("game"); fileNode; fileNode = fileNode.next_sibling("game"))
|
||||
{
|
||||
pugi::xml_node videoNode = fileNode.child("video");
|
||||
if (videoNode)
|
||||
{
|
||||
// See if this is the randomly selected video
|
||||
if (video-- == 0)
|
||||
{
|
||||
// Yes. Resolve to a full path
|
||||
path = resolvePath(videoNode.text().get(), (*it)->getStartPath(), true).generic_string();
|
||||
mSystemName = (*it)->getFullName();
|
||||
mGameName = fileNode.child("name").text().get();
|
||||
|
||||
// getting corresponding FileData
|
||||
|
||||
// try the easy way. Should work for the majority of cases, unless in subfolders
|
||||
FileData* rootFileData = (*it)->getRootFolder();
|
||||
std::string gamePath = resolvePath(fileNode.child("path").text().get(), (*it)->getStartPath(), false).string();
|
||||
|
||||
std::string shortPath = gamePath;
|
||||
shortPath = shortPath.replace(0, (*it)->getStartPath().length()+1, "");
|
||||
|
||||
const std::unordered_map<std::string, FileData*>& children = rootFileData->getChildrenByFilename();
|
||||
std::unordered_map<std::string, FileData*>::const_iterator screenSaverGame = children.find(shortPath);
|
||||
|
||||
if (screenSaverGame != children.end())
|
||||
{
|
||||
// Found the corresponding FileData
|
||||
mCurrentGame = screenSaverGame->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Couldn't find FileData. Going for the full iteration.
|
||||
// iterate on children
|
||||
FileType type = GAME;
|
||||
std::vector<FileData*> allFiles = rootFileData->getFilesRecursive(type);
|
||||
std::vector<FileData*>::iterator itf; // declare an iterator to a vector of strings
|
||||
|
||||
int i = 0;
|
||||
for(itf=allFiles.begin() ; itf < allFiles.end(); itf++,i++ ) {
|
||||
if ((*itf)->getPath() == gamePath)
|
||||
{
|
||||
mCurrentGame = (*itf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end of getting FileData
|
||||
if (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never")
|
||||
writeSubtitle(mGameName.c_str(), mSystemName.c_str(),
|
||||
(Settings::getInstance()->getString("ScreenSaverGameInfo") == "always"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SystemScreenSaver::update(int deltaTime)
|
||||
{
|
||||
// Use this to update the fade value for the current fade stage
|
||||
if (mState == STATE_FADE_OUT_WINDOW)
|
||||
{
|
||||
mOpacity += (float)deltaTime / FADE_TIME;
|
||||
if (mOpacity >= 1.0f)
|
||||
{
|
||||
mOpacity = 1.0f;
|
||||
|
||||
// Update to the next state
|
||||
mState = STATE_FADE_IN_VIDEO;
|
||||
}
|
||||
}
|
||||
else if (mState == STATE_FADE_IN_VIDEO)
|
||||
{
|
||||
mOpacity -= (float)deltaTime / FADE_TIME;
|
||||
if (mOpacity <= 0.0f)
|
||||
{
|
||||
mOpacity = 0.0f;
|
||||
// Update to the next state
|
||||
mState = STATE_SCREENSAVER_ACTIVE;
|
||||
}
|
||||
}
|
||||
else if (mState == STATE_SCREENSAVER_ACTIVE)
|
||||
{
|
||||
// Update the timer that swaps the videos
|
||||
mTimer += deltaTime;
|
||||
if (mTimer > SWAP_VIDEO_TIMEOUT)
|
||||
{
|
||||
nextVideo();
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a loaded video then update it
|
||||
if (mVideoScreensaver)
|
||||
mVideoScreensaver->update(deltaTime);
|
||||
}
|
||||
|
||||
void SystemScreenSaver::nextVideo() {
|
||||
stopScreenSaver();
|
||||
startScreenSaver();
|
||||
mState = STATE_SCREENSAVER_ACTIVE;
|
||||
}
|
||||
|
||||
FileData* SystemScreenSaver::getCurrentGame()
|
||||
{
|
||||
return mCurrentGame;
|
||||
}
|
||||
|
||||
void SystemScreenSaver::launchGame()
|
||||
{
|
||||
// launching Game
|
||||
ViewController::get()->goToGameList(mCurrentGame->getSystem());
|
||||
IGameListView* view = ViewController::get()->getGameListView(mCurrentGame->getSystem()).get();
|
||||
view->setCursor(mCurrentGame);
|
||||
if (Settings::getInstance()->getBool("ScreenSaverControls"))
|
||||
{
|
||||
view->launch(mCurrentGame);
|
||||
}
|
||||
}
|
49
es-app/src/SystemScreenSaver.h
Normal file
49
es-app/src/SystemScreenSaver.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "Window.h"
|
||||
|
||||
class VideoComponent;
|
||||
|
||||
// Screensaver implementation for main window
|
||||
class SystemScreenSaver : public Window::ScreenSaver
|
||||
{
|
||||
public:
|
||||
SystemScreenSaver(Window* window);
|
||||
virtual ~SystemScreenSaver();
|
||||
|
||||
virtual void startScreenSaver();
|
||||
virtual void stopScreenSaver();
|
||||
virtual void nextVideo();
|
||||
virtual void renderScreenSaver();
|
||||
virtual bool allowSleep();
|
||||
virtual void update(int deltaTime);
|
||||
virtual bool isScreenSaverActive();
|
||||
|
||||
virtual FileData* getCurrentGame();
|
||||
virtual void launchGame();
|
||||
|
||||
private:
|
||||
void countVideos();
|
||||
void pickRandomVideo(std::string& path);
|
||||
|
||||
void input(InputConfig* config, Input input);
|
||||
|
||||
enum STATE {
|
||||
STATE_INACTIVE,
|
||||
STATE_FADE_OUT_WINDOW,
|
||||
STATE_FADE_IN_VIDEO,
|
||||
STATE_SCREENSAVER_ACTIVE
|
||||
};
|
||||
|
||||
private:
|
||||
bool mCounted;
|
||||
unsigned long mVideoCount;
|
||||
VideoComponent* mVideoScreensaver;
|
||||
Window* mWindow;
|
||||
STATE mState;
|
||||
float mOpacity;
|
||||
int mTimer;
|
||||
FileData* mCurrentGame;
|
||||
std::string mGameName;
|
||||
std::string mSystemName;
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
#include "Settings.h"
|
||||
#include "guis/GuiMsgBox.h"
|
||||
#include "guis/GuiSettings.h"
|
||||
#include "guis/GuiScreensaverOptions.h"
|
||||
#include "guis/GuiScraperStart.h"
|
||||
#include "guis/GuiDetectDevice.h"
|
||||
#include "views/ViewController.h"
|
||||
|
@ -98,6 +99,30 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled);
|
||||
s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); });
|
||||
|
||||
auto video_audio = std::make_shared<SwitchComponent>(mWindow);
|
||||
video_audio->setState(Settings::getInstance()->getBool("VideoAudio"));
|
||||
s->addWithLabel("ENABLE VIDEO AUDIO", video_audio);
|
||||
s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); });
|
||||
|
||||
#ifdef _RPI_
|
||||
// OMX player Audio Device
|
||||
auto omx_audio_dev = std::make_shared< OptionListComponent<std::string> >(mWindow, "OMX PLAYER AUDIO DEVICE", false);
|
||||
std::vector<std::string> devices;
|
||||
devices.push_back("local");
|
||||
devices.push_back("hdmi");
|
||||
devices.push_back("both");
|
||||
// USB audio
|
||||
devices.push_back("alsa:hw:0,0");
|
||||
devices.push_back("alsa:hw:1,0");
|
||||
for (auto it = devices.begin(); it != devices.end(); it++)
|
||||
omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it);
|
||||
s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev);
|
||||
s->addSaveFunc([omx_audio_dev] {
|
||||
if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected())
|
||||
Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected());
|
||||
});
|
||||
#endif
|
||||
|
||||
mWindow->pushGui(s);
|
||||
});
|
||||
|
||||
|
@ -112,26 +137,32 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
s->addSaveFunc([screensaver_time] { Settings::getInstance()->setInt("ScreenSaverTime", (int)round(screensaver_time->getValue()) * (1000 * 60)); });
|
||||
|
||||
// screensaver behavior
|
||||
auto screensaver_behavior = std::make_shared< OptionListComponent<std::string> >(mWindow, "TRANSITION STYLE", false);
|
||||
auto screensaver_behavior = std::make_shared< OptionListComponent<std::string> >(mWindow, "SCREENSAVER BEHAVIOR", false);
|
||||
std::vector<std::string> screensavers;
|
||||
screensavers.push_back("dim");
|
||||
screensavers.push_back("black");
|
||||
screensavers.push_back("random video");
|
||||
for(auto it = screensavers.begin(); it != screensavers.end(); it++)
|
||||
screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it);
|
||||
s->addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior);
|
||||
s->addSaveFunc([screensaver_behavior] { Settings::getInstance()->setString("ScreenSaverBehavior", screensaver_behavior->getSelected()); });
|
||||
s->addSaveFunc([this, screensaver_behavior] {
|
||||
if (Settings::getInstance()->getString("ScreenSaverBehavior") != "random video" && screensaver_behavior->getSelected() == "random video") {
|
||||
// if before it wasn't risky but now there's a risk of problems, show warning
|
||||
mWindow->pushGui(new GuiMsgBox(mWindow,
|
||||
"The \"Random Video\" screensaver shows videos from your gamelist.\n\nIf you do not have videos, or if in several consecutive attempts the games it selects don't have videos it will default to black.\n\nMore options in the \"UI Settings\" > \"Video Screensaver\" menu.",
|
||||
"OK", [] { return; }));
|
||||
}
|
||||
Settings::getInstance()->setString("ScreenSaverBehavior", screensaver_behavior->getSelected());
|
||||
});
|
||||
|
||||
// framerate
|
||||
auto framerate = std::make_shared<SwitchComponent>(mWindow);
|
||||
framerate->setState(Settings::getInstance()->getBool("DrawFramerate"));
|
||||
s->addWithLabel("SHOW FRAMERATE", framerate);
|
||||
s->addSaveFunc([framerate] { Settings::getInstance()->setBool("DrawFramerate", framerate->getState()); });
|
||||
ComponentListRow row;
|
||||
|
||||
// show help
|
||||
auto show_help = std::make_shared<SwitchComponent>(mWindow);
|
||||
show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
|
||||
s->addWithLabel("ON-SCREEN HELP", show_help);
|
||||
s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); });
|
||||
// show filtered menu
|
||||
row.elements.clear();
|
||||
row.addElement(std::make_shared<TextComponent>(mWindow, "VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
|
||||
row.addElement(makeArrow(mWindow), false);
|
||||
row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
|
||||
s->addRow(row);
|
||||
|
||||
// quick system select (left/right in game list view)
|
||||
auto quick_sys_select = std::make_shared<SwitchComponent>(mWindow);
|
||||
|
@ -197,52 +228,12 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
if (needReload)
|
||||
ViewController::get()->reloadAll();
|
||||
});
|
||||
mWindow->pushGui(s);
|
||||
});
|
||||
|
||||
addEntry("VIDEO PLAYER SETTINGS", 0x777777FF, true,
|
||||
[this] {
|
||||
auto s = new GuiSettings(mWindow, "VIDEO PLAYER SETTINGS");
|
||||
|
||||
#ifdef _RPI_
|
||||
// Video Player - VideoOmxPlayer
|
||||
auto omx_player = std::make_shared<SwitchComponent>(mWindow);
|
||||
omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer"));
|
||||
s->addWithLabel("USE OMX VIDEO PLAYER (HW ACCELERATED)", omx_player);
|
||||
s->addSaveFunc([omx_player]
|
||||
{
|
||||
// need to reload all views to re-create the right video components
|
||||
bool needReload = false;
|
||||
if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState())
|
||||
needReload = true;
|
||||
|
||||
Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState());
|
||||
|
||||
if(needReload)
|
||||
ViewController::get()->reloadAll();
|
||||
});
|
||||
|
||||
// OMX player Audio Device
|
||||
auto omx_audio_dev = std::make_shared< OptionListComponent<std::string> >(mWindow, "OMX PLAYER AUDIO DEVICE", false);
|
||||
std::vector<std::string> devices;
|
||||
devices.push_back("local");
|
||||
devices.push_back("hdmi");
|
||||
devices.push_back("both");
|
||||
// USB audio
|
||||
devices.push_back("alsa:hw:0,0");
|
||||
devices.push_back("alsa:hw:1,0");
|
||||
for (auto it = devices.begin(); it != devices.end(); it++)
|
||||
omx_audio_dev->add(*it, *it, Settings::getInstance()->getString("OMXAudioDev") == *it);
|
||||
s->addWithLabel("OMX PLAYER AUDIO DEVICE", omx_audio_dev);
|
||||
s->addSaveFunc([omx_audio_dev] {
|
||||
if (Settings::getInstance()->getString("OMXAudioDev") != omx_audio_dev->getSelected())
|
||||
Settings::getInstance()->setString("OMXAudioDev", omx_audio_dev->getSelected());
|
||||
});
|
||||
#endif
|
||||
auto video_audio = std::make_shared<SwitchComponent>(mWindow);
|
||||
video_audio->setState(Settings::getInstance()->getBool("VideoAudio"));
|
||||
s->addWithLabel("ENABLE VIDEO AUDIO", video_audio);
|
||||
s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); });
|
||||
// show help
|
||||
auto show_help = std::make_shared<SwitchComponent>(mWindow);
|
||||
show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
|
||||
s->addWithLabel("ON-SCREEN HELP", show_help);
|
||||
s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); });
|
||||
|
||||
mWindow->pushGui(s);
|
||||
});
|
||||
|
@ -262,12 +253,39 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
s->addWithLabel("PARSE GAMESLISTS ONLY", parse_gamelists);
|
||||
s->addSaveFunc([parse_gamelists] { Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelists->getState()); });
|
||||
|
||||
#ifdef _RPI_
|
||||
// Video Player - VideoOmxPlayer
|
||||
auto omx_player = std::make_shared<SwitchComponent>(mWindow);
|
||||
omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer"));
|
||||
s->addWithLabel("USE OMX PLAYER (HW ACCELERATED)", omx_player);
|
||||
s->addSaveFunc([omx_player]
|
||||
{
|
||||
// need to reload all views to re-create the right video components
|
||||
bool needReload = false;
|
||||
if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState())
|
||||
needReload = true;
|
||||
|
||||
Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState());
|
||||
|
||||
if(needReload)
|
||||
ViewController::get()->reloadAll();
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
// maximum vram
|
||||
auto max_vram = std::make_shared<SliderComponent>(mWindow, 0.f, 1000.f, 10.f, "Mb");
|
||||
max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM")));
|
||||
s->addWithLabel("VRAM LIMIT", max_vram);
|
||||
s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)round(max_vram->getValue())); });
|
||||
|
||||
// framerate
|
||||
auto framerate = std::make_shared<SwitchComponent>(mWindow);
|
||||
framerate->setState(Settings::getInstance()->getBool("DrawFramerate"));
|
||||
s->addWithLabel("SHOW FRAMERATE", framerate);
|
||||
s->addSaveFunc([framerate] { Settings::getInstance()->setBool("DrawFramerate", framerate->getState()); });
|
||||
|
||||
|
||||
mWindow->pushGui(s);
|
||||
});
|
||||
|
||||
|
@ -350,6 +368,11 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, Renderer::getScreenHeight() * 0.15f);
|
||||
}
|
||||
|
||||
void GuiMenu::openScreensaverOptions() {
|
||||
GuiScreensaverOptions* ggf = new GuiScreensaverOptions(mWindow, "VIDEO SCREENSAVER");
|
||||
mWindow->pushGui(ggf);
|
||||
}
|
||||
|
||||
void GuiMenu::onSizeChanged()
|
||||
{
|
||||
mVersion.setSize(mSize.x(), 0);
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
|
||||
private:
|
||||
void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func);
|
||||
|
||||
void openScreensaverOptions();
|
||||
MenuComponent mMenu;
|
||||
TextComponent mVersion;
|
||||
};
|
||||
|
|
125
es-app/src/guis/GuiScreensaverOptions.cpp
Normal file
125
es-app/src/guis/GuiScreensaverOptions.cpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include "guis/GuiScreensaverOptions.h"
|
||||
#include "Window.h"
|
||||
#include "Settings.h"
|
||||
#include "views/ViewController.h"
|
||||
|
||||
#include "components/ButtonComponent.h"
|
||||
#include "components/SwitchComponent.h"
|
||||
#include "components/SliderComponent.h"
|
||||
#include "components/TextComponent.h"
|
||||
#include "components/OptionListComponent.h"
|
||||
#include "components/MenuComponent.h"
|
||||
#include "guis/GuiMsgBox.h"
|
||||
|
||||
GuiScreensaverOptions::GuiScreensaverOptions(Window* window, const char* title) : GuiComponent(window), mMenu(window, title)
|
||||
{
|
||||
addChild(&mMenu);
|
||||
|
||||
#ifdef _RPI_
|
||||
auto ss_omx = std::make_shared<SwitchComponent>(mWindow);
|
||||
ss_omx->setState(Settings::getInstance()->getBool("ScreenSaverOmxPlayer"));
|
||||
addWithLabel("USE OMX PLAYER FOR SCREENSAVER", ss_omx);
|
||||
addSaveFunc([ss_omx, this] { Settings::getInstance()->setBool("ScreenSaverOmxPlayer", ss_omx->getState()); });
|
||||
#endif
|
||||
|
||||
// Allow ScreenSaver Controls - ScreenSaverControls
|
||||
auto ss_controls = std::make_shared<SwitchComponent>(mWindow);
|
||||
ss_controls->setState(Settings::getInstance()->getBool("ScreenSaverControls"));
|
||||
addWithLabel("SCREENSAVER CONTROLS", ss_controls);
|
||||
addSaveFunc([ss_controls] { Settings::getInstance()->setBool("ScreenSaverControls", ss_controls->getState()); });
|
||||
|
||||
// Render Video Game Name as subtitles
|
||||
auto ss_info = std::make_shared< OptionListComponent<std::string> >(mWindow, "SHOW GAME INFO", false);
|
||||
std::vector<std::string> info_type;
|
||||
info_type.push_back("always");
|
||||
info_type.push_back("start & end");
|
||||
info_type.push_back("never");
|
||||
for(auto it = info_type.begin(); it != info_type.end(); it++)
|
||||
ss_info->add(*it, *it, Settings::getInstance()->getString("ScreenSaverGameInfo") == *it);
|
||||
addWithLabel("SHOW GAME INFO ON SCREENSAVER", ss_info);
|
||||
addSaveFunc([ss_info, this] { Settings::getInstance()->setString("ScreenSaverGameInfo", ss_info->getSelected()); });
|
||||
|
||||
#ifndef _RPI_
|
||||
auto captions_compatibility = std::make_shared<SwitchComponent>(mWindow);
|
||||
captions_compatibility->setState(Settings::getInstance()->getBool("CaptionsCompatibility"));
|
||||
addWithLabel("USE COMPATIBLE LOW RESOLUTION FOR CAPTIONS", captions_compatibility);
|
||||
addSaveFunc([captions_compatibility] { Settings::getInstance()->setBool("CaptionsCompatibility", captions_compatibility->getState()); });
|
||||
#endif
|
||||
|
||||
auto stretch_screensaver = std::make_shared<SwitchComponent>(mWindow);
|
||||
stretch_screensaver->setState(Settings::getInstance()->getBool("StretchVideoOnScreenSaver"));
|
||||
addWithLabel("STRETCH VIDEO ON SCREENSAVER", stretch_screensaver);
|
||||
addSaveFunc([stretch_screensaver] { Settings::getInstance()->setBool("StretchVideoOnScreenSaver", stretch_screensaver->getState()); });
|
||||
|
||||
mMenu.addButton("BACK", "go back", [this] { delete this; });
|
||||
|
||||
setSize((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
mMenu.setPosition((mSize.x() - mMenu.getSize().x()) / 2, Renderer::getScreenHeight() * 0.15f);
|
||||
}
|
||||
|
||||
GuiScreensaverOptions::~GuiScreensaverOptions()
|
||||
{
|
||||
save();
|
||||
}
|
||||
|
||||
void GuiScreensaverOptions::save()
|
||||
{
|
||||
if(!mSaveFuncs.size())
|
||||
return;
|
||||
|
||||
#ifdef _RPI_
|
||||
bool startingStatusNotRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") == "never" || !Settings::getInstance()->getBool("ScreenSaverOmxPlayer"));
|
||||
#endif
|
||||
|
||||
for(auto it = mSaveFuncs.begin(); it != mSaveFuncs.end(); it++)
|
||||
(*it)();
|
||||
|
||||
Settings::getInstance()->saveFile();
|
||||
|
||||
#ifdef _RPI_
|
||||
bool endStatusRisky = (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never" && Settings::getInstance()->getBool("ScreenSaverOmxPlayer"));
|
||||
if (startingStatusNotRisky && endStatusRisky) {
|
||||
// if before it wasn't risky but now there's a risk of problems, show warning
|
||||
mWindow->pushGui(new GuiMsgBox(mWindow,
|
||||
"Using OMX Player and displaying Game Info may result in the video flickering in some TV modes. If that happens, consider:\n\n• Disabling the \"Show Game Info\" option;\n• Disabling \"Overscan\" on the Pi configuration menu might help:\nRetroPie > Raspi-Config > Advanced Options > Overscan > \"No\".\n• Disabling the use of OMX Player for the screensaver.",
|
||||
"GOT IT!", [] { return; }));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GuiScreensaverOptions::input(InputConfig* config, Input input)
|
||||
{
|
||||
if(config->isMappedTo("b", input) && input.value != 0)
|
||||
{
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(config->isMappedTo("start", input) && input.value != 0)
|
||||
{
|
||||
// close everything
|
||||
Window* window = mWindow;
|
||||
while(window->peekGui() && window->peekGui() != ViewController::get())
|
||||
delete window->peekGui();
|
||||
return true;
|
||||
}
|
||||
|
||||
return GuiComponent::input(config, input);
|
||||
}
|
||||
|
||||
HelpStyle GuiScreensaverOptions::getHelpStyle()
|
||||
{
|
||||
HelpStyle style = HelpStyle();
|
||||
style.applyTheme(ViewController::get()->getState().getSystem()->getTheme(), "system");
|
||||
return style;
|
||||
}
|
||||
|
||||
std::vector<HelpPrompt> GuiScreensaverOptions::getHelpPrompts()
|
||||
{
|
||||
std::vector<HelpPrompt> prompts = mMenu.getHelpPrompts();
|
||||
|
||||
prompts.push_back(HelpPrompt("b", "back"));
|
||||
prompts.push_back(HelpPrompt("start", "close"));
|
||||
|
||||
return prompts;
|
||||
}
|
24
es-app/src/guis/GuiScreensaverOptions.h
Normal file
24
es-app/src/guis/GuiScreensaverOptions.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "GuiComponent.h"
|
||||
#include "components/MenuComponent.h"
|
||||
#include "SystemData.h"
|
||||
|
||||
// This is just a really simple template for a GUI that calls some save functions when closed.
|
||||
class GuiScreensaverOptions : public GuiComponent
|
||||
{
|
||||
public:
|
||||
GuiScreensaverOptions(Window* window, const char* title);
|
||||
virtual ~GuiScreensaverOptions(); // just calls save();
|
||||
|
||||
void save();
|
||||
inline void addRow(const ComponentListRow& row) { mMenu.addRow(row); };
|
||||
inline void addWithLabel(const std::string& label, const std::shared_ptr<GuiComponent>& comp) { mMenu.addWithLabel(label, comp); };
|
||||
inline void addSaveFunc(const std::function<void()>& func) { mSaveFuncs.push_back(func); };
|
||||
|
||||
bool input(InputConfig* config, Input input) override;
|
||||
std::vector<HelpPrompt> getHelpPrompts() override;
|
||||
HelpStyle getHelpStyle() override;
|
||||
|
||||
private:
|
||||
MenuComponent mMenu;
|
||||
std::vector< std::function<void()> > mSaveFuncs;
|
||||
};
|
|
@ -14,6 +14,7 @@
|
|||
#include "platform.h"
|
||||
#include "Log.h"
|
||||
#include "Window.h"
|
||||
#include "SystemScreenSaver.h"
|
||||
#include "EmulationStation.h"
|
||||
#include "Settings.h"
|
||||
#include "ScraperCmdLine.h"
|
||||
|
@ -222,6 +223,7 @@ int main(int argc, char* argv[])
|
|||
atexit(&onExit);
|
||||
|
||||
Window window;
|
||||
SystemScreenSaver screensaver(&window);
|
||||
ViewController::init(&window);
|
||||
window.pushGui(ViewController::get());
|
||||
|
||||
|
|
|
@ -158,6 +158,12 @@ bool SystemView::input(InputConfig* config, Input input)
|
|||
config->isMappedTo("up", input) ||
|
||||
config->isMappedTo("down", input))
|
||||
listInput(0);
|
||||
if(config->isMappedTo("select", input) && Settings::getInstance()->getBool("ScreenSaverControls"))
|
||||
{
|
||||
mWindow->startScreenSaver();
|
||||
mWindow->renderScreenSaver();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return GuiComponent::input(config, input);
|
||||
|
@ -348,6 +354,10 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
|
|||
prompts.push_back(HelpPrompt("left/right", "choose"));
|
||||
prompts.push_back(HelpPrompt("a", "select"));
|
||||
prompts.push_back(HelpPrompt("x", "random"));
|
||||
|
||||
if (Settings::getInstance()->getBool("ScreenSaverControls"))
|
||||
prompts.push_back(HelpPrompt("select", "launch screensaver"));
|
||||
|
||||
return prompts;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,10 @@ public:
|
|||
virtual const char* getName() const override { return "basic"; }
|
||||
|
||||
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||
virtual void launch(FileData* game) override;
|
||||
virtual void remove(FileData* game) override;
|
||||
|
||||
TextListComponent<FileData*> mList;
|
||||
|
|
|
@ -14,7 +14,6 @@ public:
|
|||
|
||||
virtual const char* getName() const override { return "detailed"; }
|
||||
|
||||
protected:
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -20,10 +20,10 @@ public:
|
|||
virtual const char* getName() const override { return "grid"; }
|
||||
|
||||
virtual std::vector<HelpPrompt> getHelpPrompts() override;
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) override;
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
ImageGridComponent<FileData*> mGrid;
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
virtual void remove(FileData* game) = 0;
|
||||
|
||||
virtual const char* getName() const = 0;
|
||||
virtual void launch(FileData* game) = 0;
|
||||
|
||||
virtual HelpStyle getHelpStyle() override;
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@ public:
|
|||
virtual void setCursor(FileData*) = 0;
|
||||
|
||||
virtual bool input(InputConfig* config, Input input) override;
|
||||
virtual void launch(FileData* game) = 0;
|
||||
|
||||
protected:
|
||||
virtual void populateList(const std::vector<FileData*>& files) = 0;
|
||||
virtual void launch(FileData* game) = 0;
|
||||
|
||||
TextComponent mHeaderText;
|
||||
ImageComponent mHeaderImage;
|
||||
|
|
|
@ -29,11 +29,11 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
|||
// Create the correct type of video window
|
||||
#ifdef _RPI_
|
||||
if (Settings::getInstance()->getBool("VideoOmxPlayer"))
|
||||
mVideo = new VideoPlayerComponent(window);
|
||||
mVideo = new VideoPlayerComponent(window, "");
|
||||
else
|
||||
mVideo = new VideoVlcComponent(window);
|
||||
mVideo = new VideoVlcComponent(window, getTitlePath());
|
||||
#else
|
||||
mVideo = new VideoVlcComponent(window);
|
||||
mVideo = new VideoVlcComponent(window, getTitlePath());
|
||||
#endif
|
||||
|
||||
mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y());
|
||||
|
@ -227,6 +227,8 @@ void VideoGameListView::updateInfoPanel()
|
|||
{
|
||||
FileData* file = (mList.size() == 0 || mList.isScrolling()) ? NULL : mList.getSelected();
|
||||
|
||||
boost::filesystem::remove(getTitlePath().c_str());
|
||||
|
||||
bool fadingOut;
|
||||
if(file == NULL)
|
||||
{
|
||||
|
|
|
@ -17,10 +17,9 @@ public:
|
|||
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
|
||||
|
||||
virtual const char* getName() const override { return "video"; }
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
protected:
|
||||
virtual void launch(FileData* game) override;
|
||||
|
||||
virtual void update(int deltaTime) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -87,6 +87,7 @@ public:
|
|||
|
||||
virtual void onShow();
|
||||
virtual void onHide();
|
||||
|
||||
virtual void onScreenSaverActivate();
|
||||
virtual void onScreenSaverDeactivate();
|
||||
virtual void topWindow(bool isTop);
|
||||
|
|
|
@ -77,10 +77,22 @@ void Settings::setDefaults()
|
|||
mStringMap["Scraper"] = "TheGamesDB";
|
||||
mStringMap["GamelistViewStyle"] = "automatic";
|
||||
|
||||
mBoolMap["ScreenSaverControls"] = true;
|
||||
mStringMap["ScreenSaverGameInfo"] = "never";
|
||||
mBoolMap["StretchVideoOnScreenSaver"] = false;
|
||||
|
||||
// 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
|
||||
mBoolMap["VideoOmxPlayer"] = false;
|
||||
#ifdef _RPI_
|
||||
// we're defaulting to OMX Player for full screen video on the Pi
|
||||
mBoolMap["ScreenSaverOmxPlayer"] = true;
|
||||
#else
|
||||
mBoolMap["ScreenSaverOmxPlayer"] = false;
|
||||
#endif
|
||||
|
||||
mBoolMap["VideoAudio"] = true;
|
||||
mBoolMap["CaptionsCompatibility"] = true;
|
||||
// Audio out device for Video playback using OMX player.
|
||||
mStringMap["OMXAudioDev"] = "both";
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "components/ImageComponent.h"
|
||||
|
||||
Window::Window() : mNormalizeNextUpdate(false), mFrameTimeElapsed(0), mFrameCountElapsed(0), mAverageDeltaTime(10),
|
||||
mAllowSleep(true), mSleeping(false), mTimeSinceLastInput(0)
|
||||
mAllowSleep(true), mSleeping(false), mTimeSinceLastInput(0), mScreenSaver(NULL), mRenderScreenSaver(false)
|
||||
{
|
||||
mHelp = new HelpComponent(this);
|
||||
mBackgroundOverlay = new ImageComponent(this);
|
||||
|
@ -115,26 +115,48 @@ void Window::textInput(const char* text)
|
|||
|
||||
void Window::input(InputConfig* config, Input input)
|
||||
{
|
||||
if (mRenderScreenSaver)
|
||||
{
|
||||
mRenderScreenSaver = false;
|
||||
|
||||
// Tell the GUI components the screensaver has stopped
|
||||
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
|
||||
(*i)->onScreenSaverDeactivate();
|
||||
if (mScreenSaver) {
|
||||
if(mScreenSaver->isScreenSaverActive() && Settings::getInstance()->getBool("ScreenSaverControls") &&
|
||||
(Settings::getInstance()->getString("ScreenSaverBehavior") == "random video"))
|
||||
{
|
||||
if(mScreenSaver->getCurrentGame() != NULL && (config->isMappedTo("right", input) || config->isMappedTo("start", input) || config->isMappedTo("select", input)))
|
||||
{
|
||||
if(config->isMappedTo("right", input) || config->isMappedTo("select", input))
|
||||
{
|
||||
if (input.value != 0) {
|
||||
// handle screensaver control
|
||||
mScreenSaver->nextVideo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(config->isMappedTo("start", input))
|
||||
{
|
||||
// launch game!
|
||||
cancelScreenSaver();
|
||||
mScreenSaver->launchGame();
|
||||
// to force handling the wake up process
|
||||
mSleeping = true;
|
||||
}
|
||||
}
|
||||
else if(input.value != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mSleeping)
|
||||
{
|
||||
// wake up
|
||||
mTimeSinceLastInput = 0;
|
||||
|
||||
cancelScreenSaver();
|
||||
mSleeping = false;
|
||||
onWake();
|
||||
return;
|
||||
}
|
||||
|
||||
mTimeSinceLastInput = 0;
|
||||
cancelScreenSaver();
|
||||
|
||||
if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug"))
|
||||
{
|
||||
|
@ -194,6 +216,10 @@ void Window::update(int deltaTime)
|
|||
|
||||
if(peekGui())
|
||||
peekGui()->update(deltaTime);
|
||||
|
||||
// Update the screensaver
|
||||
if (mScreenSaver)
|
||||
mScreenSaver->update(deltaTime);
|
||||
}
|
||||
|
||||
void Window::render()
|
||||
|
@ -226,18 +252,16 @@ void Window::render()
|
|||
}
|
||||
|
||||
unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime");
|
||||
if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0)
|
||||
startScreenSaver();
|
||||
|
||||
// Always call the screensaver render function regardless of whether the screensaver is active
|
||||
// or not because it may perform a fade on transition
|
||||
renderScreenSaver();
|
||||
|
||||
if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0)
|
||||
{
|
||||
if (!mRenderScreenSaver)
|
||||
{
|
||||
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
|
||||
(*i)->onScreenSaverActivate();
|
||||
mRenderScreenSaver = true;
|
||||
}
|
||||
|
||||
renderScreenSaver();
|
||||
|
||||
if (!isProcessing() && mAllowSleep)
|
||||
if (!isProcessing() && mAllowSleep && (!mScreenSaver || mScreenSaver->allowSleep()))
|
||||
{
|
||||
// go to sleep
|
||||
mSleeping = true;
|
||||
|
@ -374,9 +398,35 @@ bool Window::isProcessing()
|
|||
return count_if(mGuiStack.begin(), mGuiStack.end(), [](GuiComponent* c) { return c->isProcessing(); }) > 0;
|
||||
}
|
||||
|
||||
void Window::renderScreenSaver()
|
||||
{
|
||||
Renderer::setMatrix(Eigen::Affine3f::Identity());
|
||||
unsigned char opacity = Settings::getInstance()->getString("ScreenSaverBehavior") == "dim" ? 0xA0 : 0xFF;
|
||||
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x00000000 | opacity);
|
||||
}
|
||||
void Window::startScreenSaver()
|
||||
{
|
||||
if (mScreenSaver && !mRenderScreenSaver)
|
||||
{
|
||||
// Tell the GUI components the screensaver is starting
|
||||
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
|
||||
(*i)->onScreenSaverActivate();
|
||||
|
||||
mScreenSaver->startScreenSaver();
|
||||
mRenderScreenSaver = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::cancelScreenSaver()
|
||||
{
|
||||
if (mScreenSaver && mRenderScreenSaver)
|
||||
{
|
||||
mScreenSaver->stopScreenSaver();
|
||||
mRenderScreenSaver = false;
|
||||
|
||||
// Tell the GUI components the screensaver has stopped
|
||||
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
|
||||
(*i)->onScreenSaverDeactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::renderScreenSaver()
|
||||
{
|
||||
if (mScreenSaver)
|
||||
mScreenSaver->renderScreenSaver();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,26 @@
|
|||
#include "resources/Font.h"
|
||||
#include "InputManager.h"
|
||||
|
||||
class FileData;
|
||||
class HelpComponent;
|
||||
class ImageComponent;
|
||||
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
class ScreenSaver {
|
||||
public:
|
||||
virtual void startScreenSaver() = 0;
|
||||
virtual void stopScreenSaver() = 0;
|
||||
virtual void nextVideo() = 0;
|
||||
virtual void renderScreenSaver() = 0;
|
||||
virtual bool allowSleep() = 0;
|
||||
virtual void update(int deltaTime) = 0;
|
||||
virtual bool isScreenSaverActive() = 0;
|
||||
virtual FileData* getCurrentGame() = 0;
|
||||
virtual void launchGame() = 0;
|
||||
};
|
||||
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
|
@ -38,16 +52,23 @@ public:
|
|||
void renderHelpPromptsEarly(); // used to render HelpPrompts before a fade
|
||||
void setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpStyle& style);
|
||||
|
||||
void setScreenSaver(ScreenSaver* screenSaver) { mScreenSaver = screenSaver; }
|
||||
|
||||
void startScreenSaver();
|
||||
void cancelScreenSaver();
|
||||
void renderScreenSaver();
|
||||
|
||||
private:
|
||||
void onSleep();
|
||||
void onWake();
|
||||
|
||||
// Returns true if at least one component on the stack is processing
|
||||
bool isProcessing();
|
||||
void renderScreenSaver();
|
||||
|
||||
|
||||
HelpComponent* mHelp;
|
||||
ImageComponent* mBackgroundOverlay;
|
||||
ScreenSaver* mScreenSaver;
|
||||
bool mRenderScreenSaver;
|
||||
|
||||
std::vector<GuiComponent*> mGuiStack;
|
||||
|
||||
|
@ -56,7 +77,6 @@ private:
|
|||
int mFrameTimeElapsed;
|
||||
int mFrameCountElapsed;
|
||||
int mAverageDeltaTime;
|
||||
bool mRenderScreenSaver;
|
||||
|
||||
std::unique_ptr<TextCache> mFrameDataText;
|
||||
|
||||
|
|
|
@ -9,6 +9,45 @@
|
|||
|
||||
#define FADE_TIME_MS 200
|
||||
|
||||
std::string getTitlePath() {
|
||||
std::string titleFolder = getTitleFolder();
|
||||
return titleFolder + "last_title.srt";
|
||||
}
|
||||
|
||||
std::string getTitleFolder() {
|
||||
std::string home = getHomePath();
|
||||
return home + "/.emulationstation/tmp/";
|
||||
}
|
||||
|
||||
void writeSubtitle(const char* gameName, const char* systemName, bool always)
|
||||
{
|
||||
FILE* file = fopen(getTitlePath().c_str(), "w");
|
||||
if (always) {
|
||||
fprintf(file, "1\n00:00:01,000 --> 00:00:30,000\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "1\n00:00:01,000 --> 00:00:08,000\n");
|
||||
}
|
||||
fprintf(file, "%s\n", gameName);
|
||||
fprintf(file, "<i>%s</i>\n\n", systemName);
|
||||
|
||||
if (!always) {
|
||||
fprintf(file, "2\n00:00:26,000 --> 00:00:30,000\n");
|
||||
fprintf(file, "%s\n", gameName);
|
||||
fprintf(file, "<i>%s</i>\n", systemName);
|
||||
}
|
||||
|
||||
fflush(file);
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
void VideoComponent::setScreensaverMode(bool isScreensaver)
|
||||
{
|
||||
mScreensaverMode = isScreensaver;
|
||||
}
|
||||
|
||||
VideoComponent::VideoComponent(Window* window) :
|
||||
GuiComponent(window),
|
||||
mStaticImage(window),
|
||||
|
@ -19,6 +58,7 @@ VideoComponent::VideoComponent(Window* window) :
|
|||
mShowing(false),
|
||||
mScreensaverActive(false),
|
||||
mDisable(false),
|
||||
mScreensaverMode(false),
|
||||
mTargetIsMax(false),
|
||||
mOrigin(0, 0),
|
||||
mTargetSize(0, 0)
|
||||
|
@ -31,12 +71,17 @@ VideoComponent::VideoComponent(Window* window) :
|
|||
topWindow(false);
|
||||
}
|
||||
|
||||
std::string path = getTitleFolder();
|
||||
if(!boost::filesystem::exists(path))
|
||||
boost::filesystem::create_directory(path);
|
||||
}
|
||||
|
||||
VideoComponent::~VideoComponent()
|
||||
{
|
||||
// Stop any currently running video
|
||||
stopVideo();
|
||||
// Delete subtitle file, if existing
|
||||
remove(getTitlePath().c_str());
|
||||
}
|
||||
|
||||
void VideoComponent::setOrigin(float originX, float originY)
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include <SDL_mutex.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
std::string getTitlePath();
|
||||
std::string getTitleFolder();
|
||||
void writeSubtitle(const char* gameName, const char* systemName, bool always);
|
||||
|
||||
class VideoComponent : public GuiComponent
|
||||
{
|
||||
// Structure that groups together the configuration of the video component
|
||||
|
@ -35,6 +39,9 @@ public:
|
|||
// Configures the component to show the default video
|
||||
void setDefaultVideo();
|
||||
|
||||
// sets whether it's going to render in screensaver mode
|
||||
void setScreensaverMode(bool isScreensaver);
|
||||
|
||||
virtual void onShow() override;
|
||||
virtual void onHide() override;
|
||||
virtual void onScreenSaverActivate() override;
|
||||
|
@ -107,6 +114,7 @@ protected:
|
|||
bool mShowing;
|
||||
bool mDisable;
|
||||
bool mScreensaverActive;
|
||||
bool mScreensaverMode;
|
||||
bool mTargetIsMax;
|
||||
|
||||
Configuration mConfig;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifdef _RPI_
|
||||
#include "components/VideoPlayerComponent.h"
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "AudioManager.h"
|
||||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
|
@ -11,14 +12,16 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
VideoPlayerComponent::VideoPlayerComponent(Window* window) :
|
||||
VideoPlayerComponent::VideoPlayerComponent(Window* window, std::string path) :
|
||||
VideoComponent(window),
|
||||
mPlayerPid(-1)
|
||||
mPlayerPid(-1),
|
||||
subtitlePath(path)
|
||||
{
|
||||
}
|
||||
|
||||
VideoPlayerComponent::~VideoPlayerComponent()
|
||||
{
|
||||
stopVideo();
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
|
@ -46,7 +49,8 @@ void VideoPlayerComponent::setMaxSize(float width, float height)
|
|||
|
||||
void VideoPlayerComponent::startVideo()
|
||||
{
|
||||
if (!mIsPlaying) {
|
||||
if (!mIsPlaying)
|
||||
{
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
|
||||
|
@ -58,8 +62,11 @@ void VideoPlayerComponent::startVideo()
|
|||
// Set the video that we are going to be playing so we don't attempt to restart it
|
||||
mPlayingVideoPath = mVideoPath;
|
||||
|
||||
// Disable AudioManager so video can play
|
||||
AudioManager::getInstance()->deinit();
|
||||
// Disable AudioManager so video can play, in case we're requesting ALSA
|
||||
if (boost::starts_with(Settings::getInstance()->getString("OMXAudioDev").c_str(), "alsa"))
|
||||
{
|
||||
AudioManager::getInstance()->deinit();
|
||||
}
|
||||
|
||||
// Start the player process
|
||||
pid_t pid = fork();
|
||||
|
@ -88,7 +95,7 @@ void VideoPlayerComponent::startVideo()
|
|||
// We need to specify the layer of 10000 or above to ensure the video is displayed on top
|
||||
// of our SDL display
|
||||
|
||||
const char* argv[] = { "", "--layer", "10010", "--loop", "--no-osd", "--aspect-mode", "letterbox", "--vol", "0", "-o", "both","--win", buf, "-b", "", "", "", "", NULL };
|
||||
const char* argv[] = { "", "--layer", "10010", "--loop", "--no-osd", "--aspect-mode", "letterbox", "--vol", "0", "-o", "both","--win", buf, "--no-ghost-box", "", "", "", "", NULL };
|
||||
|
||||
// check if we want to mute the audio
|
||||
if (!Settings::getInstance()->getBool("VideoAudio"))
|
||||
|
@ -96,16 +103,43 @@ void VideoPlayerComponent::startVideo()
|
|||
argv[8] = "-1000000";
|
||||
}
|
||||
|
||||
// if we are rendering a video gamelist
|
||||
if (!mTargetIsMax)
|
||||
// test if there's a path for possible subtitles, meaning we're a screensaver video
|
||||
if (!subtitlePath.empty())
|
||||
{
|
||||
argv[6] = "stretch";
|
||||
// if we are rendering a screensaver
|
||||
|
||||
// check if we want to stretch the image
|
||||
if (Settings::getInstance()->getBool("StretchVideoOnScreenSaver"))
|
||||
{
|
||||
argv[6] = "stretch";
|
||||
}
|
||||
|
||||
if (Settings::getInstance()->getString("ScreenSaverGameInfo") != "never")
|
||||
{
|
||||
// if we have chosen to render subtitles
|
||||
argv[13] = "--subtitles";
|
||||
argv[14] = subtitlePath.c_str();
|
||||
argv[15] = mPlayingVideoPath.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have chosen NOT to render subtitles in the screensaver
|
||||
argv[13] = mPlayingVideoPath.c_str();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are rendering a video gamelist
|
||||
if (!mTargetIsMax)
|
||||
{
|
||||
argv[6] = "stretch";
|
||||
}
|
||||
argv[13] = mPlayingVideoPath.c_str();
|
||||
}
|
||||
|
||||
argv[10] = Settings::getInstance()->getString("OMXAudioDev").c_str();
|
||||
|
||||
argv[13] = mPlayingVideoPath.c_str();
|
||||
|
||||
//const char* argv[] = args;
|
||||
const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", NULL };
|
||||
|
||||
// Redirect stdout
|
||||
|
@ -141,7 +175,10 @@ void VideoPlayerComponent::stopVideo()
|
|||
kill(mPlayerPid, SIGKILL);
|
||||
waitpid(mPlayerPid, &status, WNOHANG);
|
||||
// Restart AudioManager
|
||||
AudioManager::getInstance()->init();
|
||||
if (boost::starts_with(Settings::getInstance()->getString("OMXAudioDev").c_str(), "alsa"))
|
||||
{
|
||||
AudioManager::getInstance()->init();
|
||||
}
|
||||
mPlayerPid = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ void catch_child(int sig_num);
|
|||
class VideoPlayerComponent : public VideoComponent
|
||||
{
|
||||
public:
|
||||
VideoPlayerComponent(Window* window);
|
||||
VideoPlayerComponent(Window* window, std::string path);
|
||||
virtual ~VideoPlayerComponent();
|
||||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
@ -36,6 +36,7 @@ private:
|
|||
|
||||
private:
|
||||
pid_t mPlayerPid;
|
||||
std::string subtitlePath;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,26 +11,26 @@ libvlc_instance_t* VideoVlcComponent::mVLC = NULL;
|
|||
|
||||
// VLC prepares to render a video frame.
|
||||
static void *lock(void *data, void **p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_LockMutex(c->mutex);
|
||||
SDL_LockSurface(c->surface);
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_LockMutex(c->mutex);
|
||||
SDL_LockSurface(c->surface);
|
||||
*p_pixels = c->surface->pixels;
|
||||
return NULL; // Picture identifier, not needed here.
|
||||
return NULL; // Picture identifier, not needed here.
|
||||
}
|
||||
|
||||
// VLC just rendered a video frame.
|
||||
static void unlock(void *data, void *id, void *const *p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_UnlockSurface(c->surface);
|
||||
SDL_UnlockMutex(c->mutex);
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_UnlockSurface(c->surface);
|
||||
SDL_UnlockMutex(c->mutex);
|
||||
}
|
||||
|
||||
// VLC wants to display a video frame.
|
||||
static void display(void *data, void *id) {
|
||||
//Data to be displayed
|
||||
//Data to be displayed
|
||||
}
|
||||
|
||||
VideoVlcComponent::VideoVlcComponent(Window* window) :
|
||||
VideoVlcComponent::VideoVlcComponent(Window* window, std::string subtitles) :
|
||||
VideoComponent(window),
|
||||
mMediaPlayer(nullptr)
|
||||
{
|
||||
|
@ -40,11 +40,12 @@ VideoVlcComponent::VideoVlcComponent(Window* window) :
|
|||
mTexture = TextureResource::get("");
|
||||
|
||||
// Make sure VLC has been initialised
|
||||
setupVLC();
|
||||
setupVLC(subtitles);
|
||||
}
|
||||
|
||||
VideoVlcComponent::~VideoVlcComponent()
|
||||
{
|
||||
stopVideo();
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setResize(float width, float height)
|
||||
|
@ -226,13 +227,27 @@ void VideoVlcComponent::freeContext()
|
|||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setupVLC()
|
||||
void VideoVlcComponent::setupVLC(std::string subtitles)
|
||||
{
|
||||
// If VLC hasn't been initialised yet then do it now
|
||||
if (!mVLC)
|
||||
{
|
||||
const char* args[] = { "--quiet" };
|
||||
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args);
|
||||
const char** args;
|
||||
const char* newargs[] = { "--quiet", "--sub-file", subtitles.c_str() };
|
||||
const char* singleargs[] = { "--quiet" };
|
||||
int argslen = 0;
|
||||
|
||||
if (!subtitles.empty())
|
||||
{
|
||||
argslen = sizeof(newargs) / sizeof(newargs[0]);
|
||||
args = newargs;
|
||||
}
|
||||
else
|
||||
{
|
||||
argslen = sizeof(singleargs) / sizeof(singleargs[0]);
|
||||
args = singleargs;
|
||||
}
|
||||
mVLC = libvlc_new(argslen, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,10 +306,31 @@ void VideoVlcComponent::startVideo()
|
|||
// Make sure we found a valid video track
|
||||
if ((mVideoWidth > 0) && (mVideoHeight > 0))
|
||||
{
|
||||
#ifndef _RPI_
|
||||
if (mScreensaverMode)
|
||||
{
|
||||
if(!Settings::getInstance()->getBool("CaptionsCompatibility")) {
|
||||
|
||||
Eigen::Vector2f resizeScale((Renderer::getScreenWidth() / mVideoWidth), (Renderer::getScreenHeight() / mVideoHeight));
|
||||
|
||||
if(resizeScale.x() < resizeScale.y())
|
||||
{
|
||||
mVideoWidth *= resizeScale.x();
|
||||
mVideoHeight *= resizeScale.x();
|
||||
}else{
|
||||
mVideoWidth *= resizeScale.y();
|
||||
mVideoHeight *= resizeScale.y();
|
||||
}
|
||||
mVideoHeight = round(mVideoHeight);
|
||||
mVideoWidth = round(mVideoWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
setupContext();
|
||||
|
||||
// Setup the media player
|
||||
mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
|
||||
|
||||
if (!Settings::getInstance()->getBool("VideoAudio"))
|
||||
{
|
||||
libvlc_audio_set_mute(mMediaPlayer, 1);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "VideoComponent.h"
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/libvlc_media.h>
|
||||
#include "resources/TextureResource.h"
|
||||
|
||||
struct VideoContext {
|
||||
|
@ -26,9 +27,9 @@ class VideoVlcComponent : public VideoComponent
|
|||
};
|
||||
|
||||
public:
|
||||
static void setupVLC();
|
||||
static void setupVLC(std::string subtitles);
|
||||
|
||||
VideoVlcComponent(Window* window);
|
||||
VideoVlcComponent(Window* window, std::string subtitles);
|
||||
virtual ~VideoVlcComponent();
|
||||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
std::string getHomePath();
|
||||
|
||||
|
||||
int runShutdownCommand(); // shut down the system (returns 0 if successful)
|
||||
int runRestartCommand(); // restart the system (returns 0 if successful)
|
||||
int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell (requires wstring conversion on Windows)
|
||||
|
|
Loading…
Reference in a new issue