Merge pull request #153 from pjft/RetroPie-ScreenSaver-Merge

Adding Random Video Screensaver/Attract Mode, plus controls
This commit is contained in:
Jools Wills 2017-06-12 16:43:41 +01:00 committed by GitHub
commit 2188efd2b6
27 changed files with 891 additions and 123 deletions

View file

@ -11,6 +11,7 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h ${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.h ${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.h ${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemScreenSaver.h
# GuiComponents # GuiComponents
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.h ${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/GuiMetaDataEd.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.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/GuiMenu.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.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/VolumeControl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Gamelist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemScreenSaver.cpp
# GuiComponents # GuiComponents
${CMAKE_CURRENT_SOURCE_DIR}/src/components/AsyncReqComponent.cpp ${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/GuiMetaDataEd.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGameScraper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiGamelistOptions.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/GuiMenu.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp

View 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);
}
}

View 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;
};

View file

@ -6,6 +6,7 @@
#include "Settings.h" #include "Settings.h"
#include "guis/GuiMsgBox.h" #include "guis/GuiMsgBox.h"
#include "guis/GuiSettings.h" #include "guis/GuiSettings.h"
#include "guis/GuiScreensaverOptions.h"
#include "guis/GuiScraperStart.h" #include "guis/GuiScraperStart.h"
#include "guis/GuiDetectDevice.h" #include "guis/GuiDetectDevice.h"
#include "views/ViewController.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->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled);
s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); 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); 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)); }); s->addSaveFunc([screensaver_time] { Settings::getInstance()->setInt("ScreenSaverTime", (int)round(screensaver_time->getValue()) * (1000 * 60)); });
// screensaver behavior // 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; std::vector<std::string> screensavers;
screensavers.push_back("dim"); screensavers.push_back("dim");
screensavers.push_back("black"); screensavers.push_back("black");
screensavers.push_back("random video");
for(auto it = screensavers.begin(); it != screensavers.end(); it++) for(auto it = screensavers.begin(); it != screensavers.end(); it++)
screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it); screensaver_behavior->add(*it, *it, Settings::getInstance()->getString("ScreenSaverBehavior") == *it);
s->addWithLabel("SCREENSAVER BEHAVIOR", screensaver_behavior); 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 ComponentListRow row;
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()); });
// show help // show filtered menu
auto show_help = std::make_shared<SwitchComponent>(mWindow); row.elements.clear();
show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts")); row.addElement(std::make_shared<TextComponent>(mWindow, "VIDEO SCREENSAVER SETTINGS", Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true);
s->addWithLabel("ON-SCREEN HELP", show_help); row.addElement(makeArrow(mWindow), false);
s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); }); row.makeAcceptInputHandler(std::bind(&GuiMenu::openScreensaverOptions, this));
s->addRow(row);
// quick system select (left/right in game list view) // quick system select (left/right in game list view)
auto quick_sys_select = std::make_shared<SwitchComponent>(mWindow); 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) if (needReload)
ViewController::get()->reloadAll(); ViewController::get()->reloadAll();
}); });
mWindow->pushGui(s);
});
addEntry("VIDEO PLAYER SETTINGS", 0x777777FF, true, // show help
[this] { auto show_help = std::make_shared<SwitchComponent>(mWindow);
auto s = new GuiSettings(mWindow, "VIDEO PLAYER SETTINGS"); show_help->setState(Settings::getInstance()->getBool("ShowHelpPrompts"));
s->addWithLabel("ON-SCREEN HELP", show_help);
#ifdef _RPI_ s->addSaveFunc([show_help] { Settings::getInstance()->setBool("ShowHelpPrompts", show_help->getState()); });
// 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()); });
mWindow->pushGui(s); 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->addWithLabel("PARSE GAMESLISTS ONLY", parse_gamelists);
s->addSaveFunc([parse_gamelists] { Settings::getInstance()->setBool("ParseGamelistOnly", parse_gamelists->getState()); }); 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 // maximum vram
auto max_vram = std::make_shared<SliderComponent>(mWindow, 0.f, 1000.f, 10.f, "Mb"); auto max_vram = std::make_shared<SliderComponent>(mWindow, 0.f, 1000.f, 10.f, "Mb");
max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM"))); max_vram->setValue((float)(Settings::getInstance()->getInt("MaxVRAM")));
s->addWithLabel("VRAM LIMIT", max_vram); s->addWithLabel("VRAM LIMIT", max_vram);
s->addSaveFunc([max_vram] { Settings::getInstance()->setInt("MaxVRAM", (int)round(max_vram->getValue())); }); 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); 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); 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() void GuiMenu::onSizeChanged()
{ {
mVersion.setSize(mSize.x(), 0); mVersion.setSize(mSize.x(), 0);

View file

@ -16,7 +16,7 @@ public:
private: private:
void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func); void addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func);
void openScreensaverOptions();
MenuComponent mMenu; MenuComponent mMenu;
TextComponent mVersion; TextComponent mVersion;
}; };

View 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;
}

View 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;
};

View file

@ -14,6 +14,7 @@
#include "platform.h" #include "platform.h"
#include "Log.h" #include "Log.h"
#include "Window.h" #include "Window.h"
#include "SystemScreenSaver.h"
#include "EmulationStation.h" #include "EmulationStation.h"
#include "Settings.h" #include "Settings.h"
#include "ScraperCmdLine.h" #include "ScraperCmdLine.h"
@ -222,6 +223,7 @@ int main(int argc, char* argv[])
atexit(&onExit); atexit(&onExit);
Window window; Window window;
SystemScreenSaver screensaver(&window);
ViewController::init(&window); ViewController::init(&window);
window.pushGui(ViewController::get()); window.pushGui(ViewController::get());

View file

@ -158,6 +158,12 @@ bool SystemView::input(InputConfig* config, Input input)
config->isMappedTo("up", input) || config->isMappedTo("up", input) ||
config->isMappedTo("down", input)) config->isMappedTo("down", input))
listInput(0); listInput(0);
if(config->isMappedTo("select", input) && Settings::getInstance()->getBool("ScreenSaverControls"))
{
mWindow->startScreenSaver();
mWindow->renderScreenSaver();
return true;
}
} }
return GuiComponent::input(config, input); 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("left/right", "choose"));
prompts.push_back(HelpPrompt("a", "select")); prompts.push_back(HelpPrompt("a", "select"));
prompts.push_back(HelpPrompt("x", "random")); prompts.push_back(HelpPrompt("x", "random"));
if (Settings::getInstance()->getBool("ScreenSaverControls"))
prompts.push_back(HelpPrompt("select", "launch screensaver"));
return prompts; return prompts;
} }

View file

@ -19,10 +19,10 @@ public:
virtual const char* getName() const override { return "basic"; } virtual const char* getName() const override { return "basic"; }
virtual std::vector<HelpPrompt> getHelpPrompts() override; virtual std::vector<HelpPrompt> getHelpPrompts() override;
virtual void launch(FileData* game) override;
protected: protected:
virtual void populateList(const std::vector<FileData*>& files) override; virtual void populateList(const std::vector<FileData*>& files) override;
virtual void launch(FileData* game) override;
virtual void remove(FileData* game) override; virtual void remove(FileData* game) override;
TextListComponent<FileData*> mList; TextListComponent<FileData*> mList;

View file

@ -14,7 +14,6 @@ public:
virtual const char* getName() const override { return "detailed"; } virtual const char* getName() const override { return "detailed"; }
protected:
virtual void launch(FileData* game) override; virtual void launch(FileData* game) override;
private: private:

View file

@ -20,10 +20,10 @@ public:
virtual const char* getName() const override { return "grid"; } virtual const char* getName() const override { return "grid"; }
virtual std::vector<HelpPrompt> getHelpPrompts() override; virtual std::vector<HelpPrompt> getHelpPrompts() override;
virtual void launch(FileData* game) override;
protected: protected:
virtual void populateList(const std::vector<FileData*>& files) override; virtual void populateList(const std::vector<FileData*>& files) override;
virtual void launch(FileData* game) override;
ImageGridComponent<FileData*> mGrid; ImageGridComponent<FileData*> mGrid;
}; };

View file

@ -35,6 +35,7 @@ public:
virtual void remove(FileData* game) = 0; virtual void remove(FileData* game) = 0;
virtual const char* getName() const = 0; virtual const char* getName() const = 0;
virtual void launch(FileData* game) = 0;
virtual HelpStyle getHelpStyle() override; virtual HelpStyle getHelpStyle() override;

View file

@ -23,10 +23,10 @@ public:
virtual void setCursor(FileData*) = 0; virtual void setCursor(FileData*) = 0;
virtual bool input(InputConfig* config, Input input) override; virtual bool input(InputConfig* config, Input input) override;
virtual void launch(FileData* game) = 0;
protected: protected:
virtual void populateList(const std::vector<FileData*>& files) = 0; virtual void populateList(const std::vector<FileData*>& files) = 0;
virtual void launch(FileData* game) = 0;
TextComponent mHeaderText; TextComponent mHeaderText;
ImageComponent mHeaderImage; ImageComponent mHeaderImage;

View file

@ -29,11 +29,11 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
// Create the correct type of video window // Create the correct type of video window
#ifdef _RPI_ #ifdef _RPI_
if (Settings::getInstance()->getBool("VideoOmxPlayer")) if (Settings::getInstance()->getBool("VideoOmxPlayer"))
mVideo = new VideoPlayerComponent(window); mVideo = new VideoPlayerComponent(window, "");
else else
mVideo = new VideoVlcComponent(window); mVideo = new VideoVlcComponent(window, getTitlePath());
#else #else
mVideo = new VideoVlcComponent(window); mVideo = new VideoVlcComponent(window, getTitlePath());
#endif #endif
mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y()); 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(); FileData* file = (mList.size() == 0 || mList.isScrolling()) ? NULL : mList.getSelected();
boost::filesystem::remove(getTitlePath().c_str());
bool fadingOut; bool fadingOut;
if(file == NULL) if(file == NULL)
{ {

View file

@ -17,10 +17,9 @@ public:
virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override; virtual void onThemeChanged(const std::shared_ptr<ThemeData>& theme) override;
virtual const char* getName() const override { return "video"; } virtual const char* getName() const override { return "video"; }
virtual void launch(FileData* game) override;
protected: protected:
virtual void launch(FileData* game) override;
virtual void update(int deltaTime) override; virtual void update(int deltaTime) override;
private: private:

View file

@ -87,6 +87,7 @@ public:
virtual void onShow(); virtual void onShow();
virtual void onHide(); virtual void onHide();
virtual void onScreenSaverActivate(); virtual void onScreenSaverActivate();
virtual void onScreenSaverDeactivate(); virtual void onScreenSaverDeactivate();
virtual void topWindow(bool isTop); virtual void topWindow(bool isTop);

View file

@ -77,10 +77,22 @@ void Settings::setDefaults()
mStringMap["Scraper"] = "TheGamesDB"; mStringMap["Scraper"] = "TheGamesDB";
mStringMap["GamelistViewStyle"] = "automatic"; 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 // 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
mBoolMap["VideoOmxPlayer"] = false; 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["VideoAudio"] = true;
mBoolMap["CaptionsCompatibility"] = true;
// Audio out device for Video playback using OMX player. // Audio out device for Video playback using OMX player.
mStringMap["OMXAudioDev"] = "both"; mStringMap["OMXAudioDev"] = "both";

View file

@ -10,7 +10,7 @@
#include "components/ImageComponent.h" #include "components/ImageComponent.h"
Window::Window() : mNormalizeNextUpdate(false), mFrameTimeElapsed(0), mFrameCountElapsed(0), mAverageDeltaTime(10), 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); mHelp = new HelpComponent(this);
mBackgroundOverlay = new ImageComponent(this); mBackgroundOverlay = new ImageComponent(this);
@ -115,26 +115,48 @@ void Window::textInput(const char* text)
void Window::input(InputConfig* config, Input input) void Window::input(InputConfig* config, Input input)
{ {
if (mRenderScreenSaver) if (mScreenSaver) {
{ if(mScreenSaver->isScreenSaverActive() && Settings::getInstance()->getBool("ScreenSaverControls") &&
mRenderScreenSaver = false; (Settings::getInstance()->getString("ScreenSaverBehavior") == "random video"))
{
// Tell the GUI components the screensaver has stopped if(mScreenSaver->getCurrentGame() != NULL && (config->isMappedTo("right", input) || config->isMappedTo("start", input) || config->isMappedTo("select", input)))
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++) {
(*i)->onScreenSaverDeactivate(); 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) if(mSleeping)
{ {
// wake up // wake up
mTimeSinceLastInput = 0; mTimeSinceLastInput = 0;
cancelScreenSaver();
mSleeping = false; mSleeping = false;
onWake(); onWake();
return; return;
} }
mTimeSinceLastInput = 0; mTimeSinceLastInput = 0;
cancelScreenSaver();
if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) 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()) if(peekGui())
peekGui()->update(deltaTime); peekGui()->update(deltaTime);
// Update the screensaver
if (mScreenSaver)
mScreenSaver->update(deltaTime);
} }
void Window::render() void Window::render()
@ -226,18 +252,16 @@ 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)
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(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0)
{ {
if (!mRenderScreenSaver) if (!isProcessing() && mAllowSleep && (!mScreenSaver || mScreenSaver->allowSleep()))
{
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
(*i)->onScreenSaverActivate();
mRenderScreenSaver = true;
}
renderScreenSaver();
if (!isProcessing() && mAllowSleep)
{ {
// go to sleep // go to sleep
mSleeping = true; mSleeping = true;
@ -374,9 +398,35 @@ bool Window::isProcessing()
return count_if(mGuiStack.begin(), mGuiStack.end(), [](GuiComponent* c) { return c->isProcessing(); }) > 0; return count_if(mGuiStack.begin(), mGuiStack.end(), [](GuiComponent* c) { return c->isProcessing(); }) > 0;
} }
void Window::renderScreenSaver() void Window::startScreenSaver()
{ {
Renderer::setMatrix(Eigen::Affine3f::Identity()); if (mScreenSaver && !mRenderScreenSaver)
unsigned char opacity = Settings::getInstance()->getString("ScreenSaverBehavior") == "dim" ? 0xA0 : 0xFF; {
Renderer::drawRect(0, 0, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x00000000 | opacity); // 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();
}

View file

@ -5,12 +5,26 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "InputManager.h" #include "InputManager.h"
class FileData;
class HelpComponent; class HelpComponent;
class ImageComponent; class ImageComponent;
class Window class Window
{ {
public: 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();
~Window(); ~Window();
@ -38,16 +52,23 @@ public:
void renderHelpPromptsEarly(); // used to render HelpPrompts before a fade void renderHelpPromptsEarly(); // used to render HelpPrompts before a fade
void setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpStyle& style); void setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpStyle& style);
void setScreenSaver(ScreenSaver* screenSaver) { mScreenSaver = screenSaver; }
void startScreenSaver();
void cancelScreenSaver();
void renderScreenSaver();
private: private:
void onSleep(); void onSleep();
void onWake(); void onWake();
// Returns true if at least one component on the stack is processing // Returns true if at least one component on the stack is processing
bool isProcessing(); bool isProcessing();
void renderScreenSaver();
HelpComponent* mHelp; HelpComponent* mHelp;
ImageComponent* mBackgroundOverlay; ImageComponent* mBackgroundOverlay;
ScreenSaver* mScreenSaver;
bool mRenderScreenSaver;
std::vector<GuiComponent*> mGuiStack; std::vector<GuiComponent*> mGuiStack;
@ -56,7 +77,6 @@ private:
int mFrameTimeElapsed; int mFrameTimeElapsed;
int mFrameCountElapsed; int mFrameCountElapsed;
int mAverageDeltaTime; int mAverageDeltaTime;
bool mRenderScreenSaver;
std::unique_ptr<TextCache> mFrameDataText; std::unique_ptr<TextCache> mFrameDataText;

View file

@ -9,6 +9,45 @@
#define FADE_TIME_MS 200 #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) : VideoComponent::VideoComponent(Window* window) :
GuiComponent(window), GuiComponent(window),
mStaticImage(window), mStaticImage(window),
@ -19,6 +58,7 @@ VideoComponent::VideoComponent(Window* window) :
mShowing(false), mShowing(false),
mScreensaverActive(false), mScreensaverActive(false),
mDisable(false), mDisable(false),
mScreensaverMode(false),
mTargetIsMax(false), mTargetIsMax(false),
mOrigin(0, 0), mOrigin(0, 0),
mTargetSize(0, 0) mTargetSize(0, 0)
@ -31,12 +71,17 @@ VideoComponent::VideoComponent(Window* window) :
topWindow(false); topWindow(false);
} }
std::string path = getTitleFolder();
if(!boost::filesystem::exists(path))
boost::filesystem::create_directory(path);
} }
VideoComponent::~VideoComponent() VideoComponent::~VideoComponent()
{ {
// Stop any currently running video // Stop any currently running video
stopVideo(); stopVideo();
// Delete subtitle file, if existing
remove(getTitlePath().c_str());
} }
void VideoComponent::setOrigin(float originX, float originY) void VideoComponent::setOrigin(float originX, float originY)

View file

@ -12,6 +12,10 @@
#include <SDL_mutex.h> #include <SDL_mutex.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
std::string getTitlePath();
std::string getTitleFolder();
void writeSubtitle(const char* gameName, const char* systemName, bool always);
class VideoComponent : public GuiComponent class VideoComponent : public GuiComponent
{ {
// Structure that groups together the configuration of the video component // Structure that groups together the configuration of the video component
@ -35,6 +39,9 @@ public:
// Configures the component to show the default video // Configures the component to show the default video
void setDefaultVideo(); void setDefaultVideo();
// sets whether it's going to render in screensaver mode
void setScreensaverMode(bool isScreensaver);
virtual void onShow() override; virtual void onShow() override;
virtual void onHide() override; virtual void onHide() override;
virtual void onScreenSaverActivate() override; virtual void onScreenSaverActivate() override;
@ -107,6 +114,7 @@ protected:
bool mShowing; bool mShowing;
bool mDisable; bool mDisable;
bool mScreensaverActive; bool mScreensaverActive;
bool mScreensaverMode;
bool mTargetIsMax; bool mTargetIsMax;
Configuration mConfig; Configuration mConfig;

View file

@ -1,5 +1,6 @@
#ifdef _RPI_ #ifdef _RPI_
#include "components/VideoPlayerComponent.h" #include "components/VideoPlayerComponent.h"
#include <boost/algorithm/string/predicate.hpp>
#include "AudioManager.h" #include "AudioManager.h"
#include "Renderer.h" #include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
@ -11,14 +12,16 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
VideoPlayerComponent::VideoPlayerComponent(Window* window) : VideoPlayerComponent::VideoPlayerComponent(Window* window, std::string path) :
VideoComponent(window), VideoComponent(window),
mPlayerPid(-1) mPlayerPid(-1),
subtitlePath(path)
{ {
} }
VideoPlayerComponent::~VideoPlayerComponent() VideoPlayerComponent::~VideoPlayerComponent()
{ {
stopVideo();
} }
void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans) void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans)
@ -46,7 +49,8 @@ void VideoPlayerComponent::setMaxSize(float width, float height)
void VideoPlayerComponent::startVideo() void VideoPlayerComponent::startVideo()
{ {
if (!mIsPlaying) { if (!mIsPlaying)
{
mVideoWidth = 0; mVideoWidth = 0;
mVideoHeight = 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 // Set the video that we are going to be playing so we don't attempt to restart it
mPlayingVideoPath = mVideoPath; mPlayingVideoPath = mVideoPath;
// Disable AudioManager so video can play // Disable AudioManager so video can play, in case we're requesting ALSA
AudioManager::getInstance()->deinit(); if (boost::starts_with(Settings::getInstance()->getString("OMXAudioDev").c_str(), "alsa"))
{
AudioManager::getInstance()->deinit();
}
// Start the player process // Start the player process
pid_t pid = fork(); 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 // We need to specify the layer of 10000 or above to ensure the video is displayed on top
// of our SDL display // 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 // check if we want to mute the audio
if (!Settings::getInstance()->getBool("VideoAudio")) if (!Settings::getInstance()->getBool("VideoAudio"))
@ -96,16 +103,43 @@ void VideoPlayerComponent::startVideo()
argv[8] = "-1000000"; argv[8] = "-1000000";
} }
// if we are rendering a video gamelist // test if there's a path for possible subtitles, meaning we're a screensaver video
if (!mTargetIsMax) 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[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 }; const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", NULL };
// Redirect stdout // Redirect stdout
@ -141,7 +175,10 @@ void VideoPlayerComponent::stopVideo()
kill(mPlayerPid, SIGKILL); kill(mPlayerPid, SIGKILL);
waitpid(mPlayerPid, &status, WNOHANG); waitpid(mPlayerPid, &status, WNOHANG);
// Restart AudioManager // Restart AudioManager
AudioManager::getInstance()->init(); if (boost::starts_with(Settings::getInstance()->getString("OMXAudioDev").c_str(), "alsa"))
{
AudioManager::getInstance()->init();
}
mPlayerPid = -1; mPlayerPid = -1;
} }
} }

View file

@ -12,7 +12,7 @@ void catch_child(int sig_num);
class VideoPlayerComponent : public VideoComponent class VideoPlayerComponent : public VideoComponent
{ {
public: public:
VideoPlayerComponent(Window* window); VideoPlayerComponent(Window* window, std::string path);
virtual ~VideoPlayerComponent(); virtual ~VideoPlayerComponent();
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
@ -36,6 +36,7 @@ private:
private: private:
pid_t mPlayerPid; pid_t mPlayerPid;
std::string subtitlePath;
}; };
#endif #endif

View file

@ -11,26 +11,26 @@ libvlc_instance_t* VideoVlcComponent::mVLC = NULL;
// VLC prepares to render a video frame. // VLC prepares to render a video frame.
static void *lock(void *data, void **p_pixels) { static void *lock(void *data, void **p_pixels) {
struct VideoContext *c = (struct VideoContext *)data; struct VideoContext *c = (struct VideoContext *)data;
SDL_LockMutex(c->mutex); SDL_LockMutex(c->mutex);
SDL_LockSurface(c->surface); SDL_LockSurface(c->surface);
*p_pixels = c->surface->pixels; *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. // VLC just rendered a video frame.
static void unlock(void *data, void *id, void *const *p_pixels) { static void unlock(void *data, void *id, void *const *p_pixels) {
struct VideoContext *c = (struct VideoContext *)data; struct VideoContext *c = (struct VideoContext *)data;
SDL_UnlockSurface(c->surface); SDL_UnlockSurface(c->surface);
SDL_UnlockMutex(c->mutex); SDL_UnlockMutex(c->mutex);
} }
// VLC wants to display a video frame. // VLC wants to display a video frame.
static void display(void *data, void *id) { 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), VideoComponent(window),
mMediaPlayer(nullptr) mMediaPlayer(nullptr)
{ {
@ -40,11 +40,12 @@ VideoVlcComponent::VideoVlcComponent(Window* window) :
mTexture = TextureResource::get(""); mTexture = TextureResource::get("");
// Make sure VLC has been initialised // Make sure VLC has been initialised
setupVLC(); setupVLC(subtitles);
} }
VideoVlcComponent::~VideoVlcComponent() VideoVlcComponent::~VideoVlcComponent()
{ {
stopVideo();
} }
void VideoVlcComponent::setResize(float width, float height) 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 VLC hasn't been initialised yet then do it now
if (!mVLC) if (!mVLC)
{ {
const char* args[] = { "--quiet" }; const char** args;
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), 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 // Make sure we found a valid video track
if ((mVideoWidth > 0) && (mVideoHeight > 0)) 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(); setupContext();
// Setup the media player // Setup the media player
mMediaPlayer = libvlc_media_player_new_from_media(mMedia); mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
if (!Settings::getInstance()->getBool("VideoAudio")) if (!Settings::getInstance()->getBool("VideoAudio"))
{ {
libvlc_audio_set_mute(mMediaPlayer, 1); libvlc_audio_set_mute(mMediaPlayer, 1);

View file

@ -6,6 +6,7 @@
#include "VideoComponent.h" #include "VideoComponent.h"
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/libvlc_media.h>
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
struct VideoContext { struct VideoContext {
@ -26,9 +27,9 @@ class VideoVlcComponent : public VideoComponent
}; };
public: public:
static void setupVLC(); static void setupVLC(std::string subtitles);
VideoVlcComponent(Window* window); VideoVlcComponent(Window* window, std::string subtitles);
virtual ~VideoVlcComponent(); virtual ~VideoVlcComponent();
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;

View file

@ -19,6 +19,7 @@
std::string getHomePath(); std::string getHomePath();
int runShutdownCommand(); // shut down the system (returns 0 if successful) int runShutdownCommand(); // shut down the system (returns 0 if successful)
int runRestartCommand(); // restart 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) int runSystemCommand(const std::string& cmd_utf8); // run a utf-8 encoded in the shell (requires wstring conversion on Windows)