ES-DE/es-core/src/components/VideoPlayerComponent.cpp

200 lines
4.9 KiB
C++
Raw Normal View History

#ifdef _RPI_
#include "components/VideoPlayerComponent.h"
#include <boost/algorithm/string/predicate.hpp>
#include "AudioManager.h"
#include "Renderer.h"
#include "ThemeData.h"
#include "Settings.h"
#include "Util.h"
#include <signal.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
class VolumeControl
{
public:
static std::shared_ptr<VolumeControl> & getInstance();
int getVolume() const;
};
VideoPlayerComponent::VideoPlayerComponent(Window* window, std::string path) :
VideoComponent(window),
mPlayerPid(-1),
subtitlePath(path)
{
}
VideoPlayerComponent::~VideoPlayerComponent()
{
stopVideo();
}
void VideoPlayerComponent::render(const Transform4x4f& parentTrans)
{
VideoComponent::render(parentTrans);
2017-06-13 22:57:18 +00:00
if (!mIsPlaying || mPlayerPid == -1)
VideoComponent::renderSnapshot(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)
{
mVideoWidth = 0;
mVideoHeight = 0;
std::string path(mVideoPath.c_str());
// Make sure we have a video path
if ((path.size() > 0) && (mPlayerPid == -1))
{
// 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, 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();
if (pid == -1)
{
// Failed
mPlayingVideoPath = "";
}
else if (pid > 0)
{
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];
float x = mPosition.x() - (mOrigin.x() * mSize.x());
float y = mPosition.y() - (mOrigin.y() * mSize.y());
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[] = { "", "--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") || (float)VolumeControl::getInstance()->getVolume() == 0)
{
argv[8] = "-1000000";
}
else
{
float percentVolume = (float)VolumeControl::getInstance()->getVolume();
int OMXVolume = (int)((percentVolume-98)*105);
argv[8] = std::to_string(OMXVolume).c_str();
}
// test if there's a path for possible subtitles, meaning we're a screensaver video
if (!subtitlePath.empty())
{
// 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();
//const char* argv[] = args;
const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", NULL };
// Redirect stdout
int fdin = open("/dev/null", O_RDONLY);
int fdout = open("/dev/null", O_WRONLY);
dup2(fdin, 0);
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;
mStartDelayed = false;
// Stop the player process
if (mPlayerPid != -1)
{
int status;
kill(mPlayerPid, SIGKILL);
waitpid(mPlayerPid, &status, WNOHANG);
mPlayerPid = -1;
}
}
#endif