mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 15:45:38 +00:00
Fixes and tweaks to OMXPlayer work, by pjft
- Correct handling of zombie processes left in memory - Add options to mute video - Fix resizing to work with theme refactorings introduced by jdrassa and zigurana
This commit is contained in:
parent
34ea9caa89
commit
029e8bd040
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -0,0 +1,3 @@
|
|||
[submodule "external/pugixml"]
|
||||
path = external/pugixml
|
||||
url = https://github.com/zeux/pugixml.git
|
|
@ -31,8 +31,8 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
// [version]
|
||||
|
||||
auto openScrapeNow = [this] { mWindow->pushGui(new GuiScraperStart(mWindow)); };
|
||||
addEntry("SCRAPER", 0x777777FF, true,
|
||||
[this, openScrapeNow] {
|
||||
addEntry("SCRAPER", 0x777777FF, true,
|
||||
[this, openScrapeNow] {
|
||||
auto s = new GuiSettings(mWindow, "SCRAPER");
|
||||
|
||||
// scrape from
|
||||
|
@ -65,7 +65,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
mWindow->pushGui(s);
|
||||
});
|
||||
|
||||
addEntry("SOUND SETTINGS", 0x777777FF, true,
|
||||
addEntry("SOUND SETTINGS", 0x777777FF, true,
|
||||
[this] {
|
||||
auto s = new GuiSettings(mWindow, "SOUND SETTINGS");
|
||||
|
||||
|
@ -74,11 +74,11 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
volume->setValue((float)VolumeControl::getInstance()->getVolume());
|
||||
s->addWithLabel("SYSTEM VOLUME", volume);
|
||||
s->addSaveFunc([volume] { VolumeControl::getInstance()->setVolume((int)round(volume->getValue())); });
|
||||
|
||||
|
||||
// disable sounds
|
||||
auto sounds_enabled = std::make_shared<SwitchComponent>(mWindow);
|
||||
sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds"));
|
||||
s->addWithLabel("ENABLE SOUNDS", sounds_enabled);
|
||||
s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled);
|
||||
s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); });
|
||||
|
||||
mWindow->pushGui(s);
|
||||
|
@ -147,7 +147,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
s->addWithLabel("THEME SET", theme_set);
|
||||
|
||||
Window* window = mWindow;
|
||||
s->addSaveFunc([window, theme_set]
|
||||
s->addSaveFunc([window, theme_set]
|
||||
{
|
||||
bool needReload = false;
|
||||
if(Settings::getInstance()->getString("ThemeSet") != theme_set->getSelected())
|
||||
|
@ -174,13 +174,43 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
bool needReload = false;
|
||||
if (Settings::getInstance()->getString("GamelistViewStyle") != gamelist_style->getSelected())
|
||||
needReload = true;
|
||||
Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected());
|
||||
Settings::getInstance()->setString("GamelistViewStyle", gamelist_style->getSelected());
|
||||
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();
|
||||
});
|
||||
#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);
|
||||
});
|
||||
|
||||
addEntry("OTHER SETTINGS", 0x777777FF, true,
|
||||
[this] {
|
||||
auto s = new GuiSettings(mWindow, "OTHER SETTINGS");
|
||||
|
@ -205,7 +235,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
mWindow->pushGui(s);
|
||||
});
|
||||
|
||||
addEntry("CONFIGURE INPUT", 0x777777FF, true,
|
||||
addEntry("CONFIGURE INPUT", 0x777777FF, true,
|
||||
[this] {
|
||||
Window* window = mWindow;
|
||||
window->pushGui(new GuiMsgBox(window, "ARE YOU SURE YOU WANT TO CONFIGURE INPUT?", "YES",
|
||||
|
@ -215,10 +245,10 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
);
|
||||
});
|
||||
|
||||
addEntry("QUIT", 0x777777FF, true,
|
||||
addEntry("QUIT", 0x777777FF, true,
|
||||
[this] {
|
||||
auto s = new GuiSettings(mWindow, "QUIT");
|
||||
|
||||
|
||||
Window* window = mWindow;
|
||||
|
||||
ComponentListRow row;
|
||||
|
@ -234,8 +264,8 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
|
||||
row.elements.clear();
|
||||
row.makeAcceptInputHandler([window] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES",
|
||||
[] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY RESTART?", "YES",
|
||||
[] {
|
||||
if(quitES("/tmp/es-sysrestart") != 0)
|
||||
LOG(LogWarning) << "Restart terminated with non-zero result!";
|
||||
}, "NO", nullptr));
|
||||
|
@ -245,8 +275,8 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
|
||||
row.elements.clear();
|
||||
row.makeAcceptInputHandler([window] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY SHUTDOWN?", "YES",
|
||||
[] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY SHUTDOWN?", "YES",
|
||||
[] {
|
||||
if(quitES("/tmp/es-shutdown") != 0)
|
||||
LOG(LogWarning) << "Shutdown terminated with non-zero result!";
|
||||
}, "NO", nullptr));
|
||||
|
@ -258,8 +288,8 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
|
|||
{
|
||||
row.elements.clear();
|
||||
row.makeAcceptInputHandler([window] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY QUIT?", "YES",
|
||||
[] {
|
||||
window->pushGui(new GuiMsgBox(window, "REALLY QUIT?", "YES",
|
||||
[] {
|
||||
SDL_Event ev;
|
||||
ev.type = SDL_QUIT;
|
||||
SDL_PushEvent(&ev);
|
||||
|
@ -293,7 +323,7 @@ void GuiMenu::onSizeChanged()
|
|||
void GuiMenu::addEntry(const char* name, unsigned int color, bool add_arrow, const std::function<void()>& func)
|
||||
{
|
||||
std::shared_ptr<Font> font = Font::get(FONT_SIZE_MEDIUM);
|
||||
|
||||
|
||||
// populate the list
|
||||
ComponentListRow row;
|
||||
row.addElement(std::make_shared<TextComponent>(mWindow, name, font, color), true);
|
||||
|
@ -303,7 +333,7 @@ void GuiMenu::addEntry(const char* name, unsigned int color, bool add_arrow, con
|
|||
std::shared_ptr<ImageComponent> bracket = makeArrow(mWindow);
|
||||
row.addElement(bracket, false);
|
||||
}
|
||||
|
||||
|
||||
row.makeAcceptInputHandler(func);
|
||||
|
||||
mMenu.addRow(row);
|
||||
|
|
|
@ -61,7 +61,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
|||
mVideo->setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f);
|
||||
mVideo->setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f);
|
||||
mVideo->setDefaultZIndex(30);
|
||||
addChild(&mVideo);
|
||||
addChild(mVideo);
|
||||
|
||||
// metadata labels + values
|
||||
mLblRating.setText("Rating: ");
|
||||
|
|
|
@ -79,11 +79,9 @@ void Settings::setDefaults()
|
|||
|
||||
// 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
|
||||
#ifdef _RPI_
|
||||
mBoolMap["VideoOmxPlayer"] = true;
|
||||
#else
|
||||
mBoolMap["VideoOmxPlayer"] = false;
|
||||
#endif
|
||||
mBoolMap["VideoAudio"] = true;
|
||||
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "components/HelpComponent.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)
|
||||
{
|
||||
mHelp = new HelpComponent(this);
|
||||
|
@ -23,7 +23,7 @@ Window::~Window()
|
|||
// delete all our GUIs
|
||||
while(peekGui())
|
||||
delete peekGui();
|
||||
|
||||
|
||||
delete mHelp;
|
||||
}
|
||||
|
||||
|
@ -115,10 +115,20 @@ 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(mSleeping)
|
||||
{
|
||||
// wake up
|
||||
mTimeSinceLastInput = 0;
|
||||
|
||||
mSleeping = false;
|
||||
onWake();
|
||||
return;
|
||||
|
@ -157,11 +167,11 @@ void Window::update(int deltaTime)
|
|||
if(mFrameTimeElapsed > 500)
|
||||
{
|
||||
mAverageDeltaTime = mFrameTimeElapsed / mFrameCountElapsed;
|
||||
|
||||
|
||||
if(Settings::getInstance()->getBool("DrawFramerate"))
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
|
||||
// fps
|
||||
ss << std::fixed << std::setprecision(1) << (1000.0f * (float)mFrameCountElapsed / (float)mFrameTimeElapsed) << "fps, ";
|
||||
ss << std::fixed << std::setprecision(2) << ((float)mFrameTimeElapsed / (float)mFrameCountElapsed) << "ms";
|
||||
|
@ -218,6 +228,13 @@ void Window::render()
|
|||
unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime");
|
||||
if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0)
|
||||
{
|
||||
if (!mRenderScreenSaver)
|
||||
{
|
||||
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
|
||||
(*i)->onScreenSaverActivate();
|
||||
mRenderScreenSaver = true;
|
||||
}
|
||||
|
||||
renderScreenSaver();
|
||||
|
||||
if (!isProcessing() && mAllowSleep)
|
||||
|
@ -258,7 +275,7 @@ void Window::renderLoadingScreen()
|
|||
|
||||
auto& font = mDefaultFonts.at(1);
|
||||
TextCache* cache = font->buildTextCache("LOADING...", 0, 0, 0x656565FF);
|
||||
trans = trans.translate(Eigen::Vector3f(round((Renderer::getScreenWidth() - cache->metrics.size.x()) / 2.0f),
|
||||
trans = trans.translate(Eigen::Vector3f(round((Renderer::getScreenWidth() - cache->metrics.size.x()) / 2.0f),
|
||||
round(Renderer::getScreenHeight() * 0.835f), 0.0f));
|
||||
Renderer::setMatrix(trans);
|
||||
font->renderTextCache(cache);
|
||||
|
@ -314,16 +331,16 @@ void Window::setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpSt
|
|||
|
||||
// sort prompts so it goes [dpad_all] [dpad_u/d] [dpad_l/r] [a/b/x/y/l/r] [start/select]
|
||||
std::sort(addPrompts.begin(), addPrompts.end(), [](const HelpPrompt& a, const HelpPrompt& b) -> bool {
|
||||
|
||||
|
||||
static const char* map[] = {
|
||||
"up/down/left/right",
|
||||
"up/down",
|
||||
"left/right",
|
||||
"a", "b", "x", "y", "l", "r",
|
||||
"start", "select",
|
||||
"a", "b", "x", "y", "l", "r",
|
||||
"start", "select",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
int i = 0;
|
||||
int aVal = 0;
|
||||
int bVal = 0;
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
void pushGui(GuiComponent* gui);
|
||||
void removeGui(GuiComponent* gui);
|
||||
GuiComponent* peekGui();
|
||||
inline int getGuiStackSize() { return mGuiStack.size(); }
|
||||
|
||||
void textInput(const char* text);
|
||||
void input(InputConfig* config, Input input);
|
||||
|
@ -31,7 +32,7 @@ public:
|
|||
inline bool isSleeping() const { return mSleeping; }
|
||||
bool getAllowSleep();
|
||||
void setAllowSleep(bool sleep);
|
||||
|
||||
|
||||
void renderLoadingScreen();
|
||||
|
||||
void renderHelpPromptsEarly(); // used to render HelpPrompts before a fade
|
||||
|
@ -55,6 +56,7 @@ private:
|
|||
int mFrameTimeElapsed;
|
||||
int mFrameCountElapsed;
|
||||
int mAverageDeltaTime;
|
||||
bool mRenderScreenSaver;
|
||||
|
||||
std::unique_ptr<TextCache> mFrameDataText;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Util.h"
|
||||
#include "Window.h"
|
||||
#ifdef WIN32
|
||||
#include <codecvt>
|
||||
#endif
|
||||
|
@ -26,6 +27,10 @@ VideoComponent::VideoComponent(Window* window) :
|
|||
mConfig.showSnapshotDelay = false;
|
||||
mConfig.showSnapshotNoVideo = false;
|
||||
mConfig.startDelay = 0;
|
||||
if (mWindow->getGuiStackSize() > 1) {
|
||||
topWindow(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VideoComponent::~VideoComponent()
|
||||
|
@ -42,89 +47,12 @@ void VideoComponent::setOrigin(float originX, float originY)
|
|||
mStaticImage.setOrigin(originX, originY);
|
||||
}
|
||||
|
||||
void VideoComponent::setResize(float width, float height)
|
||||
{
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = false;
|
||||
mStaticImage.setResize(width, height);
|
||||
resize();
|
||||
}
|
||||
|
||||
void VideoComponent::setMaxSize(float width, float height)
|
||||
{
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = true;
|
||||
mStaticImage.setMaxSize(width, height);
|
||||
resize();
|
||||
}
|
||||
|
||||
Eigen::Vector2f VideoComponent::getCenter() const
|
||||
{
|
||||
return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2,
|
||||
mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
|
||||
}
|
||||
|
||||
void VideoComponent::resize()
|
||||
{
|
||||
if(!mTexture)
|
||||
return;
|
||||
|
||||
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
|
||||
|
||||
if(textureSize.isZero())
|
||||
return;
|
||||
|
||||
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
|
||||
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
|
||||
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
|
||||
// (you'll see this scattered throughout the function)
|
||||
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
|
||||
|
||||
if(mTargetIsMax)
|
||||
{
|
||||
|
||||
mSize = textureSize;
|
||||
|
||||
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
|
||||
|
||||
if(resizeScale.x() < resizeScale.y())
|
||||
{
|
||||
mSize[0] *= resizeScale.x();
|
||||
mSize[1] *= resizeScale.x();
|
||||
}else{
|
||||
mSize[0] *= resizeScale.y();
|
||||
mSize[1] *= resizeScale.y();
|
||||
}
|
||||
|
||||
// for SVG rasterization, always calculate width from rounded height (see comment above)
|
||||
mSize[1] = round(mSize[1]);
|
||||
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
|
||||
|
||||
}else{
|
||||
// if both components are set, we just stretch
|
||||
// if no components are set, we don't resize at all
|
||||
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
|
||||
|
||||
// if only one component is set, we resize in a way that maintains aspect ratio
|
||||
// for SVG rasterization, we always calculate width from rounded height (see comment above)
|
||||
if(!mTargetSize.x() && mTargetSize.y())
|
||||
{
|
||||
mSize[1] = round(mTargetSize.y());
|
||||
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||
}else if(mTargetSize.x() && !mTargetSize.y())
|
||||
{
|
||||
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
|
||||
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||
}
|
||||
}
|
||||
|
||||
// mSize.y() should already be rounded
|
||||
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
|
||||
|
||||
onSizeChanged();
|
||||
}
|
||||
|
||||
|
||||
void VideoComponent::onSizeChanged()
|
||||
{
|
||||
// Update the embeded static image
|
||||
|
@ -161,6 +89,8 @@ void VideoComponent::setImage(std::string path)
|
|||
return;
|
||||
|
||||
mStaticImage.setImage(path);
|
||||
// Make the image stretch to fill the video region
|
||||
mStaticImage.setSize(getSize());
|
||||
mFadeIn = 0.0f;
|
||||
mStaticImagePath = path;
|
||||
}
|
||||
|
|
|
@ -48,19 +48,6 @@ public:
|
|||
void onSizeChanged() override;
|
||||
void setOpacity(unsigned char opacity) override;
|
||||
|
||||
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
|
||||
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
|
||||
// Can be set before or after a video is loaded.
|
||||
// setMaxSize() and setResize() are mutually exclusive.
|
||||
void setResize(float width, float height);
|
||||
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
|
||||
|
||||
// Resize the video to be as large as possible but fit within a box of this size.
|
||||
// Can be set before or after a video is loaded.
|
||||
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
|
||||
void setMaxSize(float width, float height);
|
||||
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
|
||||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||
|
@ -72,6 +59,19 @@ public:
|
|||
|
||||
virtual void update(int deltaTime);
|
||||
|
||||
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
|
||||
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
|
||||
// Can be set before or after a video is loaded.
|
||||
// setMaxSize() and setResize() are mutually exclusive.
|
||||
virtual void setResize(float width, float height) = 0;
|
||||
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
|
||||
|
||||
// Resize the video to be as large as possible but fit within a box of this size.
|
||||
// Can be set before or after a video is loaded.
|
||||
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
|
||||
virtual void setMaxSize(float width, float height) = 0;
|
||||
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
|
||||
|
||||
private:
|
||||
// Start the video Immediately
|
||||
virtual void startVideo() = 0;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "components/VideoPlayerComponent.h"
|
||||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Settings.h"
|
||||
#include "Util.h"
|
||||
#include <signal.h>
|
||||
#include <wait.h>
|
||||
|
@ -24,6 +25,24 @@ void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans)
|
|||
VideoComponent::render(parentTrans);
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::setResize(float width, float height)
|
||||
{
|
||||
setSize(width, height);
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = false;
|
||||
mStaticImage.setSize(width, height);
|
||||
onSizeChanged();
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::setMaxSize(float width, float height)
|
||||
{
|
||||
setSize(width, height);
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = true;
|
||||
mStaticImage.setMaxSize(width, height);
|
||||
onSizeChanged();
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::startVideo()
|
||||
{
|
||||
if (!mIsPlaying) {
|
||||
|
@ -49,11 +68,13 @@ void VideoPlayerComponent::startVideo()
|
|||
{
|
||||
mPlayerPid = pid;
|
||||
// Update the playing state
|
||||
signal(SIGCHLD, catch_child);
|
||||
mIsPlaying = true;
|
||||
mFadeIn = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Find out the pixel position of the video view and build a command line for
|
||||
// omxplayer to position it in the right place
|
||||
char buf[32];
|
||||
|
@ -62,10 +83,25 @@ void VideoPlayerComponent::startVideo()
|
|||
sprintf(buf, "%d,%d,%d,%d", (int)x, (int)y, (int)(x + mSize.x()), (int)(y + mSize.y()));
|
||||
// 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[] = { "", "--win", buf, "--layer", "10000", "--loop", "--no-osd", "", NULL };
|
||||
|
||||
const char* argv[] = { "", "--layer", "10010", "--loop", "--no-osd", "--aspect-mode", "letterbox", "--vol", "0", "--win", buf, "-b", "", "", "", "", NULL };
|
||||
|
||||
// check if we want to mute the audio
|
||||
if (!Settings::getInstance()->getBool("VideoAudio"))
|
||||
{
|
||||
argv[8] = "-1000000";
|
||||
}
|
||||
|
||||
// if we are rendering a video gamelist
|
||||
if (!mTargetIsMax)
|
||||
{
|
||||
argv[6] = "stretch";
|
||||
}
|
||||
|
||||
argv[11] = mPlayingVideoPath.c_str();
|
||||
|
||||
const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", NULL };
|
||||
// Fill in the empty argument with the video path
|
||||
argv[7] = mPlayingVideoPath.c_str();
|
||||
|
||||
// Redirect stdout
|
||||
int fdin = open("/dev/null", O_RDONLY);
|
||||
int fdout = open("/dev/null", O_WRONLY);
|
||||
|
@ -73,12 +109,20 @@ void VideoPlayerComponent::startVideo()
|
|||
dup2(fdout, 1);
|
||||
// Run the omxplayer binary
|
||||
execve("/usr/bin/omxplayer.bin", (char**)argv, (char**)env);
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void catch_child(int sig_num)
|
||||
{
|
||||
/* when we get here, we know there's a zombie child waiting */
|
||||
int child_status;
|
||||
wait(&child_status);
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::stopVideo()
|
||||
{
|
||||
mIsPlaying = false;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "components/VideoComponent.h"
|
||||
|
||||
void catch_child(int sig_num);
|
||||
|
||||
class VideoPlayerComponent : public VideoComponent
|
||||
{
|
||||
public:
|
||||
|
@ -15,6 +17,17 @@ public:
|
|||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
|
||||
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
|
||||
// Can be set before or after a video is loaded.
|
||||
// setMaxSize() and setResize() are mutually exclusive.
|
||||
void setResize(float width, float height);
|
||||
|
||||
// Resize the video to be as large as possible but fit within a box of this size.
|
||||
// Can be set before or after a video is loaded.
|
||||
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
|
||||
void setMaxSize(float width, float height);
|
||||
|
||||
private:
|
||||
// Start the video Immediately
|
||||
virtual void startVideo();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Util.h"
|
||||
#include "Settings.h"
|
||||
#ifdef WIN32
|
||||
#include <codecvt>
|
||||
#endif
|
||||
|
@ -46,6 +47,82 @@ VideoVlcComponent::~VideoVlcComponent()
|
|||
{
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setResize(float width, float height)
|
||||
{
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = false;
|
||||
mStaticImage.setResize(width, height);
|
||||
resize();
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setMaxSize(float width, float height)
|
||||
{
|
||||
mTargetSize << width, height;
|
||||
mTargetIsMax = true;
|
||||
mStaticImage.setMaxSize(width, height);
|
||||
resize();
|
||||
}
|
||||
|
||||
void VideoVlcComponent::resize()
|
||||
{
|
||||
if(!mTexture)
|
||||
return;
|
||||
|
||||
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
|
||||
|
||||
if(textureSize.isZero())
|
||||
return;
|
||||
|
||||
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
|
||||
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
|
||||
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
|
||||
// (you'll see this scattered throughout the function)
|
||||
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
|
||||
|
||||
if(mTargetIsMax)
|
||||
{
|
||||
|
||||
mSize = textureSize;
|
||||
|
||||
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
|
||||
|
||||
if(resizeScale.x() < resizeScale.y())
|
||||
{
|
||||
mSize[0] *= resizeScale.x();
|
||||
mSize[1] *= resizeScale.x();
|
||||
}else{
|
||||
mSize[0] *= resizeScale.y();
|
||||
mSize[1] *= resizeScale.y();
|
||||
}
|
||||
|
||||
// for SVG rasterization, always calculate width from rounded height (see comment above)
|
||||
mSize[1] = round(mSize[1]);
|
||||
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
|
||||
|
||||
}else{
|
||||
// if both components are set, we just stretch
|
||||
// if no components are set, we don't resize at all
|
||||
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
|
||||
|
||||
// if only one component is set, we resize in a way that maintains aspect ratio
|
||||
// for SVG rasterization, we always calculate width from rounded height (see comment above)
|
||||
if(!mTargetSize.x() && mTargetSize.y())
|
||||
{
|
||||
mSize[1] = round(mTargetSize.y());
|
||||
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||
}else if(mTargetSize.x() && !mTargetSize.y())
|
||||
{
|
||||
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
|
||||
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
|
||||
}
|
||||
}
|
||||
|
||||
// mSize.y() should already be rounded
|
||||
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
|
||||
|
||||
onSizeChanged();
|
||||
}
|
||||
|
||||
void VideoVlcComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
VideoComponent::render(parentTrans);
|
||||
|
@ -55,7 +132,7 @@ void VideoVlcComponent::render(const Eigen::Affine3f& parentTrans)
|
|||
GuiComponent::renderChildren(trans);
|
||||
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
|
||||
if (mIsPlaying && mContext.valid)
|
||||
{
|
||||
float tex_offs_x = 0.0f;
|
||||
|
@ -135,6 +212,7 @@ void VideoVlcComponent::setupContext()
|
|||
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||
mContext.mutex = SDL_CreateMutex();
|
||||
mContext.valid = true;
|
||||
resize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +231,9 @@ void VideoVlcComponent::setupVLC()
|
|||
// If VLC hasn't been initialised yet then do it now
|
||||
if (!mVLC)
|
||||
{
|
||||
const char* args[] = { "--quiet" };
|
||||
const char* args[] = { "--quiet", "", "", "" };
|
||||
// check if we want to mute the audio
|
||||
|
||||
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args);
|
||||
}
|
||||
}
|
||||
|
@ -217,6 +297,11 @@ void VideoVlcComponent::startVideo()
|
|||
|
||||
// Setup the media player
|
||||
mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
|
||||
if (!Settings::getInstance()->getBool("VideoAudio"))
|
||||
{
|
||||
libvlc_audio_set_mute(mMediaPlayer, 1);
|
||||
}
|
||||
|
||||
libvlc_media_player_play(mMediaPlayer);
|
||||
libvlc_video_set_callbacks(mMediaPlayer, lock, unlock, display, (void*)&mContext);
|
||||
libvlc_video_set_format(mMediaPlayer, "RGBA", (int)mVideoWidth, (int)mVideoHeight, (int)mVideoWidth * 4);
|
||||
|
|
|
@ -33,7 +33,22 @@ public:
|
|||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
|
||||
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
|
||||
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
|
||||
// Can be set before or after a video is loaded.
|
||||
// setMaxSize() and setResize() are mutually exclusive.
|
||||
void setResize(float width, float height);
|
||||
|
||||
// Resize the video to be as large as possible but fit within a box of this size.
|
||||
// Can be set before or after a video is loaded.
|
||||
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
|
||||
void setMaxSize(float width, float height);
|
||||
|
||||
private:
|
||||
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
||||
// Used internally whenever the resizing parameters or texture change.
|
||||
void resize();
|
||||
// Start the video Immediately
|
||||
virtual void startVideo();
|
||||
// Stop the video
|
||||
|
|
1
external/pugixml
vendored
Submodule
1
external/pugixml
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d2deb420bc70369faa12785df2b5dd4d390e523d
|
Loading…
Reference in a new issue