Adding files
This commit is contained in:
parent
0193df7402
commit
4aa7578cf7
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
|
|
||||||
|
project(Hyperion_Grabber_X11_QT VERSION 0.1 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
|
|
||||||
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5Network REQUIRED)
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -lXrender -lXdamage")
|
||||||
|
include_directories(${X11_INCLUDE_DIR})
|
||||||
|
add_executable(${PROJECT_NAME} "main.cpp" "hgx11.h" "hgx11.cpp" "hgx11net.h" "hgx11net.cpp" "hgx11damage.h" "hgx11damage.cpp" "hgx11grab.h" "hgx11grab.cpp")
|
||||||
|
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::Widgets ${X11_LIBRARIES})
|
||||||
68
hgx11.cpp
Normal file
68
hgx11.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "hgx11.h"
|
||||||
|
|
||||||
|
// public
|
||||||
|
|
||||||
|
hgx11::hgx11(QString addr, QString port, QString scale, QString frameskip, QString inactiveTime)
|
||||||
|
{
|
||||||
|
_addr_m = (addr.isEmpty() || addr.isNull()) ? "localhost" : addr;
|
||||||
|
_port_m = (port.toInt() > 65535 || port.toInt() < 1) ? "19444" : port;
|
||||||
|
_scale_m = (scale.toInt() < 1 || scale.toInt() > 1000) ? "4" : scale;
|
||||||
|
_frameskip_m = (frameskip.toInt() > 0 && frameskip.toInt() < 256) ? frameskip : "0";
|
||||||
|
_inactiveTime_m = (inactiveTime.toInt() > 0 ? QString::number(inactiveTime.toInt() * 1000) : "0");
|
||||||
|
|
||||||
|
_grabber_p = new hgx11grab(_scale_m.toInt(), _frameskip_m.toUShort());
|
||||||
|
_hclient_p = new hgx11net(_addr_m.toStdString().c_str(), _port_m.toUShort());
|
||||||
|
_damage_p = new hgx11damage();
|
||||||
|
|
||||||
|
_hclient_p->imgWidth = QString::number(_grabber_p->getDest_width());
|
||||||
|
_hclient_p->imgHeight = QString::number(_grabber_p->getDest_height());
|
||||||
|
|
||||||
|
_damage_p->start();
|
||||||
|
|
||||||
|
connect(_damage_p, SIGNAL(damageDetected()), _grabber_p, SLOT(grabFrame()));
|
||||||
|
connect(_grabber_p, SIGNAL(scaleChanged()), this, SLOT(_setImgSize()));
|
||||||
|
connect(_grabber_p, SIGNAL(imageCreated()), this, SLOT(_sendImage()));
|
||||||
|
|
||||||
|
if (_inactiveTime_m.toInt()) {
|
||||||
|
_timer_p = new QTimer(this);
|
||||||
|
connect(_timer_p, SIGNAL(timeout()), this, SLOT(_inActivity()));
|
||||||
|
_timer_p->start(_inactiveTime_m.toInt());
|
||||||
|
connect(_damage_p, SIGNAL(damageDetected()), this, SLOT(_activity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hgx11::~hgx11()
|
||||||
|
{
|
||||||
|
delete _hclient_p;
|
||||||
|
_hclient_p = nullptr;
|
||||||
|
_damage_p->terminate();
|
||||||
|
while (!_damage_p->isFinished()) {}
|
||||||
|
delete _damage_p;
|
||||||
|
_damage_p = nullptr;
|
||||||
|
delete _grabber_p;
|
||||||
|
_grabber_p = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private slots
|
||||||
|
|
||||||
|
void hgx11::_sendImage()
|
||||||
|
{
|
||||||
|
_hclient_p->sendImage(&_grabber_p->imgdata_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11::_inActivity()
|
||||||
|
{
|
||||||
|
_hclient_p->clearLeds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11::_activity()
|
||||||
|
{
|
||||||
|
_timer_p->stop();
|
||||||
|
_timer_p->start(_inactiveTime_m.toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11::_setImgSize()
|
||||||
|
{
|
||||||
|
_hclient_p->imgWidth = QString::number(_grabber_p->getDest_width());
|
||||||
|
_hclient_p->imgHeight = QString::number(_grabber_p->getDest_height());
|
||||||
|
}
|
||||||
41
hgx11.h
Normal file
41
hgx11.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef HGX11_H
|
||||||
|
#define HGX11_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
#include "hgx11grab.h"
|
||||||
|
#include "hgx11net.h"
|
||||||
|
#include "hgx11damage.h"
|
||||||
|
|
||||||
|
|
||||||
|
class hgx11 : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
hgx11(QString, QString, QString, QString, QString);
|
||||||
|
~hgx11();
|
||||||
|
|
||||||
|
private:
|
||||||
|
hgx11damage *_damage_p;
|
||||||
|
hgx11grab *_grabber_p;
|
||||||
|
hgx11net *_hclient_p;
|
||||||
|
QTimer *_timer_p;
|
||||||
|
|
||||||
|
QString _addr_m;
|
||||||
|
QString _port_m;
|
||||||
|
QString _scale_m;
|
||||||
|
QString _frameskip_m;
|
||||||
|
QString _inactiveTime_m;
|
||||||
|
QString _destWidth_m;
|
||||||
|
QString _destHeight_m;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void _sendImage();
|
||||||
|
void _inActivity();
|
||||||
|
void _activity();
|
||||||
|
void _setImgSize();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HGX11_H
|
||||||
34
hgx11damage.cpp
Normal file
34
hgx11damage.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "hgx11damage.h"
|
||||||
|
|
||||||
|
// public
|
||||||
|
|
||||||
|
hgx11damage::hgx11damage()
|
||||||
|
{
|
||||||
|
_display_p = XOpenDisplay(nullptr);
|
||||||
|
if(!_display_p){
|
||||||
|
qCritical() << "failed to open x display";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Window window = DefaultRootWindow(_display_p);
|
||||||
|
_damage_m = XDamageCreate(_display_p, window, XDamageReportNonEmpty);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
hgx11damage::~hgx11damage()
|
||||||
|
{
|
||||||
|
_loop_m = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected
|
||||||
|
|
||||||
|
void hgx11damage::_monitor()
|
||||||
|
{
|
||||||
|
if(!_display_p){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (_loop_m) {
|
||||||
|
XNextEvent(_display_p, &_event_m);
|
||||||
|
emit damageDetected();
|
||||||
|
XDamageSubtract(_display_p ,_damage_m, None, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
hgx11damage.h
Normal file
34
hgx11damage.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef HGX11DAMAGE_H
|
||||||
|
#define HGX11DAMAGE_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <X11/extensions/Xdamage.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
class hgx11damage : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
hgx11damage();
|
||||||
|
~hgx11damage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Display *_display_p;
|
||||||
|
XEvent _event_m;
|
||||||
|
Damage _damage_m;
|
||||||
|
bool _loop_m = true;
|
||||||
|
|
||||||
|
void _monitor();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run() {
|
||||||
|
_monitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void damageDetected();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HGX11DAMAGE_H
|
||||||
206
hgx11grab.cpp
Normal file
206
hgx11grab.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
#include "hgx11grab.h"
|
||||||
|
|
||||||
|
// public
|
||||||
|
|
||||||
|
hgx11grab::hgx11grab(int scaleDivisor, ushort frameSkip)
|
||||||
|
{
|
||||||
|
_frameSkip_m = frameSkip;
|
||||||
|
_x11Display_p = XOpenDisplay(":0");
|
||||||
|
if (_x11Display_p == nullptr) {
|
||||||
|
qCritical() << "Failed to open X11 display.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_window_m = DefaultRootWindow(_x11Display_p);
|
||||||
|
|
||||||
|
bool _XShmAvailable = XShmQueryExtension(_x11Display_p);
|
||||||
|
if (!_XShmAvailable) {
|
||||||
|
qCritical() << "Xshm is: not available.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dummy, pixmaps_supported;
|
||||||
|
|
||||||
|
bool _XRenderAvailable = XRenderQueryExtension(_x11Display_p, &dummy, &dummy);
|
||||||
|
if (!_XRenderAvailable) {
|
||||||
|
qCritical() << "XRender is not available.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XShmQueryVersion(_x11Display_p, &dummy, &dummy, &pixmaps_supported);
|
||||||
|
bool _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display_p) == ZPixmap;
|
||||||
|
if (!_XShmPixmapAvailable) {
|
||||||
|
qCritical() << "XshmPixMap is: not available.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_getWinAttr()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_destWidth_m = int(_srcWidth_m / scaleDivisor);
|
||||||
|
_destHeight_m = int(_srcHeight_m / scaleDivisor);
|
||||||
|
|
||||||
|
_imgSize_m = _destHeight_m * _destWidth_m * 4;
|
||||||
|
|
||||||
|
memset(&_pictAttr_m, 0, sizeof(_pictAttr_m));
|
||||||
|
_pictAttr_m.repeat = RepeatNone;
|
||||||
|
|
||||||
|
_mTransform_m.matrix[0][0] = XDoubleToFixed(1.0);
|
||||||
|
_mTransform_m.matrix[0][1] = 0;
|
||||||
|
_mTransform_m.matrix[0][2] = 0;
|
||||||
|
_mTransform_m.matrix[1][0] = 0;
|
||||||
|
_mTransform_m.matrix[1][1] = XDoubleToFixed(1.0);
|
||||||
|
_mTransform_m.matrix[1][2] = 0;
|
||||||
|
_mTransform_m.matrix[2][0] = 0;
|
||||||
|
_mTransform_m.matrix[2][1] = 0;
|
||||||
|
_setScale();
|
||||||
|
|
||||||
|
connect(this, SIGNAL(scaleChanged()), this, SLOT(_changeScale()));
|
||||||
|
}
|
||||||
|
|
||||||
|
hgx11grab::~hgx11grab()
|
||||||
|
{
|
||||||
|
if (_x11Display_p != nullptr) {
|
||||||
|
_freeResources();
|
||||||
|
XCloseDisplay(_x11Display_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hgx11grab::getDest_height() const
|
||||||
|
{
|
||||||
|
return _destHeight_m;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hgx11grab::getDest_width() const
|
||||||
|
{
|
||||||
|
return _destWidth_m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private
|
||||||
|
|
||||||
|
void hgx11grab::_grabFrame()
|
||||||
|
{
|
||||||
|
if (!_getWinAttr()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_xImage_p = XShmCreateImage(
|
||||||
|
_x11Display_p, _windowAttr_m.visual,
|
||||||
|
uint(_windowAttr_m.depth), ZPixmap, nullptr, &_shminfo_m,
|
||||||
|
uint(_destWidth_m), uint(_destHeight_m)
|
||||||
|
);
|
||||||
|
|
||||||
|
_shminfo_m.shmid = shmget(IPC_PRIVATE, ulong(_xImage_p->bytes_per_line * _xImage_p->height), IPC_CREAT|0777);
|
||||||
|
_xImage_p->data = reinterpret_cast<char *>(shmat(_shminfo_m.shmid, nullptr, 0));
|
||||||
|
_shminfo_m.shmaddr = _xImage_p->data;
|
||||||
|
_shminfo_m.readOnly = false;
|
||||||
|
|
||||||
|
XShmAttach(_x11Display_p, &_shminfo_m);
|
||||||
|
_pixmap_m = XShmCreatePixmap(_x11Display_p, _window_m, _xImage_p->data, &_shminfo_m, uint(_destWidth_m), uint(_destHeight_m), uint(_windowAttr_m.depth));
|
||||||
|
|
||||||
|
_dstFormat_p = XRenderFindVisualFormat(_x11Display_p, _windowAttr_m.visual);
|
||||||
|
_srcFormat_p = XRenderFindVisualFormat(_x11Display_p, _windowAttr_m.visual);
|
||||||
|
|
||||||
|
_srcPicture_m = XRenderCreatePicture(_x11Display_p, _window_m, _srcFormat_p, CPRepeat, &_pictAttr_m);
|
||||||
|
_dstPicture_m = XRenderCreatePicture(_x11Display_p, _pixmap_m, _dstFormat_p, CPRepeat, &_pictAttr_m);
|
||||||
|
|
||||||
|
XRenderSetPictureFilter(_x11Display_p, _srcPicture_m, "bilinear", nullptr, 0);
|
||||||
|
XRenderSetPictureTransform (_x11Display_p, _srcPicture_m, &_mTransform_m);
|
||||||
|
|
||||||
|
XRenderComposite(
|
||||||
|
_x11Display_p, // *dpy,
|
||||||
|
PictOpSrc, // op,
|
||||||
|
_srcPicture_m, // src
|
||||||
|
None, // mask
|
||||||
|
_dstPicture_m, // dst
|
||||||
|
0, // src_x
|
||||||
|
0, // src_y
|
||||||
|
0, // mask_x
|
||||||
|
0, // mask_y
|
||||||
|
0, // dst_x
|
||||||
|
0, // dst_y
|
||||||
|
uint(_destWidth_m), // width
|
||||||
|
uint(_destHeight_m) // height
|
||||||
|
);
|
||||||
|
|
||||||
|
XSync(_x11Display_p, false);
|
||||||
|
|
||||||
|
XShmGetImage(_x11Display_p, _pixmap_m, _xImage_p, 0, 0, 0x00FFFFFF);
|
||||||
|
|
||||||
|
if (_xImage_p == nullptr) {
|
||||||
|
qWarning() << "Failed to get image from X11 server.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgdata_m.clear();
|
||||||
|
|
||||||
|
if (_xImage_p->byte_order == 0) { // BGR
|
||||||
|
for (int i = 0; i < _imgSize_m; i += 4) {
|
||||||
|
imgdata_m.append(_xImage_p->data[i+2]);
|
||||||
|
imgdata_m.append(_xImage_p->data[i+1]);
|
||||||
|
imgdata_m.append(_xImage_p->data[i]);
|
||||||
|
}
|
||||||
|
} else { // RGB
|
||||||
|
for (int i = 0; i < _imgSize_m; i += 4) {
|
||||||
|
imgdata_m.append(_xImage_p->data[i]);
|
||||||
|
imgdata_m.append(_xImage_p->data[i+1]);
|
||||||
|
imgdata_m.append(_xImage_p->data[i+2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hgx11grab::_getWinAttr()
|
||||||
|
{
|
||||||
|
if (XGetWindowAttributes(_x11Display_p, _window_m, &_windowAttr_m) == 0) {
|
||||||
|
qWarning() << "Failed to obtain X11 window attributes.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (_srcWidth_m != _windowAttr_m.width || _srcHeight_m != _windowAttr_m.height) {
|
||||||
|
if (0 != _srcWidth_m) {
|
||||||
|
_freeResources();
|
||||||
|
}
|
||||||
|
_srcWidth_m = _windowAttr_m.width;
|
||||||
|
_srcHeight_m = _windowAttr_m.height;
|
||||||
|
emit scaleChanged();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11grab::_freeResources()
|
||||||
|
{
|
||||||
|
XDestroyImage(_xImage_p);
|
||||||
|
XShmDetach(_x11Display_p, &_shminfo_m);
|
||||||
|
shmdt(_shminfo_m.shmaddr);
|
||||||
|
shmctl(_shminfo_m.shmid, IPC_RMID, nullptr);
|
||||||
|
XRenderFreePicture(_x11Display_p, _srcPicture_m);
|
||||||
|
XRenderFreePicture(_x11Display_p, _dstPicture_m);
|
||||||
|
XFreePixmap(_x11Display_p, _pixmap_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11grab::_setScale()
|
||||||
|
{
|
||||||
|
_scale_m = (1.0 / (double(_srcWidth_m) / double(_destWidth_m)));
|
||||||
|
_mTransform_m.matrix[2][2] = XDoubleToFixed(_scale_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public slots
|
||||||
|
|
||||||
|
void hgx11grab::grabFrame()
|
||||||
|
{
|
||||||
|
if (_frameCount_m++ < _frameSkip_m) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_frameCount_m = 0;
|
||||||
|
_grabFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
// private slots
|
||||||
|
|
||||||
|
void hgx11grab::_changeScale()
|
||||||
|
{
|
||||||
|
_imgSize_m = _destHeight_m * _destWidth_m * 4;
|
||||||
|
_setScale();
|
||||||
|
}
|
||||||
61
hgx11grab.h
Normal file
61
hgx11grab.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef HGX11GRAB_H
|
||||||
|
#define HGX11GRAB_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
|
#include <X11/extensions/XShm.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
|
||||||
|
class hgx11grab : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QByteArray imgdata_m;
|
||||||
|
|
||||||
|
hgx11grab(int, ushort);
|
||||||
|
~hgx11grab();
|
||||||
|
|
||||||
|
int getDest_width() const;
|
||||||
|
int getDest_height() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Display *_x11Display_p;
|
||||||
|
Window _window_m;
|
||||||
|
Picture _srcPicture_m;
|
||||||
|
Picture _dstPicture_m;
|
||||||
|
Pixmap _pixmap_m;
|
||||||
|
XImage *_xImage_p;
|
||||||
|
XRenderPictFormat *_srcFormat_p;
|
||||||
|
XRenderPictFormat *_dstFormat_p;
|
||||||
|
XRenderPictureAttributes _pictAttr_m;
|
||||||
|
XShmSegmentInfo _shminfo_m;
|
||||||
|
XTransform _mTransform_m;
|
||||||
|
XWindowAttributes _windowAttr_m;
|
||||||
|
int _srcWidth_m = 0;
|
||||||
|
int _srcHeight_m = 0;
|
||||||
|
int _destWidth_m;
|
||||||
|
int _destHeight_m;
|
||||||
|
int _imgSize_m;
|
||||||
|
double _scale_m;
|
||||||
|
ushort _frameCount_m = 255;
|
||||||
|
ushort _frameSkip_m = 0;
|
||||||
|
|
||||||
|
void _grabFrame();
|
||||||
|
bool _getWinAttr();
|
||||||
|
void _freeResources();
|
||||||
|
void _setScale();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void imageCreated();
|
||||||
|
void scaleChanged();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void grabFrame();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void _changeScale();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HGX11GRAB_H
|
||||||
86
hgx11net.cpp
Normal file
86
hgx11net.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "hgx11net.h"
|
||||||
|
|
||||||
|
// public
|
||||||
|
|
||||||
|
hgx11net::hgx11net(const char *host, ushort port)
|
||||||
|
{
|
||||||
|
_sock_p = new QTcpSocket(this);
|
||||||
|
connect(_sock_p, SIGNAL(disconnected()), this, SLOT(_disconnected()));
|
||||||
|
_host_m = host;
|
||||||
|
_port_m = port;
|
||||||
|
this->_connectHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
hgx11net::~hgx11net()
|
||||||
|
{
|
||||||
|
clearLeds();
|
||||||
|
_sock_p->disconnectFromHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11net::clearLeds()
|
||||||
|
{
|
||||||
|
if (!_isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_sock_p->write("{\"command\": \"clearall\"}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11net::setLedColor(quint8 R, quint8 G, quint8 B)
|
||||||
|
{
|
||||||
|
if (!_isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_cmd_m.clear();
|
||||||
|
_cmd_m.append("{\"color\":[");
|
||||||
|
_cmd_m.append(QString::number(R));
|
||||||
|
_cmd_m.append(",");
|
||||||
|
_cmd_m.append(QString::number(G));
|
||||||
|
_cmd_m.append(",");
|
||||||
|
_cmd_m.append(QString::number(B));
|
||||||
|
_cmd_m.append("],\"command\":\"color\",\"priority\":100}}\n");
|
||||||
|
_sock_p->write(_cmd_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private
|
||||||
|
|
||||||
|
bool hgx11net::_isConnected()
|
||||||
|
{
|
||||||
|
return (_sock_p->state() == QAbstractSocket::ConnectedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hgx11net::_connectHost()
|
||||||
|
{
|
||||||
|
_sock_p->connectToHost(_host_m, _port_m);
|
||||||
|
if(!_sock_p->waitForConnected(5000)) {
|
||||||
|
qWarning() << "hxgfnet Error: " << _sock_p->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// public slots
|
||||||
|
|
||||||
|
void hgx11net::sendImage(QByteArray *imgdata)
|
||||||
|
{
|
||||||
|
if (!_isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_cmd_m.clear();
|
||||||
|
_cmd_m.append("{\"command\":\"image\",\"imagedata\":\"");
|
||||||
|
_cmd_m.append(imgdata->toBase64());
|
||||||
|
_cmd_m.append("\",\"imageheight\":");
|
||||||
|
_cmd_m.append(imgHeight);
|
||||||
|
_cmd_m.append(",\"imagewidth\":");
|
||||||
|
_cmd_m.append(imgWidth);
|
||||||
|
_cmd_m.append(",\"priority\":100}\n");
|
||||||
|
_sock_p->write(_cmd_m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private slots
|
||||||
|
|
||||||
|
void hgx11net::_disconnected()
|
||||||
|
{
|
||||||
|
while (!_isConnected()) {
|
||||||
|
_connectHost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
39
hgx11net.h
Normal file
39
hgx11net.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef HGX11NET_H
|
||||||
|
#define HGX11NET_H
|
||||||
|
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
#include <QString>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class hgx11net : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QString imgWidth;
|
||||||
|
QString imgHeight;
|
||||||
|
|
||||||
|
hgx11net(const char *, ushort);
|
||||||
|
~hgx11net();
|
||||||
|
|
||||||
|
void clearLeds();
|
||||||
|
void setLedColor(quint8, quint8, quint8);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpSocket *_sock_p;
|
||||||
|
QByteArray _cmd_m;
|
||||||
|
const char *_host_m;
|
||||||
|
quint16 _port_m;
|
||||||
|
|
||||||
|
void _connectHost();
|
||||||
|
bool _isConnected();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void sendImage(QByteArray *);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void _disconnected();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HGX11NET_H
|
||||||
67
main.cpp
Normal file
67
main.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "hgx11.h"
|
||||||
|
|
||||||
|
static hgx11 *grab;
|
||||||
|
static QCoreApplication *qapp;
|
||||||
|
|
||||||
|
static void quit(int sig)
|
||||||
|
{
|
||||||
|
grab->~hgx11();
|
||||||
|
qapp->exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
qapp = new QCoreApplication(argc, argv);
|
||||||
|
signal(SIGINT, quit);
|
||||||
|
signal(SIGTERM, quit);
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("hgx11");
|
||||||
|
QCoreApplication::setApplicationVersion("0.1");
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription("X11 grabber for Hyperion using QT");
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addVersionOption();
|
||||||
|
QCommandLineOption address(QStringList() << "a" << "address",
|
||||||
|
QCoreApplication::translate("main", "Address to the hyperion json server. (ex. 127.0.0.1)"),
|
||||||
|
QCoreApplication::translate("main", "hyperion address")
|
||||||
|
);
|
||||||
|
parser.addOption(address);
|
||||||
|
QCommandLineOption port(QStringList() << "p" << "port",
|
||||||
|
QCoreApplication::translate("main", "Port for the hyperion json server. (ex. 19444)"),
|
||||||
|
QCoreApplication::translate("main", "hyperion port")
|
||||||
|
);
|
||||||
|
parser.addOption(port);
|
||||||
|
QCommandLineOption scale(QStringList() << "s" << "scale",
|
||||||
|
QCoreApplication::translate("main", "Divisor used to scale your screen resolution (ex. 8 ; if your screen is 1920x1080, the result image sent to hyperion is 240x135"),
|
||||||
|
QCoreApplication::translate("main", "scale dividor")
|
||||||
|
);
|
||||||
|
parser.addOption(scale);
|
||||||
|
QCommandLineOption frameskip(QStringList() << "f" << "frameskip",
|
||||||
|
QCoreApplication::translate("main", "How many X11 frames to skip over. (ex. 4 ; 1 frame will be scaled and sent to hyperion and 4 will be ignored)"),
|
||||||
|
QCoreApplication::translate("main", "X11 frames to skip")
|
||||||
|
);
|
||||||
|
parser.addOption(frameskip);
|
||||||
|
QCommandLineOption inactiveTime(QStringList() << "i" << "inactive",
|
||||||
|
QCoreApplication::translate("main", "How many seconds after the screen has not changed to turn off the LED's. Set to 0 to disable."),
|
||||||
|
QCoreApplication::translate("main", "seconds before turning off LEDs")
|
||||||
|
);
|
||||||
|
parser.addOption(inactiveTime);
|
||||||
|
parser.process(*qapp);
|
||||||
|
|
||||||
|
if (!parser.isSet("address")) {
|
||||||
|
qWarning() << "Hyperion address missing.";
|
||||||
|
parser.showHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser.isSet("port")) {
|
||||||
|
qWarning() << "Hyperion port missing.";
|
||||||
|
parser.showHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
grab = new hgx11(parser.value("address"), parser.value("port"), parser.value("scale"), parser.value("frameskip"), parser.value("inactive"));
|
||||||
|
return qapp->exec();
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user