Hyperion X11 KodiCheck (#685)

* Update X11Grabber.h

* Update ProtoConnection.h

* Update ProtoConnectionWrapper.h

* Update ProtoServer.h

* Update X11Grabber.cpp

* Update message.proto

* Update ProtoClientConnection.cpp

* Update ProtoClientConnection.h

* Update ProtoConnection.cpp

* Update ProtoConnectionWrapper.cpp

* Update ProtoServer.cpp

* Update hyperion-x11.cpp

* Update X11Wrapper.cpp

* Update X11Wrapper.h

* Update hyperiond.cpp

* Update ProtoClientConnection.cpp

* Update X11Wrapper.cpp

* Update hyperiond.cpp


Former-commit-id: a572f275b2
This commit is contained in:
Paulchen-Panther 2016-06-07 23:12:18 +02:00 committed by brindosch
parent 614131ebe6
commit f0dec4cf73
15 changed files with 235 additions and 50 deletions

View File

@ -19,7 +19,11 @@ public:
virtual ~X11Grabber();
int open();
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
bool Setup();

View File

@ -13,6 +13,8 @@
// hyperion util
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
// jsoncpp includes
#include <message.pb.h>
@ -82,6 +84,18 @@ private slots:
/// Try to connect to the Hyperion host
void connectToHost();
///
/// Slot called when new data has arrived
///
void readData();
signals:
///
/// XBMC Video Checker Message
///
void setGrabbingMode(const GrabbingMode mode);
void setVideoMode(const VideoMode videoMode);
private:
@ -109,4 +123,7 @@ private:
QTimer _timer;
QAbstractSocket::SocketState _prevSocketState;
/// The buffer used for reading data from the socket
QByteArray _receiveBuffer;
};

View File

@ -4,11 +4,13 @@
// hyperion includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
// hyperion proto includes
#include "protoserver/ProtoConnection.h"
/// This class handles callbacks from the V4L2 grabber
/// This class handles callbacks from the V4L2 and X11 grabber
class ProtoConnectionWrapper : public QObject
{
Q_OBJECT
@ -16,6 +18,13 @@ class ProtoConnectionWrapper : public QObject
public:
ProtoConnectionWrapper(const std::string & address, int priority, int duration_ms, bool skipProtoReply);
virtual ~ProtoConnectionWrapper();
signals:
///
/// Forwarding XBMC Video Checker Message
///
void setGrabbingMode(const GrabbingMode mode);
void setVideoMode(const VideoMode videoMode);
public slots:
/// Handle a single image

View File

@ -15,6 +15,8 @@
// hyperion includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
// forward decl
class ProtoClientConnection;
@ -50,6 +52,13 @@ public:
public slots:
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
signals:
///
/// Forwarding XBMC Checker
///
void grabbingMode(const GrabbingMode mode);
void videoMode(const VideoMode VideoMode);
private slots:
///
/// Slot which is called when a client tries to create a new connection

View File

@ -40,6 +40,11 @@ X11Grabber::~X11Grabber()
}
}
void X11Grabber::setVideoMode(const VideoMode videoMode)
{
_imageResampler.set3D(videoMode);
}
void X11Grabber::freeResources()
{
// Cleanup allocated resources of the X11 grab

View File

@ -79,6 +79,32 @@ void ProtoClientConnection::socketClosed()
emit connectionClosed(this);
}
void ProtoClientConnection::setGrabbingMode(const GrabbingMode mode)
{
int grabbing_mode = (int)mode;
proto::HyperionReply gMode;
// create proto message
gMode.set_type(proto::HyperionReply::GRABBING);
gMode.set_grabbing(grabbing_mode);
// send message
sendMessage(gMode);
}
void ProtoClientConnection::setVideoMode(const VideoMode videoMode)
{
int video_Mode = (int)videoMode;
proto::HyperionReply vMode;
// create proto message
vMode.set_type(proto::HyperionReply::VIDEO);
vMode.set_grabbing(video_Mode);
// send message
sendMessage(vMode);
}
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
{
// forward messages
@ -208,6 +234,7 @@ void ProtoClientConnection::sendSuccessReply()
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(true);
// send reply
@ -218,6 +245,7 @@ void ProtoClientConnection::sendErrorReply(const std::string &error)
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(false);
reply.set_error(error);

View File

@ -11,6 +11,10 @@
// Hyperion includes
#include <hyperion/Hyperion.h>
//Utils includes
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
// proto includes
#include "message.pb.h"
#include "protoserver/ProtoConnection.h"
@ -18,7 +22,7 @@
class ImageProcessor;
///
/// The Connection object created by \a ProtoServer when a new connection is establshed
/// The Connection object created by a ProtoServer when a new connection is establshed
///
class ProtoClientConnection : public QObject
{
@ -36,6 +40,13 @@ public:
/// Destructor
///
~ProtoClientConnection();
public slots:
///
/// Send XBMC Video Checker message to connected client
///
void setGrabbingMode(const GrabbingMode mode);
void setVideoMode(const VideoMode videoMode);
signals:
///

View File

@ -35,7 +35,8 @@ ProtoConnection::ProtoConnection(const std::string & a) :
_timer.setInterval(5000);
_timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()) );
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()));
connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData()));
_timer.start();
}
@ -45,6 +46,44 @@ ProtoConnection::~ProtoConnection()
_socket.close();
}
void ProtoConnection::readData()
{
_receiveBuffer += _socket.readAll();
// check if we can read a message size
if (_receiveBuffer.size() <= 4)
{
return;
}
// read the message size
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
{
return;
}
// read a message
proto::HyperionReply reply;
if (!reply.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
{
std::cerr << "PROTOCONNECTION ERROR: Unable to parse message" << std::endl;
return;
}
parseReply(reply);
// remove message data from buffer
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
}
void ProtoConnection::setSkipReply(bool skip)
{
_skipReply = skip;
@ -157,58 +196,51 @@ void ProtoConnection::sendMessage(const proto::HyperionRequest &message)
std::cerr << "PROTOCONNECTION ERROR: Error while writing data to host" << std::endl;
return;
}
if (!_skipReply)
{
// read reply data
QByteArray serializedReply;
length = -1;
while (length < 0 && serializedReply.size() < length+4)
{
// receive reply
if (!_socket.waitForReadyRead())
{
std::cerr << "PROTOCONNECTION ERROR: Error while reading data from host" << std::endl;
return;
}
serializedReply += _socket.readAll();
if (length < 0 && serializedReply.size() >= 4)
{
// read the message size
length =
((serializedReply[0]<<24) & 0xFF000000) |
((serializedReply[1]<<16) & 0x00FF0000) |
((serializedReply[2]<< 8) & 0x0000FF00) |
((serializedReply[3] ) & 0x000000FF);
}
}
// parse reply data
proto::HyperionReply reply;
reply.ParseFromArray(serializedReply.constData()+4, length);
// parse reply message
parseReply(reply);
}
}
bool ProtoConnection::parseReply(const proto::HyperionReply &reply)
{
bool success = false;
if (!reply.success())
switch (reply.type())
{
if (reply.has_error())
case proto::HyperionReply::REPLY:
{
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
if (!_skipReply)
{
if (!reply.success())
{
if (reply.has_error())
{
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
}
else
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
}
else
{
success = true;
}
}
break;
}
else
case proto::HyperionReply::GRABBING:
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
int grabbing = reply.has_grabbing() ? reply.grabbing() : 6;
GrabbingMode gMode = (GrabbingMode)grabbing;
emit setGrabbingMode(gMode);
break;
}
case proto::HyperionReply::VIDEO:
{
int video = reply.has_video() ? reply.video() : 0;
VideoMode vMode = (VideoMode)video;
emit setVideoMode(vMode);
break;
}
}
return success;
}

View File

@ -7,6 +7,8 @@ ProtoConnectionWrapper::ProtoConnectionWrapper(const std::string & address, int
_connection(address)
{
_connection.setSkipReply(skipProtoReply);
connect(&_connection, SIGNAL(setGrabbingMode(GrabbingMode)), this, SIGNAL(setGrabbingMode(GrabbingMode)));
connect(&_connection, SIGNAL(setVideoMode(VideoMode)), this, SIGNAL(setVideoMode(VideoMode)));
}
ProtoConnectionWrapper::~ProtoConnectionWrapper()

View File

@ -64,6 +64,10 @@ void ProtoServer::newConnection()
// register slot for cleaning up after the connection closed
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
// register forward signal for xbmc checker
connect(this, SIGNAL(grabbingMode(GrabbingMode)), connection, SLOT(setGrabbingMode(GrabbingMode)));
connect(this, SIGNAL(videoMode(VideoMode)), connection, SLOT(setVideoMode(VideoMode)));
}
}

View File

@ -61,9 +61,24 @@ message ClearRequest {
}
message HyperionReply {
enum Type {
REPLY = 1;
GRABBING = 2;
VIDEO = 3;
}
// Identifies which field is filled in.
required Type type = 1;
// flag indication success or failure
required bool success = 1;
optional bool success = 2;
// string indicating the reason for failure (if applicable)
optional string error = 2;
optional string error = 3;
// XBMC Video Checker Proto Messages for Grabbing mode
optional int32 grabbing = 4;
// XBMC Video Checker Proto Messages for Video mode
optional int32 video = 5;
}

View File

@ -39,3 +39,26 @@ void X11Wrapper::capture()
const Image<ColorRgb> & screenshot = _grabber.grab();
emit sig_screenshot(screenshot);
}
void X11Wrapper::setGrabbingMode(const GrabbingMode mode)
{
switch (mode)
{
case GRABBINGMODE_VIDEO:
case GRABBINGMODE_PAUSE:
case GRABBINGMODE_AUDIO:
case GRABBINGMODE_PHOTO:
case GRABBINGMODE_MENU:
case GRABBINGMODE_INVALID:
start();
break;
case GRABBINGMODE_OFF:
stop();
break;
}
}
void X11Wrapper::setVideoMode(const VideoMode mode)
{
_grabber.setVideoMode(mode);
}

View File

@ -5,6 +5,10 @@
// Hyperion-X11 includes
#include <grabber/X11Grabber.h>
//Utils includes
#include <utils/GrabbingMode.h>
#include <utils/VideoMode.h>
class X11Wrapper : public QObject
{
Q_OBJECT
@ -25,6 +29,19 @@ public:
signals:
void sig_screenshot(const Image<ColorRgb> & screenshot);
public slots:
///
/// Set the grabbing mode
/// @param[in] mode The new grabbing mode
///
void setGrabbingMode(const GrabbingMode mode);
///
/// Set the video mode (2D/3D)
/// @param[in] mode The new video mode
///
void setVideoMode(const VideoMode videoMode);
private slots:
///
/// Performs a single screenshot capture and publishes the capture screenshot on the screenshot

View File

@ -104,6 +104,10 @@ int main(int argc, char ** argv)
// Connect the screen capturing to the proto processing
QObject::connect(&x11Wrapper, SIGNAL(sig_screenshot(const Image<ColorRgb> &)), &protoWrapper, SLOT(receiveImage(Image<ColorRgb>)));
// Connect the XBMC Video Checker to the proto processing
QObject::connect(&protoWrapper, SIGNAL(setGrabbingMode(GrabbingMode)), &x11Wrapper, SLOT(setGrabbingMode(GrabbingMode)));
QObject::connect(&protoWrapper, SIGNAL(setVideoMode(VideoMode)), &x11Wrapper, SLOT(setVideoMode(VideoMode)));
// Start the capturing
x11Wrapper.start();

View File

@ -187,7 +187,7 @@ void startXBMCVideoChecker(const Json::Value &config, XBMCVideoChecker* &xbmcVid
}
}
void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer)
void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonServer* &jsonServer, ProtoServer* &protoServer, BoblightServer* &boblightServer, XBMCVideoChecker* &xbmcVideoChecker)
{
// Create Json server if configuration is present
if (config.isMember("jsonServer"))
@ -216,6 +216,11 @@ void startNetworkServices(const Json::Value &config, Hyperion &hyperion, JsonSer
{
const Json::Value & protoServerConfig = config["protoServer"];
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt() );
if (xbmcVideoChecker != nullptr)
{
QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), protoServer, SIGNAL(grabbingMode(GrabbingMode)));
QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), protoServer, SIGNAL(videoMode(VideoMode)));
}
std::cout << "INFO: Proto server created and started on port " << protoServer->getPort() << std::endl;
#ifdef ENABLE_ZEROCONF
@ -481,7 +486,7 @@ int main(int argc, char** argv)
JsonServer * jsonServer = nullptr;
ProtoServer * protoServer = nullptr;
BoblightServer * boblightServer = nullptr;
startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer);
startNetworkServices(config, hyperion, jsonServer, protoServer, boblightServer, xbmcVideoChecker);
// ---- grabber -----