Feature/CEC detection (#877)

* Add CEC functionality

* Initial commit

* removed libCEC from the system skip list

Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
This commit is contained in:
Murat Seker 2020-07-20 20:06:41 +02:00 committed by GitHub
parent a3ce4fa706
commit c124e2136a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 651 additions and 89 deletions

View File

@ -50,17 +50,19 @@ SET ( DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF )
SET ( DEFAULT_TESTS OFF ) SET ( DEFAULT_TESTS OFF )
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" ) IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
SET ( DEFAULT_V4L2 ON ) SET ( DEFAULT_V4L2 ON )
SET ( DEFAULT_SPIDEV ON ) SET ( DEFAULT_SPIDEV ON )
SET ( DEFAULT_TINKERFORGE ON) SET ( DEFAULT_TINKERFORGE ON )
SET ( DEFAULT_FB ON ) SET ( DEFAULT_FB ON )
SET ( DEFAULT_USB_HID ON ) SET ( DEFAULT_USB_HID ON )
SET ( DEFAULT_CEC ON )
ELSE() ELSE()
SET ( DEFAULT_V4L2 OFF ) SET ( DEFAULT_V4L2 OFF )
SET ( DEFAULT_FB OFF ) SET ( DEFAULT_FB OFF )
SET ( DEFAULT_SPIDEV OFF ) SET ( DEFAULT_SPIDEV OFF )
SET ( DEFAULT_TINKERFORGE OFF) SET ( DEFAULT_TINKERFORGE OFF )
SET ( DEFAULT_USB_HID OFF ) SET ( DEFAULT_USB_HID OFF )
SET ( DEFAULT_CEC OFF )
ENDIF() ENDIF()
if ( NOT DEFINED PLATFORM ) if ( NOT DEFINED PLATFORM )
@ -173,6 +175,9 @@ message(STATUS "ENABLE_AVAHI = " ${ENABLE_AVAHI})
option(ENABLE_USB_HID "Enable the libusb and hid devices" ${DEFAULT_USB_HID} ) option(ENABLE_USB_HID "Enable the libusb and hid devices" ${DEFAULT_USB_HID} )
message(STATUS "ENABLE_USB_HID = ${ENABLE_USB_HID}") message(STATUS "ENABLE_USB_HID = ${ENABLE_USB_HID}")
option(ENABLE_CEC "Enable the libcec and CEC control" ${DEFAULT_CEC} )
message(STATUS "ENABLE_CEC = ${ENABLE_CEC}")
option(ENABLE_X11 "Enable the X11 grabber" ${DEFAULT_X11}) option(ENABLE_X11 "Enable the X11 grabber" ${DEFAULT_X11})
message(STATUS "ENABLE_X11 = ${ENABLE_X11}") message(STATUS "ENABLE_X11 = ${ENABLE_X11}")

View File

@ -40,7 +40,7 @@ wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/
``` ```
sudo apt-get update sudo apt-get update
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libcec-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev
``` ```
**on RPI you need the videocore IV headers** **on RPI you need the videocore IV headers**

View File

@ -4,14 +4,14 @@ Use a clean Raspbian Stretch Lite (on target) and Ubuntu 18/19 (on host) to exec
## On the Target system (here Raspberry Pi) ## On the Target system (here Raspberry Pi)
Install required additional packages. Install required additional packages.
``` ```
sudo apt-get install qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite aptitude qt5-default rsync libssl-dev zlib1g-dev sudo apt-get install qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libcec-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite aptitude qt5-default rsync libssl-dev zlib1g-dev
``` ```
## On the Host system (here Ubuntu) ## On the Host system (here Ubuntu)
Update the Ubuntu environment to the latest stage and install required additional packages. Update the Ubuntu environment to the latest stage and install required additional packages.
``` ```
sudo apt-get update sudo apt-get update
sudo apt-get upgrade sudo apt-get upgrade
sudo apt-get -qq -y install git rsync cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev sudo apt-get -qq -y install git rsync cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libcec-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev
``` ```
Refine the target IP or hostname, plus userID as required and set-up cross-compilation environment: Refine the target IP or hostname, plus userID as required and set-up cross-compilation environment:

View File

@ -33,6 +33,9 @@
// Define to enable avahi // Define to enable avahi
#cmakedefine ENABLE_AVAHI #cmakedefine ENABLE_AVAHI
// Define to enable cec
#cmakedefine ENABLE_CEC
// Define to enable the usb / hid devices // Define to enable the usb / hid devices
#cmakedefine ENABLE_USB_HID #cmakedefine ENABLE_USB_HID

View File

@ -636,6 +636,8 @@
"edt_conf_v4l2_cropTop_expl" : "Count of pixels on the top side that are removed from the picture.", "edt_conf_v4l2_cropTop_expl" : "Count of pixels on the top side that are removed from the picture.",
"edt_conf_v4l2_cropBottom_title" : "Crop bottom", "edt_conf_v4l2_cropBottom_title" : "Crop bottom",
"edt_conf_v4l2_cropBottom_expl" : "Count of pixels on the bottom side that are removed from the picture.", "edt_conf_v4l2_cropBottom_expl" : "Count of pixels on the bottom side that are removed from the picture.",
"edt_conf_v4l2_cecDetection_title" : "CEC detection",
"edt_conf_v4l2_cecDetection_expl" : "If enabled, usb capture will be temporarily disabled when CEC standby event received from HDMI bus.",
"edt_conf_v4l2_signalDetection_title" : "Signal detection", "edt_conf_v4l2_signalDetection_title" : "Signal detection",
"edt_conf_v4l2_signalDetection_expl" : "If enabled, usb capture will be temporarily disabled when no signal was found. This will happen when the picture fall below the threshold value for a period of 4 seconds.", "edt_conf_v4l2_signalDetection_expl" : "If enabled, usb capture will be temporarily disabled when no signal was found. This will happen when the picture fall below the threshold value for a period of 4 seconds.",
"edt_conf_v4l2_redSignalThreshold_title" : "Red signal threshold", "edt_conf_v4l2_redSignalThreshold_title" : "Red signal threshold",

View File

@ -465,7 +465,8 @@ async function requestLedDeviceProperties(type, params)
function requestLedDeviceIdentification(type, params) function requestLedDeviceIdentification(type, params)
{ {
sendToHyperion("leddevice", "identify", '"ledDeviceType": "'+type+'","params": '+JSON.stringify(params)+''); sendToHyperion("leddevice", "identify", '"ledDeviceType": "'+type+'","params": '+JSON.stringify(params)+'');
//let data = {ledDeviceType: type, params: params}; //let data = {ledDeviceType: type, params: params};
//sendToHyperion("leddevice", "identify", data ); //sendToHyperion("leddevice", "identify", data );
} }

View File

@ -5,7 +5,7 @@ CFG="${2:-Release}"
INST="$( [ "${3:-}" = "install" ] && echo true || echo false )" INST="$( [ "${3:-}" = "install" ] && echo true || echo false )"
sudo apt-get update sudo apt-get update
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev libturbojpeg0-dev python3-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libssl-dev libjpeg-dev libqt5sql5-sqlite zlib1g-dev || exit 1 sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev libturbojpeg0-dev python3-dev libcec-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libssl-dev libjpeg-dev libqt5sql5-sqlite zlib1g-dev || exit 1
if [ -e /dev/vc-cma -a -e /dev/vc-mem ] if [ -e /dev/vc-cma -a -e /dev/vc-mem ]
then then

View File

@ -1,31 +0,0 @@
#!/bin/sh
RPI_ROOTFS=/home/tvdzwan/hummingboard/rootfs
IMX6_ROOTFS=/home/tvdzwan/hummingboard/rootfs
outfile=hyperion.deps.openelec-imx6.tar.gz
tar --create --verbose --gzip --absolute-names --show-transformed-names --dereference \
--file "$outfile" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libaudio.so.2" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libffi.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libICE.so.6" \
"$IMX6_ROOTFS/lib/arm-linux-gnueabihf/libpcre.so.3" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libpng12.so.0" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libQtCore.so.4" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libQtGui.so.4" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libQtNetwork.so.4" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libSM.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libX11.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXau.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libxcb.so.1" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libxcb-util.so" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libxcb-randr.so" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXdmcp.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXext.so.6" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXrandr.so.2" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXrender.so.1" \
"$IMX6_ROOTFS/usr/lib/arm-linux-gnueabihf/libXt.so.6" \
"./openelec/hyperiond.sh" \
"./openelec/hyperion-v4l2.sh" \
"./openelec/hyperion-remote.sh"

View File

@ -14,7 +14,7 @@ if ! [ -d "$builddir" ]; then
echo "Could not find build director" echo "Could not find build director"
exit 1 exit 1
fi fi
outfile="$repodir/deploy/hyperion_$buildid.tar.gz" outfile="$repodir/deploy/hyperion_$buildid.tar.gz"
echo create $outfile echo create $outfile

View File

@ -24,7 +24,6 @@ macro(DeployUnix TARGET)
"libusb-1" "libusb-1"
"libutil" "libutil"
"libX11" "libX11"
"libz"
) )
if (APPLE) if (APPLE)

19
cmake/FindCEC.cmake Normal file
View File

@ -0,0 +1,19 @@
# - Try to find CEC
# Once done this will define
#
# CEC_FOUND - system has libcec
# CEC_INCLUDE_DIRS - the libcec include directory
# CEC_LIBRARIES - The libcec libraries
if(PKG_CONFIG_FOUND)
pkg_check_modules (CEC libcec>=3.0.0)
else()
find_path(CEC_INCLUDE_DIRS libcec/cec.h)
find_library(CEC_LIBRARIES cec)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CEC DEFAULT_MSG CEC_INCLUDE_DIRS CEC_LIBRARIES)
list(APPEND CEC_DEFINITIONS -DHAVE_LIBCEC=1)
mark_as_advanced(CEC_INCLUDE_DIRS CEC_LIBRARIES CEC_DEFINITIONS)

View File

@ -110,6 +110,7 @@
/// * cropTop : Cropping from the top [default=0] /// * cropTop : Cropping from the top [default=0]
/// * cropBottom : Cropping from the bottom [default=0] /// * cropBottom : Cropping from the bottom [default=0]
/// * signalDetection : enable/disable signal detection [default=true] /// * signalDetection : enable/disable signal detection [default=true]
/// * cecDetection : enable/disable cec detection [default=true]
/// * redSignalThreshold : Signal threshold for the red channel between 0 and 100 [default=5] /// * redSignalThreshold : Signal threshold for the red channel between 0 and 100 [default=5]
/// * greenSignalThreshold : Signal threshold for the green channel between 0 and 100 [default=5] /// * greenSignalThreshold : Signal threshold for the green channel between 0 and 100 [default=5]
/// * blueSignalThreshold : Signal threshold for the blue channel between 0 and 100 [default=5] /// * blueSignalThreshold : Signal threshold for the blue channel between 0 and 100 [default=5]
@ -133,6 +134,7 @@
"greenSignalThreshold" : 5, "greenSignalThreshold" : 5,
"blueSignalThreshold" : 5, "blueSignalThreshold" : 5,
"signalDetection" : false, "signalDetection" : false,
"cecDetection" : false,
"sDVOffsetMin" : 0.25, "sDVOffsetMin" : 0.25,
"sDHOffsetMin" : 0.25, "sDHOffsetMin" : 0.25,
"sDVOffsetMax" : 0.75, "sDVOffsetMax" : 0.75,

View File

@ -73,6 +73,7 @@
"greenSignalThreshold" : 5, "greenSignalThreshold" : 5,
"blueSignalThreshold" : 5, "blueSignalThreshold" : 5,
"signalDetection" : false, "signalDetection" : false,
"cecDetection" : false,
"sDVOffsetMin" : 0.25, "sDVOffsetMin" : 0.25,
"sDHOffsetMin" : 0.25, "sDHOffsetMin" : 0.25,
"sDVOffsetMax" : 0.75, "sDVOffsetMax" : 0.75,

View File

@ -406,4 +406,4 @@ private:
// current instance index // current instance index
quint8 _currInstanceIndex; quint8 _currInstanceIndex;
}; };

8
include/cec/CECEvent.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
enum class CECEvent
{
On,
Off
};

69
include/cec/CECHandler.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include <QObject>
#include <QVector>
#include <iostream>
#include <libcec/cec.h>
#include <cec/CECEvent.h>
using CECCallbacks = CEC::ICECCallbacks;
using CECAdapter = CEC::ICECAdapter;
using CECAdapterDescriptor = CEC::cec_adapter_descriptor;
using CECLogMessage = CEC::cec_log_message;
using CECKeyPress = CEC::cec_keypress;
using CECCommand = CEC::cec_command;
using CECLogicalAddress = CEC::cec_logical_address;
using CECLogicalAddresses = CEC::cec_logical_addresses;
using CECMenuState = CEC::cec_menu_state;
using CECPowerStatus = CEC::cec_power_status;
using CECVendorId = CEC::cec_vendor_id;
using CECParameter = CEC::libcec_parameter;
using CECConfig = CEC::libcec_configuration;
using CECAlert = CEC::libcec_alert;
class Logger;
class CECHandler : public QObject
{
Q_OBJECT
public:
CECHandler();
~CECHandler() override;
QString scan() const;
public slots:
bool start();
void stop();
signals:
void cecEvent(CECEvent event);
private:
/* CEC Callbacks */
static void onCecLogMessage (void * context, const CECLogMessage * message);
static void onCecKeyPress (void * context, const CECKeyPress * key);
static void onCecAlert (void * context, const CECAlert alert, const CECParameter data);
static void onCecConfigurationChanged (void * context, const CECConfig * configuration);
static void onCecCommandReceived (void * context, const CECCommand * command);
static void onCecSourceActivated (void * context, const CECLogicalAddress address, const uint8_t activated);
static int onCecMenuStateChanged (void * context, const CECMenuState state);
/* CEC Adapter helpers */
QVector<CECAdapterDescriptor> getAdapters() const;
bool openAdapter(const CECAdapterDescriptor & descriptor);
void printAdapter(const CECAdapterDescriptor & descriptor) const;
/* CEC Helpers */
CECCallbacks getCallbacks() const;
CECConfig getConfig() const;
CECAdapter * _cecAdapter {};
CECCallbacks _cecCallbacks {};
CECConfig _cecConfig {};
Logger * _logger {};
};

View File

@ -16,6 +16,7 @@
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
#include <grabber/VideoStandard.h> #include <grabber/VideoStandard.h>
#include <utils/Components.h> #include <utils/Components.h>
#include <cec/CECEvent.h>
// general JPEG decoder includes // general JPEG decoder includes
#ifdef HAVE_JPEG_DECODER #ifdef HAVE_JPEG_DECODER
@ -67,6 +68,7 @@ public:
} }
bool getSignalDetectionEnabled() { return _signalDetectionEnabled; } bool getSignalDetectionEnabled() { return _signalDetectionEnabled; }
bool getCecDetectionEnabled() { return _cecDetectionEnabled; }
int grabFrame(Image<ColorRgb> &); int grabFrame(Image<ColorRgb> &);
@ -98,6 +100,11 @@ public:
/// ///
void setSignalDetectionEnable(bool enable) override; void setSignalDetectionEnable(bool enable) override;
///
/// @brief overwrite Grabber.h implementation
///
void setCecDetectionEnable(bool enable) override;
/// ///
/// @brief overwrite Grabber.h implementation /// @brief overwrite Grabber.h implementation
/// ///
@ -149,6 +156,8 @@ public slots:
void stop(); void stop();
void handleCecEvent(CECEvent event);
signals: signals:
void newFrame(const Image<ColorRgb> & image); void newFrame(const Image<ColorRgb> & image);
void readError(const char* err); void readError(const char* err);
@ -257,6 +266,8 @@ private:
int _noSignalCounterThreshold; int _noSignalCounterThreshold;
ColorRgb _noSignalThresholdColor; ColorRgb _noSignalThresholdColor;
bool _signalDetectionEnabled; bool _signalDetectionEnabled;
bool _cecDetectionEnabled;
bool _cecStandbyActivated;
bool _noSignalDetected; bool _noSignalDetected;
int _noSignalCounter; int _noSignalCounter;
double _x_frac_min; double _x_frac_min;

View File

@ -19,6 +19,7 @@ public:
~V4L2Wrapper() override; ~V4L2Wrapper() override;
bool getSignalDetectionEnable(); bool getSignalDetectionEnable();
bool getCecDetectionEnable();
public slots: public slots:
bool start(); bool start();
@ -28,9 +29,9 @@ public slots:
void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom); void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
void setSignalDetectionEnable(bool enable); void setSignalDetectionEnable(bool enable);
void setCecDetectionEnable(bool enable);
void setDeviceVideoStandard(QString device, VideoStandard videoStandard); void setDeviceVideoStandard(QString device, VideoStandard videoStandard);
void handleCecEvent(CECEvent event);
signals:
private slots: private slots:
void newFrame(const Image<ColorRgb> & image); void newFrame(const Image<ColorRgb> & image);

View File

@ -80,6 +80,11 @@ public:
/// ///
virtual void setSignalDetectionEnable(bool enable) {} virtual void setSignalDetectionEnable(bool enable) {}
///
/// @brief Apply CecDetectionEnable (used from v4l)
///
virtual void setCecDetectionEnable(bool enable) {}
/// ///
/// @brief Apply device and videoStanded (used from v4l) /// @brief Apply device and videoStanded (used from v4l)
/// ///

View File

@ -550,6 +550,5 @@ private:
/// Boblight instance /// Boblight instance
BoblightServer* _boblightServer; BoblightServer* _boblightServer;
/// mutex
QMutex _changes; QMutex _changes;
}; };

View File

@ -20,6 +20,10 @@ add_subdirectory(db)
add_subdirectory(api) add_subdirectory(api)
add_subdirectory(python) add_subdirectory(python)
if(ENABLE_CEC)
add_subdirectory(cec)
endif()
if(ENABLE_AVAHI) if(ENABLE_AVAHI)
add_subdirectory(bonjour) add_subdirectory(bonjour)
endif() endif()

View File

@ -22,7 +22,7 @@
"params": { "params": {
"type" : "object", "type" : "object",
"required" : false "required" : false
} }
}, },
"additionalProperties": false "additionalProperties": false
} }

View File

@ -1409,7 +1409,6 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString &
*/ { */ {
if (subc == "discover") if (subc == "discover")
{ {
QJsonObject config; QJsonObject config;
config.insert("type", devType); config.insert("type", devType);

339
libsrc/cec/CECHandler.cpp Normal file
View File

@ -0,0 +1,339 @@
#include <cec/CECHandler.h>
#include <utils/Logger.h>
#include <algorithm>
#include <libcec/cecloader.h>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
/* Enable to turn on detailed CEC logs */
// #define VERBOSE_CEC
CECHandler::CECHandler()
{
qRegisterMetaType<CECEvent>("CECEvent");
_logger = Logger::getInstance("CEC");
_cecCallbacks = getCallbacks();
_cecConfig = getConfig();
_cecConfig.callbacks = &_cecCallbacks;
_cecConfig.callbackParam = this;
}
CECHandler::~CECHandler()
{
stop();
}
bool CECHandler::start()
{
if (_cecAdapter)
return true;
Info(_logger, "Starting CEC handler");
_cecAdapter = LibCecInitialise(&_cecConfig);
if(!_cecAdapter)
{
Error(_logger, "Failed loading libcec.so");
return false;
}
auto adapters = getAdapters();
if (adapters.isEmpty())
{
Error(_logger, "Failed to find CEC adapter");
UnloadLibCec(_cecAdapter);
_cecAdapter = nullptr;
return false;
}
Info(_logger, "Auto detecting CEC adapter");
bool opened = false;
for (const auto & adapter : adapters)
{
printAdapter(adapter);
if (!opened && openAdapter(adapter))
{
Info(_logger, "CEC Handler initialized with adapter : %s", adapter.strComName);
opened = true;
}
}
if (!opened)
{
UnloadLibCec(_cecAdapter);
_cecAdapter = nullptr;
}
return opened;
}
void CECHandler::stop()
{
if (_cecAdapter)
{
Info(_logger, "Stopping CEC handler");
_cecAdapter->Close();
UnloadLibCec(_cecAdapter);
_cecAdapter = nullptr;
}
}
CECConfig CECHandler::getConfig() const
{
CECConfig configuration;
const std::string name("HyperionCEC");
name.copy(configuration.strDeviceName, std::min(name.size(), sizeof(configuration.strDeviceName)));
configuration.deviceTypes.Add(CEC::CEC_DEVICE_TYPE_RECORDING_DEVICE);
configuration.clientVersion = CEC::LIBCEC_VERSION_CURRENT;
return configuration;
}
CECCallbacks CECHandler::getCallbacks() const
{
CECCallbacks callbacks;
callbacks.sourceActivated = onCecSourceActivated;
callbacks.commandReceived = onCecCommandReceived;
callbacks.alert = onCecAlert;
callbacks.logMessage = onCecLogMessage;
callbacks.keyPress = onCecKeyPress;
callbacks.configurationChanged = onCecConfigurationChanged;
callbacks.menuStateChanged = onCecMenuStateChanged;
return callbacks;
}
QVector<CECAdapterDescriptor> CECHandler::getAdapters() const
{
if (!_cecAdapter)
return {};
QVector<CECAdapterDescriptor> descriptors(16);
int8_t size = _cecAdapter->DetectAdapters(descriptors.data(), descriptors.size(), nullptr, true /*quickscan*/);
descriptors.resize(size);
return descriptors;
}
bool CECHandler::openAdapter(const CECAdapterDescriptor & descriptor)
{
if (!_cecAdapter)
return false;
if(!_cecAdapter->Open(descriptor.strComName))
{
Error(_logger, QString("Failed to open the CEC adaper on port %1")
.arg(descriptor.strComName)
.toLocal8Bit());
return false;
}
return true;
}
void CECHandler::printAdapter(const CECAdapterDescriptor & descriptor) const
{
Info(_logger, QString("CEC Adapter:").toLocal8Bit());
Info(_logger, QString("\tName : %1").arg(descriptor.strComName).toLocal8Bit());
Info(_logger, QString("\tPath : %1").arg(descriptor.strComPath).toLocal8Bit());
}
QString CECHandler::scan() const
{
if (!_cecAdapter)
return {};
Info(_logger, "Starting CEC scan");
QJsonArray devices;
CECLogicalAddresses addresses = _cecAdapter->GetActiveDevices();
for (int address = CEC::CECDEVICE_TV; address <= CEC::CECDEVICE_BROADCAST; ++address)
{
if (addresses[address])
{
CECLogicalAddress logicalAddress = (CECLogicalAddress)address;
QJsonObject device;
CECVendorId vendor = (CECVendorId)_cecAdapter->GetDeviceVendorId(logicalAddress);
CECPowerStatus power = _cecAdapter->GetDevicePowerStatus(logicalAddress);
device["name" ] = _cecAdapter->GetDeviceOSDName(logicalAddress).c_str();
device["vendor" ] = _cecAdapter->ToString(vendor);
device["address" ] = _cecAdapter->ToString(logicalAddress);
device["power" ] = _cecAdapter->ToString(power);
devices << device;
Info(_logger, QString("\tCECDevice: %1 / %2 / %3 / %4")
.arg(device["name"].toString())
.arg(device["vendor"].toString())
.arg(device["address"].toString())
.arg(device["power"].toString())
.toLocal8Bit());
}
}
return QJsonDocument(devices).toJson(QJsonDocument::Compact);
}
void CECHandler::onCecLogMessage(void * context, const CECLogMessage * message)
{
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
switch (message->level)
{
case CEC::CEC_LOG_ERROR:
Error(handler->_logger, QString("%1")
.arg(message->message)
.toLocal8Bit());
break;
case CEC::CEC_LOG_WARNING:
Warning(handler->_logger, QString("%1")
.arg(message->message)
.toLocal8Bit());
break;
case CEC::CEC_LOG_TRAFFIC:
case CEC::CEC_LOG_NOTICE:
Info(handler->_logger, QString("%1")
.arg(message->message)
.toLocal8Bit());
break;
case CEC::CEC_LOG_DEBUG:
Debug(handler->_logger, QString("%1")
.arg(message->message)
.toLocal8Bit());
break;
default:
break;
}
#endif
}
void CECHandler::onCecKeyPress(void * context, const CECKeyPress * key)
{
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
CECAdapter * adapter = handler->_cecAdapter;
Debug(handler->_logger, QString("CECHandler::onCecKeyPress: %1")
.arg(adapter->ToString(key->keycode))
.toLocal8Bit());
#endif
}
void CECHandler::onCecAlert(void * context, const CECAlert alert, const CECParameter data)
{
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
Error(handler->_logger, QString("CECHandler::onCecAlert: %1")
.arg(alert)
.toLocal8Bit());
#endif
}
void CECHandler::onCecConfigurationChanged(void * context, const CECConfig * configuration)
{
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
Debug(handler->_logger, QString("CECHandler::onCecConfigurationChanged: %1")
.arg(configuration->strDeviceName)
.toLocal8Bit());
#endif
}
int CECHandler::onCecMenuStateChanged(void * context, const CECMenuState state)
{
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return 0;
CECAdapter * adapter = handler->_cecAdapter;
Debug(handler->_logger, QString("CECHandler::onCecMenuStateChanged: %1")
.arg(adapter->ToString(state))
.toLocal8Bit());
#endif
return 0;
}
void CECHandler::onCecCommandReceived(void * context, const CECCommand * command)
{
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
CECAdapter * adapter = handler->_cecAdapter;
#ifdef VERBOSE_CEC
Debug(handler->_logger, QString("CECHandler::onCecCommandReceived: %1 (%2 > %3)")
.arg(adapter->ToString(command->opcode))
.arg(adapter->ToString(command->initiator))
.arg(adapter->ToString(command->destination))
.toLocal8Bit());
#endif
/* We do NOT check sender */
// if (address == CEC::CECDEVICE_TV)
{
if (command->opcode == CEC::CEC_OPCODE_SET_STREAM_PATH)
{
Info(handler->_logger, QString("CEC source activated: %1")
.arg(adapter->ToString(command->initiator))
.toLocal8Bit());
emit handler->cecEvent(CECEvent::On);
}
if (command->opcode == CEC::CEC_OPCODE_STANDBY)
{
Info(handler->_logger, QString("CEC source deactivated: %1")
.arg(adapter->ToString(command->initiator))
.toLocal8Bit());
emit handler->cecEvent(CECEvent::Off);
}
}
}
void CECHandler::onCecSourceActivated(void * context, const CECLogicalAddress address, const uint8_t activated)
{
/* We use CECHandler::onCecCommandReceived for
* source activated/deactivated notifications. */
#ifdef VERBOSE_CEC
CECHandler * handler = qobject_cast<CECHandler*>(static_cast<QObject*>(context));
if (!handler)
return;
CECAdapter * adapter = handler->_cecAdapter;
Debug(handler->_logger, QString("CEC source %1 : %2")
.arg(activated ? "activated" : "deactivated")
.arg(adapter->ToString(address))
.toLocal8Bit());
#endif
}

17
libsrc/cec/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
# Define the current source locations
find_package(CEC REQUIRED)
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/cec)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/cec)
FILE (GLOB CEC_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp")
add_library(cechandler ${CEC_SOURCES})
include_directories(${CEC_INCLUDE_DIRS})
target_link_libraries(cechandler
dl
${CEC_LIBRARIES}
Qt5::Core
)

View File

@ -14,5 +14,5 @@ target_link_libraries(v4l2-grabber
if(TURBOJPEG_FOUND) if(TURBOJPEG_FOUND)
target_link_libraries(v4l2-grabber ${TurboJPEG_LIBRARY}) target_link_libraries(v4l2-grabber ${TurboJPEG_LIBRARY})
elseif (JPEG_FOUND) elseif (JPEG_FOUND)
target_link_libraries(v4l2-grabber ${JPEG_LIBRARY}) target_link_libraries(v4l2-grabber ${JPEG_LIBRARY})
endif(TURBOJPEG_FOUND) endif(TURBOJPEG_FOUND)

View File

@ -52,6 +52,8 @@ V4L2Grabber::V4L2Grabber(const QString & device
, _noSignalCounterThreshold(40) , _noSignalCounterThreshold(40)
, _noSignalThresholdColor(ColorRgb{0,0,0}) , _noSignalThresholdColor(ColorRgb{0,0,0})
, _signalDetectionEnabled(true) , _signalDetectionEnabled(true)
, _cecDetectionEnabled(true)
, _cecStandbyActivated(false)
, _noSignalDetected(false) , _noSignalDetected(false)
, _noSignalCounter(0) , _noSignalCounter(0)
, _x_frac_min(0.25) , _x_frac_min(0.25)
@ -1031,6 +1033,9 @@ bool V4L2Grabber::process_image(const void *p, int size)
void V4L2Grabber::process_image(const uint8_t * data, int size) void V4L2Grabber::process_image(const uint8_t * data, int size)
{ {
if (_cecDetectionEnabled && _cecStandbyActivated)
return;
Image<ColorRgb> image(_width, _height); Image<ColorRgb> image(_width, _height);
/* ---------------------------------------------------------- /* ----------------------------------------------------------
@ -1291,6 +1296,15 @@ void V4L2Grabber::setSignalDetectionEnable(bool enable)
} }
} }
void V4L2Grabber::setCecDetectionEnable(bool enable)
{
if (_cecDetectionEnabled != enable)
{
_cecDetectionEnabled = enable;
Info(_log, QString("CEC detection is now %1").arg(enable ? "enabled" : "disabled").toLocal8Bit());
}
}
void V4L2Grabber::setPixelDecimation(int pixelDecimation) void V4L2Grabber::setPixelDecimation(int pixelDecimation)
{ {
if (_pixelDecimation != pixelDecimation) if (_pixelDecimation != pixelDecimation)
@ -1383,3 +1397,19 @@ QStringList V4L2Grabber::getFramerates(QString devicePath)
{ {
return _deviceProperties.value(devicePath).framerates; return _deviceProperties.value(devicePath).framerates;
} }
void V4L2Grabber::handleCecEvent(CECEvent event)
{
switch (event)
{
case CECEvent::On :
Debug(_log,"CEC on event received");
_cecStandbyActivated = false;
return;
case CECEvent::Off :
Debug(_log,"CEC off event received");
_cecStandbyActivated = true;
return;
default: break;
}
}

View File

@ -90,7 +90,22 @@ bool V4L2Wrapper::getSignalDetectionEnable()
return _grabber.getSignalDetectionEnabled(); return _grabber.getSignalDetectionEnabled();
} }
void V4L2Wrapper::setCecDetectionEnable(bool enable)
{
_grabber.setCecDetectionEnable(enable);
}
bool V4L2Wrapper::getCecDetectionEnable()
{
return _grabber.getCecDetectionEnabled();
}
void V4L2Wrapper::setDeviceVideoStandard(QString device, VideoStandard videoStandard) void V4L2Wrapper::setDeviceVideoStandard(QString device, VideoStandard videoStandard)
{ {
_grabber.setDeviceVideoStandard(device, videoStandard); _grabber.setDeviceVideoStandard(device, videoStandard);
} }
void V4L2Wrapper::handleCecEvent(CECEvent event)
{
_grabber.handleCecEvent(event);
}

View File

@ -172,6 +172,9 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
// device framerate // device framerate
_ggrabber->setFramerate(obj["fps"].toInt(15)); _ggrabber->setFramerate(obj["fps"].toInt(15));
// CEC Standby
_ggrabber->setCecDetectionEnable(obj["cecDetection"].toBool(true));
_ggrabber->setSignalDetectionEnable(obj["signalDetection"].toBool(true)); _ggrabber->setSignalDetectionEnable(obj["signalDetection"].toBool(true));
_ggrabber->setSignalDetectionOffset( _ggrabber->setSignalDetectionOffset(
obj["sDHOffsetMin"].toDouble(0.25), obj["sDHOffsetMin"].toDouble(0.25),

View File

@ -1,4 +1,3 @@

// STL includes // STL includes
#include <exception> #include <exception>
#include <sstream> #include <sstream>

View File

@ -131,13 +131,21 @@
"required" : true, "required" : true,
"propertyOrder" : 15 "propertyOrder" : 15
}, },
"cecDetection" :
{
"type" : "boolean",
"title" : "edt_conf_v4l2_cecDetection_title",
"default" : false,
"required" : true,
"propertyOrder" : 16
},
"signalDetection" : "signalDetection" :
{ {
"type" : "boolean", "type" : "boolean",
"title" : "edt_conf_v4l2_signalDetection_title", "title" : "edt_conf_v4l2_signalDetection_title",
"default" : false, "default" : false,
"required" : true, "required" : true,
"propertyOrder" : 16 "propertyOrder" : 17
}, },
"redSignalThreshold" : "redSignalThreshold" :
{ {
@ -153,7 +161,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 17 "propertyOrder" : 18
}, },
"greenSignalThreshold" : "greenSignalThreshold" :
{ {
@ -169,7 +177,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 18 "propertyOrder" : 19
}, },
"blueSignalThreshold" : "blueSignalThreshold" :
{ {
@ -185,7 +193,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 19 "propertyOrder" : 20
}, },
"sDVOffsetMin" : "sDVOffsetMin" :
{ {
@ -201,7 +209,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 20 "propertyOrder" : 21
}, },
"sDVOffsetMax" : "sDVOffsetMax" :
{ {
@ -217,7 +225,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 21 "propertyOrder" : 22
}, },
"sDHOffsetMin" : "sDHOffsetMin" :
{ {
@ -233,7 +241,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 22 "propertyOrder" : 23
}, },
"sDHOffsetMax" : "sDHOffsetMax" :
{ {
@ -249,7 +257,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 23 "propertyOrder" : 24
} }
}, },
"additionalProperties" : true "additionalProperties" : true

View File

@ -90,7 +90,10 @@ void print_trace()
Logger* log = Logger::getInstance("CORE"); Logger* log = Logger::getInstance("CORE");
char ** symbols = backtrace_symbols(addresses, size); char ** symbols = backtrace_symbols(addresses, size);
for (int i = 0; i < size; ++i)
/* Skip first 2 frames as they are signal
* handler and print_trace functions. */
for (int i = 2; i < size; ++i)
{ {
std::string line = "\t" + decipher_trace(symbols[i]); std::string line = "\t" + decipher_trace(symbols[i]);
Error(log, line.c_str()); Error(log, line.c_str());

View File

@ -19,18 +19,18 @@ add_executable(hyperiond
) )
target_link_libraries(hyperiond target_link_libraries(hyperiond
commandline commandline
hyperion hyperion
effectengine effectengine
jsonserver jsonserver
flatbufserver flatbufserver
protoserver protoserver
webserver webserver
ssdp ssdp
database database
python python
resources resources
Qt5::Widgets Qt5::Widgets
) )
if (NOT CMAKE_VERSION VERSION_LESS "3.12") if (NOT CMAKE_VERSION VERSION_LESS "3.12")
@ -88,6 +88,10 @@ if (ENABLE_QT)
target_link_libraries(hyperiond qt-grabber) target_link_libraries(hyperiond qt-grabber)
endif () endif ()
if (ENABLE_CEC)
target_link_libraries(hyperiond cechandler)
endif ()
if(NOT WIN32) if(NOT WIN32)
install ( TARGETS hyperiond DESTINATION "share/hyperion/bin" COMPONENT "Hyperion" ) install ( TARGETS hyperiond DESTINATION "share/hyperion/bin" COMPONENT "Hyperion" )
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT "Hyperion" ) install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT "Hyperion" )

View File

@ -54,6 +54,10 @@
// EffectFileHandler // EffectFileHandler
#include <effectengine/EffectFileHandler.h> #include <effectengine/EffectFileHandler.h>
#ifdef ENABLE_CEC
#include <cec/CECHandler.h>
#endif
HyperionDaemon *HyperionDaemon::daemon = nullptr; HyperionDaemon *HyperionDaemon::daemon = nullptr;
HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bool &logLvlOverwrite) HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bool &logLvlOverwrite)
@ -76,6 +80,7 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bo
, _osxGrabber(nullptr) , _osxGrabber(nullptr)
, _qtGrabber(nullptr) , _qtGrabber(nullptr)
, _ssdp(nullptr) , _ssdp(nullptr)
, _cecHandler(nullptr)
, _currVideoMode(VideoMode::VIDEO_2D) , _currVideoMode(VideoMode::VIDEO_2D)
{ {
HyperionDaemon::daemon = this; HyperionDaemon::daemon = this;
@ -95,6 +100,8 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bo
if (!logLvlOverwrite) if (!logLvlOverwrite)
handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER)); handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER));
createCecHandler();
// init EffectFileHandler // init EffectFileHandler
EffectFileHandler *efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this); EffectFileHandler *efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this);
connect(this, &HyperionDaemon::settingsChanged, efh, &EffectFileHandler::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, efh, &EffectFileHandler::handleSettingsUpdate);
@ -194,12 +201,17 @@ void HyperionDaemon::freeObjects()
delete _sslWebserver->thread(); delete _sslWebserver->thread();
delete _sslWebserver; delete _sslWebserver;
#ifdef ENABLE_CEC
_cecHandler->thread()->quit();
_cecHandler->thread()->wait(1000);
delete _cecHandler->thread();
delete _cecHandler;
#endif
// stop Hyperions (non blocking) // stop Hyperions (non blocking)
_instanceManager->stopAll(); _instanceManager->stopAll();
#ifdef ENABLE_AVAHI
delete _bonjourBrowserWrapper; delete _bonjourBrowserWrapper;
#endif
delete _amlGrabber; delete _amlGrabber;
delete _dispmanx; delete _dispmanx;
delete _fbGrabber; delete _fbGrabber;
@ -208,9 +220,8 @@ void HyperionDaemon::freeObjects()
delete _v4l2Grabber; delete _v4l2Grabber;
_v4l2Grabber = nullptr; _v4l2Grabber = nullptr;
#ifdef ENABLE_AVAHI _cecHandler = nullptr;
_bonjourBrowserWrapper = nullptr; _bonjourBrowserWrapper = nullptr;
#endif
_amlGrabber = nullptr; _amlGrabber = nullptr;
_dispmanx = nullptr; _dispmanx = nullptr;
_fbGrabber = nullptr; _fbGrabber = nullptr;
@ -463,13 +474,23 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type &settingsType, co
} }
else if (settingsType == settings::V4L2) else if (settingsType == settings::V4L2)
{ {
const QJsonObject &grabberConfig = config.object();
#ifdef ENABLE_CEC
QString operation;
if (_cecHandler && grabberConfig["cecDetection"].toBool(false))
{
QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
}
else
{
QMetaObject::invokeMethod(_cecHandler, "stop", Qt::QueuedConnection);
}
#endif
#ifdef ENABLE_V4L2
if (_v4l2Grabber != nullptr) if (_v4l2Grabber != nullptr)
return; return;
const QJsonObject &grabberConfig = config.object(); #ifdef ENABLE_V4L2
_v4l2Grabber = new V4L2Wrapper( _v4l2Grabber = new V4L2Wrapper(
grabberConfig["device"].toString("auto"), grabberConfig["device"].toString("auto"),
grabberConfig["width"].toInt(0), grabberConfig["width"].toInt(0),
@ -489,6 +510,8 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type &settingsType, co
grabberConfig["cropRight"].toInt(0), grabberConfig["cropRight"].toInt(0),
grabberConfig["cropTop"].toInt(0), grabberConfig["cropTop"].toInt(0),
grabberConfig["cropBottom"].toInt(0)); grabberConfig["cropBottom"].toInt(0));
_v4l2Grabber->setCecDetectionEnable(grabberConfig["cecDetection"].toBool(true));
_v4l2Grabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true)); _v4l2Grabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true));
_v4l2Grabber->setSignalDetectionOffset( _v4l2Grabber->setSignalDetectionOffset(
grabberConfig["sDHOffsetMin"].toDouble(0.25), grabberConfig["sDHOffsetMin"].toDouble(0.25),
@ -497,9 +520,9 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type &settingsType, co
grabberConfig["sDVOffsetMax"].toDouble(0.75)); grabberConfig["sDVOffsetMax"].toDouble(0.75));
Debug(_log, "V4L2 grabber created"); Debug(_log, "V4L2 grabber created");
// connect to HyperionDaemon signal // connect to HyperionDaemon signal
connect(this, &HyperionDaemon::videoMode, _v4l2Grabber, &V4L2Wrapper::setVideoMode); connect(this, &HyperionDaemon::videoMode, _v4l2Grabber, &V4L2Wrapper::setVideoMode);
connect(this, &HyperionDaemon::settingsChanged, _v4l2Grabber, &V4L2Wrapper::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _v4l2Grabber, &V4L2Wrapper::handleSettingsUpdate);
#else #else
Error(_log, "The v4l2 grabber can not be instantiated, because it has been left out from the build"); Error(_log, "The v4l2 grabber can not be instantiated, because it has been left out from the build");
#endif #endif
@ -611,3 +634,24 @@ void HyperionDaemon::createGrabberOsx(const QJsonObject &grabberConfig)
Error(_log, "The osx grabber can not be instantiated, because it has been left out from the build"); Error(_log, "The osx grabber can not be instantiated, because it has been left out from the build");
#endif #endif
} }
void HyperionDaemon::createCecHandler()
{
#ifdef ENABLE_CEC
_cecHandler = new CECHandler;
QThread * thread = new QThread(this);
thread->setObjectName("CECThread");
_cecHandler->moveToThread(thread);
thread->start();
connect(_cecHandler, &CECHandler::cecEvent, [&] (CECEvent event) {
if (_v4l2Grabber)
_v4l2Grabber->handleCecEvent(event);
});
Info(_log, "CEC handler created");
#else
Error(_log, "The CEC handler can not be instantiated, because it has been left out from the build");
#endif
}

View File

@ -65,6 +65,7 @@ class FlatBufferServer;
class ProtoServer; class ProtoServer;
class AuthManager; class AuthManager;
class NetOrigin; class NetOrigin;
class CECHandler;
class HyperionDaemon : public QObject class HyperionDaemon : public QObject
{ {
@ -144,6 +145,7 @@ private:
void createGrabberOsx(const QJsonObject & grabberConfig); void createGrabberOsx(const QJsonObject & grabberConfig);
void createGrabberX11(const QJsonObject & grabberConfig); void createGrabberX11(const QJsonObject & grabberConfig);
void createGrabberQt(const QJsonObject & grabberConfig); void createGrabberQt(const QJsonObject & grabberConfig);
void createCecHandler();
Logger* _log; Logger* _log;
HyperionIManager* _instanceManager; HyperionIManager* _instanceManager;
@ -162,6 +164,7 @@ private:
OsxWrapper* _osxGrabber; OsxWrapper* _osxGrabber;
QtWrapper* _qtGrabber; QtWrapper* _qtGrabber;
SSDPHandler* _ssdp; SSDPHandler* _ssdp;
CECHandler* _cecHandler;
FlatBufferServer* _flatBufferServer; FlatBufferServer* _flatBufferServer;
ProtoServer* _protoServer; ProtoServer* _protoServer;