even more changes

Signed-off-by: Paulchen-Panther <Paulchen--Panter@gmx.net>
This commit is contained in:
Paulchen-Panther 2018-12-28 18:12:45 +01:00
parent 3700566d10
commit 2a77f6f012
No known key found for this signature in database
GPG Key ID: D45BA68A28471D4A
99 changed files with 2610 additions and 673 deletions

View File

@ -23,6 +23,7 @@ SET ( DEFAULT_X11 OFF )
SET ( DEFAULT_WS281XPWM OFF ) SET ( DEFAULT_WS281XPWM OFF )
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON ) SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF ) SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS OFF )
SET ( DEFAULT_TESTS OFF ) SET ( DEFAULT_TESTS OFF )
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" ) IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
@ -163,6 +164,9 @@ message(STATUS "ENABLE_PROFILER = ${ENABLE_PROFILER}")
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto ) SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto ) SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( FLATBUFFERS_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/flatbuf )
SET ( FLATBUFFERS_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/flatbuf )
# check all json files # check all json files
FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json ) FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json )
SET( JSON_FILES SET( JSON_FILES
@ -246,7 +250,7 @@ if (UNIX AND NOT APPLE)
endif () endif ()
# add QT5 dependency # add QT5 dependency
SET(QT_MIN_VERSION "5.2.0") SET(QT_MIN_VERSION "5.5.0")
find_package(Qt5 COMPONENTS Core Gui Network SerialPort REQUIRED) find_package(Qt5 COMPONENTS Core Gui Network SerialPort REQUIRED)
message( STATUS "Found Qt Version: ${Qt5Core_VERSION}" ) message( STATUS "Found Qt Version: ${Qt5Core_VERSION}" )
IF ( "${Qt5Core_VERSION}" VERSION_LESS "${QT_MIN_VERSION}" ) IF ( "${Qt5Core_VERSION}" VERSION_LESS "${QT_MIN_VERSION}" )

View File

@ -6,24 +6,13 @@
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 libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev
``` ```
### Ubuntu 14.04 specific
You need a newer version of cmake (minimum 3.0.0). Install it from the ppa or website
```
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:george-edison55/cmake-3.x
sudo apt-get update && sudo apt-get upgrade
```
**on RPI you need the videocore IV headers** **on RPI you need the videocore IV headers**
``` ```
sudo apt-get install libraspberrypi-dev sudo apt-get install libraspberrypi-dev
``` ```
**OSMC**
libraspberrypi-dev is not available, use this instead
```
sudo apt-get install rbp-userland-dev-osmc
```
**ATTENTION Win10LinuxSubsystem** we do not (/we can't) support using hyperion in linux subsystem of MS Windows 10, albeit some users tested it with success. Keep in mind to disable **ATTENTION Win10LinuxSubsystem** we do not (/we can't) support using hyperion in linux subsystem of MS Windows 10, albeit some users tested it with success. Keep in mind to disable
all linux specific led and grabber hardware via cmake. Because we use QT as framework in hyperion, serialport leds and network driven devices could work. all linux specific led and grabber hardware via cmake. Because we use QT as framework in hyperion, serialport leds and network driven devices could work.
@ -71,7 +60,7 @@ sudo make install/strip
sudo make uninstall sudo make uninstall
# ... or run it from compile directory # ... or run it from compile directory
bin/hyperiond bin/hyperiond
# webui is located on localhost:8090 # webui is located on localhost:8099
``` ```

View File

@ -32,7 +32,7 @@ If you need further support please open a topic at the our new forum!
[Hyperion webpage/forum](https://www.hyperion-project.org). [Hyperion webpage/forum](https://www.hyperion-project.org).
## Requirements ## Requirements
* Debian 8, Ubuntu 14.04 or higher. Windows is not supported currently. * Debian 9, Ubuntu 16.04 or higher. Windows is not supported currently.
## Building ## Building
See [Compilehowto](CompileHowto.md) and [CrossCompileHowto](CrossCompileHowto.txt). See [Compilehowto](CompileHowto.md) and [CrossCompileHowto](CrossCompileHowto.txt).

View File

@ -27,6 +27,7 @@
"general_col_green" : "grün", "general_col_green" : "grün",
"general_col_blue" : "blau", "general_col_blue" : "blau",
"general_button_savesettings" : "Einstellungen speichern", "general_button_savesettings" : "Einstellungen speichern",
"general_btn_yes" : "Ja",
"general_btn_ok" : "OK", "general_btn_ok" : "OK",
"general_btn_cancel" : "Abbrechen", "general_btn_cancel" : "Abbrechen",
"general_btn_continue" : "Fortfahren", "general_btn_continue" : "Fortfahren",
@ -346,7 +347,7 @@
"edt_dev_enum_sub_min_warm_adjust" : "Minimale Anpassung: warm", "edt_dev_enum_sub_min_warm_adjust" : "Minimale Anpassung: warm",
"edt_dev_enum_white_off" : "Weiß ist aus", "edt_dev_enum_white_off" : "Weiß ist aus",
"edt_dev_general_heading_title" : "Allgemeine Einstellungen", "edt_dev_general_heading_title" : "Allgemeine Einstellungen",
"edt_dev_general_ledCount_title" : "Anzahl Hardware LEDs", "edt_dev_general_hardwareLedCount_title" : "Anzahl Hardware LEDs",
"edt_dev_general_colorOrder_title" : "RGB Byte Reihenfolge", "edt_dev_general_colorOrder_title" : "RGB Byte Reihenfolge",
"edt_dev_general_rewriteTime_title" : "Aktualisierungszeit", "edt_dev_general_rewriteTime_title" : "Aktualisierungszeit",
"edt_dev_spec_header_title" : "Spezifische Einstellungen", "edt_dev_spec_header_title" : "Spezifische Einstellungen",
@ -482,13 +483,11 @@
"edt_conf_smooth_continuousOutput_expl" : "Aktualisiere die LEDs, auch wenn das Bild sich nicht geändert hat.", "edt_conf_smooth_continuousOutput_expl" : "Aktualisiere die LEDs, auch wenn das Bild sich nicht geändert hat.",
"edt_conf_v4l2_heading_title" : "USB Aufnahme", "edt_conf_v4l2_heading_title" : "USB Aufnahme",
"edt_conf_v4l2_device_title" : "Gerät", "edt_conf_v4l2_device_title" : "Gerät",
"edt_conf_v4l2_device_expl" : "Der Pfad zum USB Aufnahmegerät.", "edt_conf_v4l2_device_expl" : "Der Pfad zum USB (v4l) Aufnahmegerät. Wähle 'auto' für automatische Erkennung. Beispiel: '/dev/video0'",
"edt_conf_v4l2_input_title" : "Eingang",
"edt_conf_v4l2_input_expl" : "Der Eingang des Pfades.",
"edt_conf_v4l2_standard_title" : "Videoformat", "edt_conf_v4l2_standard_title" : "Videoformat",
"edt_conf_v4l2_standard_expl" : "Wähle das passende Videoformat deiner Region.", "edt_conf_v4l2_standard_expl" : "Wähle das passende Videoformat deiner Region. Auf 'Auto' wird der gewählte Modus vom v4l interface beibehalten.",
"edt_conf_v4l2_sizeDecimation_title" : "Bildverkleinerung Faktor", "edt_conf_v4l2_sizeDecimation_title" : "Bildverkleinerung Faktor",
"edt_conf_v4l2_sizeDecimation_expl" : "Der Faktor der Bildverkleinerung ausgehend der von der ursprünglichen Größe, 1 bedeutet keine Änderung (originales Bild).", "edt_conf_v4l2_sizeDecimation_expl" : "Der Faktor der Bildverkleinerung ausgehend von der ursprünglichen Größe, 1 bedeutet keine Änderung (originales Bild).",
"edt_conf_v4l2_cropLeft_title" : "Entferne links", "edt_conf_v4l2_cropLeft_title" : "Entferne links",
"edt_conf_v4l2_cropLeft_expl" : "Anzahl der Pixel auf der linken Seite die vom Bild entfernt werden.", "edt_conf_v4l2_cropLeft_expl" : "Anzahl der Pixel auf der linken Seite die vom Bild entfernt werden.",
"edt_conf_v4l2_cropRight_title" : "Entferne rechts", "edt_conf_v4l2_cropRight_title" : "Entferne rechts",
@ -498,7 +497,7 @@
"edt_conf_v4l2_cropBottom_title" : "Entferne unten", "edt_conf_v4l2_cropBottom_title" : "Entferne unten",
"edt_conf_v4l2_cropBottom_expl" : "Anzahl der Pixel auf der unteren Seite die vom Bild entfernt werden.", "edt_conf_v4l2_cropBottom_expl" : "Anzahl der Pixel auf der unteren Seite die vom Bild entfernt werden.",
"edt_conf_v4l2_signalDetection_title" : "Signal Erkennung", "edt_conf_v4l2_signalDetection_title" : "Signal Erkennung",
"edt_conf_v4l2_signalDetection_expl" : "Wenn aktiviert, wird die USB Aufnahme temporär bei \"kein Signal\" abgeschalten.", "edt_conf_v4l2_signalDetection_expl" : "Wenn aktiviert, wird die USB Aufnahme temporär bei \"kein Signal\" abgeschalten. Das Bild muss dazu 4 Sekunden lang unter die Schwellwerte fallen.",
"edt_conf_v4l2_redSignalThreshold_title" : "Rote Signalschwelle", "edt_conf_v4l2_redSignalThreshold_title" : "Rote Signalschwelle",
"edt_conf_v4l2_redSignalThreshold_expl" : "Je höher die rote Schwelle je eher wird abgeschalten bei entsprechendem rot-Anteil.", "edt_conf_v4l2_redSignalThreshold_expl" : "Je höher die rote Schwelle je eher wird abgeschalten bei entsprechendem rot-Anteil.",
"edt_conf_v4l2_greenSignalThreshold_title" : "Grüne Signalschwelle", "edt_conf_v4l2_greenSignalThreshold_title" : "Grüne Signalschwelle",
@ -513,6 +512,11 @@
"edt_conf_v4l2_sDVOffsetMax_expl" : "Signal Erkennungs-Bereich vertikal maximum (0.0-1.0)", "edt_conf_v4l2_sDVOffsetMax_expl" : "Signal Erkennungs-Bereich vertikal maximum (0.0-1.0)",
"edt_conf_v4l2_sDHOffsetMax_title" : "Signal Erkennung HMax", "edt_conf_v4l2_sDHOffsetMax_title" : "Signal Erkennung HMax",
"edt_conf_v4l2_sDHOffsetMax_expl" : "Signal Erkennungs-Bereich horizontal maximum (0.0-1.0)", "edt_conf_v4l2_sDHOffsetMax_expl" : "Signal Erkennungs-Bereich horizontal maximum (0.0-1.0)",
"edt_conf_instCapture_heading_title" : "Instance Aufnahme",
"edt_conf_instC_systemEnable_title" : "Aktiviere Plattform Aufnahme",
"edt_conf_instC_systemEnable_expl" : "Aktiviert die Plattform Aufnahme für diese LED Hardware Instanz",
"edt_conf_instC_v4lEnable_title" : "Aktiviere USB Aufnahme",
"edt_conf_instC_v4lEnable_expl" : "Aktiviert die USB Aufnahme für diese LED Hardware Instanz",
"edt_conf_fg_heading_title" : "Plattform Aufnahme", "edt_conf_fg_heading_title" : "Plattform Aufnahme",
"edt_conf_fg_type_title" : "Typ", "edt_conf_fg_type_title" : "Typ",
"edt_conf_fg_type_expl" : "Art der Plattform Aufnahme, standard ist 'auto'", "edt_conf_fg_type_expl" : "Art der Plattform Aufnahme, standard ist 'auto'",

View File

@ -27,6 +27,7 @@
"general_col_green" : "green", "general_col_green" : "green",
"general_col_blue" : "blue", "general_col_blue" : "blue",
"general_button_savesettings" : "Save settings", "general_button_savesettings" : "Save settings",
"general_btn_yes" : "Yes",
"general_btn_ok" : "OK", "general_btn_ok" : "OK",
"general_btn_cancel" : "Cancel", "general_btn_cancel" : "Cancel",
"general_btn_continue" : "Continue", "general_btn_continue" : "Continue",
@ -347,7 +348,7 @@
"edt_dev_enum_white_off" : "White off", "edt_dev_enum_white_off" : "White off",
"edt_dev_general_heading_title" : "General Settings", "edt_dev_general_heading_title" : "General Settings",
"edt_dev_general_name_title" : "Configuration name", "edt_dev_general_name_title" : "Configuration name",
"edt_dev_general_ledCount_title" : "Count of all hardware LEDs", "edt_dev_general_hardwareLedCount_title" : "Hardware LED count",
"edt_dev_general_colorOrder_title" : "RGB byte order", "edt_dev_general_colorOrder_title" : "RGB byte order",
"edt_dev_general_rewriteTime_title" : "Refresh time", "edt_dev_general_rewriteTime_title" : "Refresh time",
"edt_dev_spec_header_title" : "Specific Settings", "edt_dev_spec_header_title" : "Specific Settings",
@ -483,17 +484,9 @@
"edt_conf_smooth_continuousOutput_expl" : "Update the leds even there is no changed picture.", "edt_conf_smooth_continuousOutput_expl" : "Update the leds even there is no changed picture.",
"edt_conf_v4l2_heading_title" : "USB Capture", "edt_conf_v4l2_heading_title" : "USB Capture",
"edt_conf_v4l2_device_title" : "Device", "edt_conf_v4l2_device_title" : "Device",
"edt_conf_v4l2_device_expl" : "The path to the usb capture.", "edt_conf_v4l2_device_expl" : "The path to the usb capture interface. Set to 'auto' for auto detection. Example: '/dev/video0'",
"edt_conf_v4l2_input_title" : "Input",
"edt_conf_v4l2_input_expl" : "Input of this path.",
"edt_conf_v4l2_standard_title" : "Video standard", "edt_conf_v4l2_standard_title" : "Video standard",
"edt_conf_v4l2_standard_expl" : "Select the video standard for your region.", "edt_conf_v4l2_standard_expl" : "Select the video standard for your region. 'Auto' keeps the chosen one from v4l interface",
"edt_conf_v4l2_width_title" : "Width",
"edt_conf_v4l2_width_expl" : "The width of the picture. (-1 = auto width)",
"edt_conf_v4l2_height_title" : "Height",
"edt_conf_v4l2_height_expl" : "The height of the picture. (-1 = auto height)",
"edt_conf_v4l2_frameDecimation_title" : "Frame decimation",
"edt_conf_v4l2_frameDecimation_expl" : "The factor of frame decimation",
"edt_conf_v4l2_sizeDecimation_title" : "Size decimation", "edt_conf_v4l2_sizeDecimation_title" : "Size decimation",
"edt_conf_v4l2_sizeDecimation_expl" : "The factor of size decimation. 1 means no decimation (keep original size)", "edt_conf_v4l2_sizeDecimation_expl" : "The factor of size decimation. 1 means no decimation (keep original size)",
"edt_conf_v4l2_cropLeft_title" : "Crop left", "edt_conf_v4l2_cropLeft_title" : "Crop left",
@ -505,7 +498,7 @@
"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_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.", "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",
"edt_conf_v4l2_redSignalThreshold_expl" : "Darkens low red values (recognized as black)", "edt_conf_v4l2_redSignalThreshold_expl" : "Darkens low red values (recognized as black)",
"edt_conf_v4l2_greenSignalThreshold_title" : "Green signal threshold", "edt_conf_v4l2_greenSignalThreshold_title" : "Green signal threshold",
@ -520,6 +513,11 @@
"edt_conf_v4l2_sDVOffsetMax_expl" : "Signal detection area vertical maximum (0.0-1.0)", "edt_conf_v4l2_sDVOffsetMax_expl" : "Signal detection area vertical maximum (0.0-1.0)",
"edt_conf_v4l2_sDHOffsetMax_title" : "Signal Detection HMax", "edt_conf_v4l2_sDHOffsetMax_title" : "Signal Detection HMax",
"edt_conf_v4l2_sDHOffsetMax_expl" : "Signal detection area horizontal maximum (0.0-1.0)", "edt_conf_v4l2_sDHOffsetMax_expl" : "Signal detection area horizontal maximum (0.0-1.0)",
"edt_conf_instCapture_heading_title" : "Instance Capture",
"edt_conf_instC_systemEnable_title" : "Enable platform capture",
"edt_conf_instC_systemEnable_expl" : "Enables the platform capture for this led hardware instance",
"edt_conf_instC_v4lEnable_title" : "Enable USB capture",
"edt_conf_instC_v4lEnable_expl" : "Enables the USB capture for this led hardware instance",
"edt_conf_fg_heading_title" : "Platform Capture", "edt_conf_fg_heading_title" : "Platform Capture",
"edt_conf_fg_type_title" : "Type", "edt_conf_fg_type_title" : "Type",
"edt_conf_fg_type_expl" : "Type of platform capture, default is 'auto'", "edt_conf_fg_type_expl" : "Type of platform capture, default is 'auto'",

View File

@ -4,6 +4,7 @@ $(document).ready( function() {
var conf_editor_net = null; var conf_editor_net = null;
var conf_editor_json = null; var conf_editor_json = null;
var conf_editor_proto = null; var conf_editor_proto = null;
var conf_editor_fbs = null;
var conf_editor_bobl = null; var conf_editor_bobl = null;
var conf_editor_udpl = null; var conf_editor_udpl = null;
var conf_editor_forw = null; var conf_editor_forw = null;
@ -20,6 +21,11 @@ $(document).ready( function() {
$('#conf_cont_proto').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver')); $('#conf_cont_proto').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#conf_cont_proto').append(createHelpTable(schema.protoServer.properties, $.i18n("edt_conf_ps_heading_title"))); $('#conf_cont_proto').append(createHelpTable(schema.protoServer.properties, $.i18n("edt_conf_ps_heading_title")));
//flatbufserver
$('#conf_cont').append(createRow('conf_cont_flatbuf'))
$('#conf_cont_flatbuf').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_fbs_heading_title"), 'editor_container_fbserver', 'btn_submit_fbserver'));
$('#conf_cont_flatbuf').append(createHelpTable(schema.flatbufServer.properties, $.i18n("edt_conf_fbs_heading_title")));
//boblight //boblight
$('#conf_cont').append(createRow('conf_cont_bobl')) $('#conf_cont').append(createRow('conf_cont_bobl'))
$('#conf_cont_bobl').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_bobls_heading_title"), 'editor_container_boblightserver', 'btn_submit_boblightserver')); $('#conf_cont_bobl').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_bobls_heading_title"), 'editor_container_boblightserver', 'btn_submit_boblightserver'));
@ -43,6 +49,7 @@ $(document).ready( function() {
$('#conf_cont').addClass('row'); $('#conf_cont').addClass('row');
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_js_heading_title"), 'editor_container_jsonserver', 'btn_submit_jsonserver')); $('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_js_heading_title"), 'editor_container_jsonserver', 'btn_submit_jsonserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver')); $('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_fbs_heading_title"), 'editor_container_fbserver', 'btn_submit_fbserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_bobls_heading_title"), 'editor_container_boblightserver', 'btn_submit_boblightserver')); $('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_bobls_heading_title"), 'editor_container_boblightserver', 'btn_submit_boblightserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_udpl_heading_title"), 'editor_container_udplistener', 'btn_submit_udplistener')); $('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_udpl_heading_title"), 'editor_container_udplistener', 'btn_submit_udplistener'));
if(storedAccess != 'default') if(storedAccess != 'default')
@ -62,7 +69,7 @@ $(document).ready( function() {
requestWriteConfig(conf_editor_json.getValue()); requestWriteConfig(conf_editor_json.getValue());
}); });
//proto //protobuffer
conf_editor_proto = createJsonEditor('editor_container_protoserver', { conf_editor_proto = createJsonEditor('editor_container_protoserver', {
protoServer : schema.protoServer protoServer : schema.protoServer
}, true, true); }, true, true);
@ -75,6 +82,19 @@ $(document).ready( function() {
requestWriteConfig(conf_editor_proto.getValue()); requestWriteConfig(conf_editor_proto.getValue());
}); });
//flatbuffer
conf_editor_fbs = createJsonEditor('editor_container_fbserver', {
flatbufServer : schema.flatbufServer
}, true, true);
conf_editor_fbs.on('change',function() {
conf_editor_fbs.validate().length ? $('#btn_submit_fbserver').attr('disabled', true) : $('#btn_submit_fbserver').attr('disabled', false);
});
$('#btn_submit_fbserver').off().on('click',function() {
requestWriteConfig(conf_editor_fbs.getValue());
});
//boblight //boblight
conf_editor_bobl = createJsonEditor('editor_container_boblightserver', { conf_editor_bobl = createJsonEditor('editor_container_boblightserver', {
boblightServer : schema.boblightServer boblightServer : schema.boblightServer
@ -122,6 +142,7 @@ $(document).ready( function() {
{ {
createHint("intro", $.i18n('conf_network_json_intro'), "editor_container_jsonserver"); createHint("intro", $.i18n('conf_network_json_intro'), "editor_container_jsonserver");
createHint("intro", $.i18n('conf_network_proto_intro'), "editor_container_protoserver"); createHint("intro", $.i18n('conf_network_proto_intro'), "editor_container_protoserver");
createHint("intro", $.i18n('conf_network_fbs_intro'), "editor_container_fbserver");
createHint("intro", $.i18n('conf_network_bobl_intro'), "editor_container_boblightserver"); createHint("intro", $.i18n('conf_network_bobl_intro'), "editor_container_boblightserver");
createHint("intro", $.i18n('conf_network_udpl_intro'), "editor_container_udplistener"); createHint("intro", $.i18n('conf_network_udpl_intro'), "editor_container_udplistener");
createHint("intro", $.i18n('conf_network_forw_intro'), "editor_container_forwarder"); createHint("intro", $.i18n('conf_network_forw_intro'), "editor_container_forwarder");

View File

@ -173,7 +173,7 @@ function sendToHyperion(command, subcommand, msg)
// also used for watchdog // also used for watchdog
function requestServerInfo() function requestServerInfo()
{ {
sendToHyperion("serverinfo","",'"subscribe":["components-update","sessions-update","priorities-update", "imageToLedMapping-update", "adjustment-update", "videomode-update", "effects-update"]'); sendToHyperion("serverinfo","",'"subscribe":["components-update","sessions-update","priorities-update", "imageToLedMapping-update", "adjustment-update", "videomode-update", "effects-update", "settings-update"]');
} }
function requestSysInfo() function requestSysInfo()

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,14 @@
[Unit] [Unit]
Description=Hyperion ambient light systemd service Description=Hyperion ambient light systemd service for user %i
After=network.target After=network.target
[Service] [Service]
ExecStart=/usr/bin/hyperiond ExecStart=/usr/bin/hyperiond
WorkingDirectory=/usr/share/hyperion/bin WorkingDirectory=/usr/share/hyperion/bin
User=%i
TimeoutStopSec=5 TimeoutStopSec=5
KillMode=mixed KillMode=mixed
Restart=always Restart=on-failure
RestartSec=2 RestartSec=2
[Install] [Install]

View File

@ -6,6 +6,7 @@ install_file()
dest="$2" dest="$2"
if [ ! -e "$dest" ] if [ ! -e "$dest" ]
then
cp "$src" "${dest}" cp "$src" "${dest}"
return 1 return 1
else else
@ -15,10 +16,7 @@ install_file()
} }
echo "--- hyperion ambient light postinstall ---" echo "---Hyperion ambient light postinstall ---"
echo "- install configuration template"
mkdir -p /etc/hyperion
mkdir -p /usr/share/hyperion/custom-effects
#check system #check system
CPU_RPI=`grep -m1 -c 'BCM2708\|BCM2709\|BCM2710\|BCM2835' /proc/cpuinfo` CPU_RPI=`grep -m1 -c 'BCM2708\|BCM2709\|BCM2710\|BCM2835' /proc/cpuinfo`
@ -27,25 +25,29 @@ CPU_X32X64=`uname -m | grep 'x86_32\|i686\|x86_64' | wc -l`
#Check for a bootloader as Berryboot #Check for a bootloader as Berryboot
BOOT_BERRYBOOT=$(grep -m1 -c '\(/var/media\|/media/pi\)/berryboot' /etc/mtab) BOOT_BERRYBOOT=$(grep -m1 -c '\(/var/media\|/media/pi\)/berryboot' /etc/mtab)
#get current system ip + add default port #get current system ip
address=$(ip -o -4 a | awk '$2 == "eth0" { gsub(/\/.*/, "", $4); print $4 }')":8099" NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}'`
NET_IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`
#check if hyperion is running #check if hyperion is running
HYPERION_RUNNING=false HYPERION_RUNNING=false
pgrep hyperiond > /dev/null 2>&1 && HYPERION_RUNNING=true pgrep hyperiond > /dev/null 2>&1 && HYPERION_RUNNING=true
# search for users in system, returns first entry
FOUND_USR=`who | grep -o '^\w*\b'` || "root"
start_msg="" start_msg=""
restart_msg="" restart_msg=""
SERVICE_POSTFIX=""
if grep -m1 systemd /proc/1/comm > /dev/null if grep -m1 systemd /proc/1/comm > /dev/null
then then
echo "--> init deamon: systemd" echo "--> init deamon: systemd"
# systemd # systemd
$HYPERION_RUNNING && systemctl stop hyperiond 2> /dev/null $HYPERION_RUNNING && systemctl stop hyperiond 2> /dev/null
install_file /usr/share/hyperion/service/hyperion.systemd /etc/systemd/system/hyperiond.service && systemctl -q enable hyperiond.service install_file /usr/share/hyperion/service/hyperion.systemd /etc/systemd/system/hyperiond@.service
start_msg="--> systemctl start hyperiond" systemctl enable hyperiond"@${FOUND_USR}".service
systemctl start hyperiond start_msg="--> systemctl start hyperiond for user ${FOUND_USR}"
systemctl start hyperiond"@${FOUND_USR}"
elif [ -e /sbin/initctl ] elif [ -e /sbin/initctl ]
then then
@ -100,9 +102,12 @@ if [ $CPU_RPI -eq 1 ]; then
fi fi
fi fi
echo ${start_msg}
echo "-----------------------------------------------------------------------------" echo "-----------------------------------------------------------------------------"
echo "--> Hyperion has been installed/updated!" echo "--> Hyperion has been installed/updated!"
echo "--> For configuration, visit with your browser: ${address}" echo "--> For configuration, visit with your browser: ${NET_IP}:8090"
echo "--> or if already used by another service try: ${NET_IP}:8091"
$REBOOTMESSAGE $REBOOTMESSAGE
echo "-----------------------------------------------------------------------------" echo "-----------------------------------------------------------------------------"
echo "Webpage: www.hyperion-project.org" echo "Webpage: www.hyperion-project.org"
@ -110,28 +115,12 @@ echo "Wiki: wiki.hyperion-project.org"
echo "Forum: forum.hyperion-project.org" echo "Forum: forum.hyperion-project.org"
echo "-----------------------------------------------------------------------------" echo "-----------------------------------------------------------------------------"
# try to open the browser for desktops. TODO: add headless detection(?)
if [ $CPU_X32X64 -eq 1]
echo "--> Will open browser with target: ${address}"
if [[ -e /usr/bin/xdg-open ]]
then
xdg-open http://"$address"
elif [[ -e /usr/bin/x-www-browser ]]
then
x-www-browser http://"$address"
elif [[ -e /usr/bin/www-browser ]]
then
www-browser http://"$address"
fi
fi
if [ -e /opt/hyperion/ ] if [ -e /opt/hyperion/ ]
then then
echo echo
echo "---------------------------------------------------------------------------------" echo "---------------------------------------------------------------------------------"
echo "- It seemd that you have an older version of hyperion installed in /opt/hyerion -" echo "- It seemd that you have an older version of hyperion installed in /opt/hyperion -"
echo "- please remove it and check your config to avoid problems -" echo "- please remove it to avoid problems -"
echo "---------------------------------------------------------------------------------" echo "---------------------------------------------------------------------------------"
fi fi

View File

@ -1,51 +1,56 @@
#!/bin/sh #!/bin/sh
# check which init script we should use echo "---Hyperion ambient light preinst ---"
USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm`
USE_INITCTL=`which /sbin/initctl | wc -l`
USE_SERVICE=`which /usr/sbin/service | wc -l`
#check for hyperion install # search for users in system, returns first entry
if [ -d /usr/share/hyperion/bin ];then FOUND_USR=`who | grep -o '^\w*\b'` || "root"
if [ -e /etc/hyperion/hyperion.config.json ];then
file=`grep -m1 -c '"general"' /etc/hyperion/hyperion.config.json`
if [ $file -ne 1 ]; then
echo "--> It seems you are running an old version of Hyperion (1.X). Will create a backup at /usr/share/hyperion/Backup_Hyperion_1.0 and reset configuration / system service"
# Stop hyperion daemon if it is running # stop running daemon before we install
echo '---> Stop Hyperion, if necessary' if pgrep hyperiond > /dev/null 2>&1
if [ $USE_SYSTEMD -eq 1 ]; then then
service hyperion stop 2>/dev/null if grep -m1 systemd /proc/1/comm > /dev/null
elif [ $USE_INITCTL -eq 1 ]; then then
/sbin/initctl stop hyperion 2>/dev/null echo "--> stop init deamon: systemd"
elif [ $USE_SERVICE -eq 1 ]; then # systemd
/usr/sbin/service hyperion stop 2>/dev/null systemctl stop hyperiond"@${FOUND_USR}" 2> /dev/null
fi
#Backup elif [ -e /sbin/initctl ]
echo "--> Move old config(s) and files to /usr/share/hyperion/Backup_Hyperion_1.0" then
mkdir /usr/share/hyperion/Backup_Hyperion_1.0 echo "--> stop init deamon: upstart"
mv /usr/share/hyperion /usr/share/hyperion/Backup_Hyperion_1.0 # upstart
mv /etc/hyperion/* /usr/share/hyperion/Backup_Hyperion_1.0 initctl stop hyperiond
#Disabling and delete service files else
if [ $USE_SYSTEMD -eq 1 ]; then echo "--> stop init deamon: sysV"
# Delete and disable Hyperion systemd script # sysV
echo '---> Delete and disable Hyperion systemd service' service hyperiond stop 2>/dev/null
systemctl disable hyperion.service
rm -v /etc/systemd/system/hyperion* 2>/dev/null
elif [ $USE_INITCTL -eq 1 ]; then
echo '---> Delete and disable Hyperion initctl script'
rm -v /etc/init/hyperion* 2>/dev/null
initctl reload-configuration
elif [ $USE_SERVICE -eq 1 ]; then
# Delete and disable Hyperion init.d script
echo '---> Delete and disable Hyperion init.d script'
update-rc.d -f hyperion remove
rm /etc/init.d/hyperion* 2>/dev/null
fi
echo "--> Hyperion 1.0 installation has been moved"
fi
fi fi
fi fi
#$USR=hyperionIS;
#addToGroup()
##{
# getent group $1 && adduser $USR $1;
#}
#check if user exists
#if id $USR >/dev/null 2>&1; then
# echo "--> hyperion user exists, skip creation";
#else
## create user
# echo "--> Create Hyperion user";
# adduser --system --group $USR;
#fi
# add user to groups if required
## secondary user groups that are required to access system things
#addToGroup(dialout);
#addToGroup(video);
#addToGroup(audio);
#addToGroup(systemd-journal);
# platform specific groups
#addToGroup(i2c);
#addToGroup(spi);
#addToGroup(gpio);

40
cmake/debian/prerm Normal file
View File

@ -0,0 +1,40 @@
#!/bin/sh
echo "---Hyperion ambient light prerm ---"
# search for users in system, returns first entry
FOUND_USR=`who | grep -o '^\w*\b'` || "root"
# stop running daemon before we delete it
HYPERION_RUNNING=false
pgrep hyperiond > /dev/null 2>&1 && HYPERION_RUNNING=true
if grep -m1 systemd /proc/1/comm > /dev/null
then
echo "--> stop init deamon: systemd"
# systemd
$HYPERION_RUNNING && systemctl stop hyperiond"@${FOUND_USR}" 2> /dev/null
# disable user specific symlink
echo "--> Disable service and remove entry"
systemctl -q disable hyperiond"@${FOUND_USR}"
rm -v /etc/systemd/system/hyperiond@.service 2>/dev/null
elif [ -e /sbin/initctl ]
then
echo "--> stop init deamon: upstart"
# upstart
$HYPERION_RUNNING && initctl stop hyperiond
echo "--> Remove upstart service"
rm -v /etc/init/hyperion* 2>/dev/null
initctl reload-configuration
else
echo "--> stop init deamon: sysV"
# sysV
$HYPERION_RUNNING && service hyperiond stop 2>/dev/null
echo "--> Remove sysV service"
update-rc.d -f hyperion remove
rm /etc/init.d/hyperion* 2>/dev/null
fi
return 0

View File

@ -13,9 +13,9 @@ SET ( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" )
SET ( CPACK_DEBIAN_PACKAGE_MAINTAINER "Hyperion Team") SET ( CPACK_DEBIAN_PACKAGE_MAINTAINER "Hyperion Team")
SET ( CPACK_DEBIAN_PACKAGE_NAME "Hyperion" ) SET ( CPACK_DEBIAN_PACKAGE_NAME "Hyperion" )
SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/preinst" ) SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/preinst;${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian/prerm" )
SET ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.hyperion-project.org" ) SET ( CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://www.hyperion-project.org" )
SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a (>= 5.2.0), libqt5network5 (>= 5.2.0), libqt5gui5 (>= 5.2.0), libqt5serialport5 (>= 5.2.0), libavahi-core7 (>= 0.6.31), libavahi-compat-libdnssd1 (>= 0.6.31), libusb-1.0-0, libpython3.4, libc6" ) SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5core5a (>= 5.5.0), libqt5network5 (>= 5.5.0), libqt5gui5 (>= 5.5.0), libqt5serialport5 (>= 5.5.0), libqt5sql5 (>= 5.5.0), libavahi-core7 (>= 0.6.31), libavahi-compat-libdnssd1 (>= 0.6.31), libusb-1.0-0, libpython3.5, libc6" )
SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" ) SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" )
SET ( CPACK_RPM_PACKAGE_NAME "Hyperion" ) SET ( CPACK_RPM_PACKAGE_NAME "Hyperion" )

View File

@ -20,14 +20,14 @@
/// Device configuration contains the following fields: /// Device configuration contains the following fields:
/// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'name' : The user friendly name of the device (only used for display purposes)
/// * 'type' : The type of the device or leds (known types for now are /// * 'type' : The type of the device
/// APA102, WS2801, P9813, LPD6803, LPD8806, ---------PWM---------, WS2812b (just RPi1), WS281X (RPi1, RPi2, RPi3), --------OTHER--------, PhilipsHUE, AtmoOrb, PiBlaster, Tinkerforge, FadeCandy, RawHID (USB), UDP, SEDU, TPM2, USBASP-WS2801, USBASP-WS2812, ------3rd PARTY------, Adalight, AdalightAPA102, Atmo, Lightpack, Multi-Lightpack, Paintpack, Test (file), None)
/// * [device type specific configuration] /// * [device type specific configuration]
/// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.).
/// * 'rewriteTime': in ms. Data is resend to leds, if no new data is available in thistime. 0 means no refresh /// * 'rewriteTime': in ms. Data is resend to leds, if no new data is available in thistime. 0 means no refresh
"device" : "device" :
{ {
"type" : "file", "type" : "file",
"hardwareLedCount" : 1,
"output" : "/dev/null", "output" : "/dev/null",
"rate" : 1000000, "rate" : 1000000,
"colorOrder" : "rgb", "colorOrder" : "rgb",
@ -98,8 +98,7 @@
}, },
/// Configuration for the embedded V4L2 grabber /// Configuration for the embedded V4L2 grabber
/// * device : V4L2 Device to use [default="/dev/video0"] /// * device : V4L2 Device to use [default="auto"] (Auto detection)
/// * input : V4L2 input to use [default=0]
/// * standard : Video standard (PAL/NTSC/SECAM/NO_CHANGE) [default="NO_CHANGE"] /// * standard : Video standard (PAL/NTSC/SECAM/NO_CHANGE) [default="NO_CHANGE"]
/// * sizeDecimation : Size decimation factor [default=8] /// * sizeDecimation : Size decimation factor [default=8]
/// * cropLeft : Cropping from the left [default=0] /// * cropLeft : Cropping from the left [default=0]
@ -118,7 +117,6 @@
[ [
{ {
"device" : "auto", "device" : "auto",
"input" : 0,
"standard" : "NO_CHANGE", "standard" : "NO_CHANGE",
"sizeDecimation" : 8, "sizeDecimation" : 8,
"priority" : 240, "priority" : 240,
@ -233,13 +231,22 @@
"port" : 19444 "port" : 19444
}, },
/// The configuration of the Proto server which enables the protobuffer remote interface /// The configuration of the Protobuffer server which enables the Protobuffer remote interface
/// * port : Port at which the protobuffer server is started /// * port : Port at which the protobuffer server is started
"protoServer" : "protoServer" :
{ {
"port" : 19445 "port" : 19445
}, },
/// The configuration of the Flatbuffer server which enables the Flatbuffer remote interface
/// * port : Port at which the flatbuffer server is started
"flatbufServer" :
{
"enable" : true,
"port" : 19400,
"timeout" : 5
},
/// The configuration of the boblight server which enables the boblight remote interface /// The configuration of the boblight server which enables the boblight remote interface
/// * enable : Enable or disable the boblight server (true/false) /// * enable : Enable or disable the boblight server (true/false)
/// * port : Port at which the boblight server is started /// * port : Port at which the boblight server is started
@ -269,12 +276,10 @@
}, },
/// Configuration of the Hyperion webserver /// Configuration of the Hyperion webserver
/// * enable : enable or disable the webserver (true/false)
/// * document_root : path to hyperion webapp files (webconfig developer only) /// * document_root : path to hyperion webapp files (webconfig developer only)
/// * port : the port where hyperion webapp is accasible /// * port : the port where hyperion webapp is accasible
"webConfig" : "webConfig" :
{ {
"enable" : true,
"document_root" : "/path/to/files", "document_root" : "/path/to/files",
"port" : 8090 "port" : 8090
}, },

View File

@ -12,6 +12,7 @@
"device" : "device" :
{ {
"type" : "file", "type" : "file",
"hardwareLedCount" : 1,
"output" : "/dev/null", "output" : "/dev/null",
"rate" : 1000000, "rate" : 1000000,
"colorOrder" : "rgb", "colorOrder" : "rgb",
@ -58,7 +59,6 @@
[ [
{ {
"device" : "auto", "device" : "auto",
"input" : 0,
"standard" : "NO_CHANGE", "standard" : "NO_CHANGE",
"sizeDecimation" : 8, "sizeDecimation" : 8,
"cropLeft" : 0, "cropLeft" : 0,
@ -135,6 +135,13 @@
"port" : 19445 "port" : 19445
}, },
"flatbufServer" :
{
"enable" : true,
"port" : 19400,
"timeout" : 5
},
"boblightServer" : "boblightServer" :
{ {
"enable" : false, "enable" : false,
@ -154,7 +161,6 @@
"webConfig" : "webConfig" :
{ {
"enable" : true,
"document_root" : "", "document_root" : "",
"port" : 8090 "port" : 8090
}, },

View File

@ -9,6 +9,48 @@ if(ENABLE_WS281XPWM)
external/rpi_ws281x/rpihw.c) external/rpi_ws281x/rpihw.c)
endif() endif()
set(USE_SYSTEM_FLATBUFFERS_LIBS ${DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS} CACHE BOOL "use flatbuffers library from system")
if (USE_SYSTEM_FLATBUFFERS_LIBS)
find_package(flatbuffers REQUIRED)
include_directories(${FLATBUFFERS_INCLUDE_DIRS})
else ()
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared flatbuffers library")
set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "Build Flatbuffers with tests")
add_subdirectory(external/flatbuffers)
if(CMAKE_CROSSCOMPILING)
# when crosscompiling import the flatc executable targets from a file generated by a native build
option(IMPORT_FLATC "flatc export file (flatc_export.cmake) from a native build" "IMPORT_FLATC-FILE_NOT_FOUND")
include(${IMPORT_FLATC})
else()
# export the flatc compiler so it can be used when cross compiling
export(TARGETS flatc FILE "${CMAKE_BINARY_DIR}/flatc_export.cmake")
endif()
# define the include for the flatbuffers library at the parent scope
set(FLATBUFFERS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/flatbuffers/include")
set(FLATBUFFERS_INCLUDE_DIRS ${FLATBUFFERS_INCLUDE_DIRS} PARENT_SCOPE)
# define the flatc executable at the parent scope
get_property(FLATBUFFERS_FLATC_EXECUTABLE TARGET flatc PROPERTY LOCATION)
set(FLATBUFFERS_FLATC_EXECUTABLE ${FLATBUFFERS_FLATC_EXECUTABLE} PARENT_SCOPE)
endif()
message(STATUS "Using flatbuffers compiler: " ${FLATBUFFERS_FLATC_EXECUTABLE})
function(compile_flattbuffer_schema SRC_FBS OUTPUT_DIR)
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
add_custom_command(
OUTPUT ${GEN_HEADER}
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
--gen-object-api
-o "${OUTPUT_DIR}"
"${SRC_FBS}"
DEPENDS flatc)
endfunction()
set(USE_SYSTEM_PROTO_LIBS ${DEFAULT_USE_SYSTEM_PROTO_LIBS} CACHE BOOL "use protobuf library from system") set(USE_SYSTEM_PROTO_LIBS ${DEFAULT_USE_SYSTEM_PROTO_LIBS} CACHE BOOL "use protobuf library from system")
if (USE_SYSTEM_PROTO_LIBS) if (USE_SYSTEM_PROTO_LIBS)

254
include/api/JsonAPI.h Normal file
View File

@ -0,0 +1,254 @@
#pragma once
// hyperion includes
#include <utils/Logger.h>
#include <utils/jsonschema/QJsonSchemaChecker.h>
#include <utils/Components.h>
#include <hyperion/Hyperion.h>
// qt includess
#include <QTimer>
#include <QJsonObject>
#include <QMutex>
#include <QString>
// createEffect helper
struct find_schema: std::unary_function<EffectSchema, bool>
{
QString pyFile;
find_schema(QString pyFile):pyFile(pyFile) { }
bool operator()(EffectSchema const& schema) const
{
return schema.pyFile == pyFile;
}
};
// deleteEffect helper
struct find_effect: std::unary_function<EffectDefinition, bool>
{
QString effectName;
find_effect(QString effectName) :effectName(effectName) { }
bool operator()(EffectDefinition const& effectDefinition) const
{
return effectDefinition.name == effectName;
}
};
class JsonCB;
class JsonAPI : public QObject
{
Q_OBJECT
public:
///
/// Constructor
///
/// @param peerAddress provide the Address of the peer
/// @param log The Logger class of the creator
/// @param parent Parent QObject
/// @param noListener if true, this instance won't listen for hyperion push events
///
JsonAPI(QString peerAddress, Logger* log, QObject* parent, bool noListener = false);
///
/// Handle an incoming JSON message
///
/// @param message the incoming message as string
///
void handleMessage(const QString & message, const QString& httpAuthHeader = "");
public slots:
/// _timer_ledcolors requests ledcolor updates (if enabled)
void streamLedcolorsUpdate();
/// push images whenever hyperion emits (if enabled)
void setImage(const Image<ColorRgb> & image);
/// process and push new log messages from logger (if enabled)
void incommingLogMessage(Logger::T_LOG_MESSAGE);
signals:
///
/// Signal emits with the reply message provided with handleMessage()
///
void callbackMessage(QJsonObject);
///
/// Signal emits whenever a jsonmessage should be forwarded
///
void forwardJsonMessage(QJsonObject);
private:
// The JsonCB instance which handles data subscription/notifications
JsonCB* _jsonCB;
// true if further callbacks are forbidden (http)
bool _noListener;
/// The peer address of the client
QString _peerAddress;
/// Log instance
Logger* _log;
/// Hyperion instance
Hyperion* _hyperion;
/// timer for ledcolors streaming
QTimer _timer_ledcolors;
// streaming buffers
QJsonObject _streaming_leds_reply;
QJsonObject _streaming_image_reply;
QJsonObject _streaming_logging_reply;
/// flag to determine state of log streaming
bool _streaming_logging_activated;
/// mutex to determine state of image streaming
QMutex _image_stream_mutex;
/// timeout for live video refresh
volatile qint64 _image_stream_timeout;
///
/// Handle an incoming JSON Color message
///
/// @param message the incoming message
///
void handleColorCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Image message
///
/// @param message the incoming message
///
void handleImageCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Effect message
///
/// @param message the incoming message
///
void handleEffectCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Effect message (Write JSON Effect)
///
/// @param message the incoming message
///
void handleCreateEffectCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Effect message (Delete JSON Effect)
///
/// @param message the incoming message
///
void handleDeleteEffectCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON System info message
///
/// @param message the incoming message
///
void handleSysInfoCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Server info message
///
/// @param message the incoming message
///
void handleServerInfoCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Clear message
///
/// @param message the incoming message
///
void handleClearCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Adjustment message
///
/// @param message the incoming message
///
void handleAdjustmentCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON SourceSelect message
///
/// @param message the incoming message
///
void handleSourceSelectCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON GetConfig message and check subcommand
///
/// @param message the incoming message
///
void handleConfigCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON GetConfig message from handleConfigCommand()
///
/// @param message the incoming message
///
void handleSchemaGetCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON SetConfig message from handleConfigCommand()
///
/// @param message the incoming message
///
void handleConfigSetCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON Component State message
///
/// @param message the incoming message
///
void handleComponentStateCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON Led Colors message
///
/// @param message the incoming message
///
void handleLedColorsCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON Logging message
///
/// @param message the incoming message
///
void handleLoggingCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON Proccessing message
///
/// @param message the incoming message
///
void handleProcessingCommand(const QJsonObject & message, const QString &command, const int tan);
/// Handle an incoming JSON VideoMode message
///
/// @param message the incoming message
///
void handleVideoModeCommand(const QJsonObject & message, const QString &command, const int tan);
///
/// Handle an incoming JSON message of unknown type
///
void handleNotImplemented();
///
/// Send a standard reply indicating success
///
void sendSuccessReply(const QString &command="", const int tan=0);
///
/// Send a standard reply indicating success with data
///
void sendSuccessDataReply(const QJsonDocument &doc, const QString &command="", const int &tan=0);
///
/// Send an error message back to the client
///
/// @param error String describing the error
///
void sendErrorReply(const QString & error, const QString &command="", const int tan=0);
};

112
include/api/JsonCB.h Normal file
View File

@ -0,0 +1,112 @@
#pragma once
// qt incl
#include <QObject>
#include <QJsonObject>
// components def
#include <utils/Components.h>
// bonjour
#include <bonjour/bonjourrecord.h>
// videModes
#include <utils/VideoMode.h>
// settings
#include <utils/settings.h>
class Hyperion;
class ComponentRegister;
class BonjourBrowserWrapper;
class PriorityMuxer;
class JsonCB : public QObject
{
Q_OBJECT
public:
JsonCB(QObject* parent);
///
/// @brief Subscribe to future data updates given by cmd
/// @param cmd The cmd which will be subscribed for
/// @return True on success, false if not found
///
bool subscribeFor(const QString& cmd);
///
/// @brief Get all possible commands to subscribe for
/// @return The list of commands
///
QStringList getCommands() { return _availableCommands; };
///
/// @brief Get all subscribed commands
/// @return The list of commands
///
QStringList getSubscribedCommands() { return _subscribedCommands; };
signals:
///
/// @brief Emits whenever a new json mesage callback is ready to send
/// @param The JsonObject message
///
void newCallback(QJsonObject);
private slots:
///
/// @brief handle component state changes
///
void handleComponentState(const hyperion::Components comp, const bool state);
///
/// @brief handle emits from bonjour wrapper
/// @param bRegisters The full register map
///
void handleBonjourChange(const QMap<QString,BonjourRecord>& bRegisters);
///
/// @brief handle emits from PriorityMuxer
///
void handlePriorityUpdate();
///
/// @brief Handle imageToLedsMapping updates
///
void handleImageToLedsMappingChange(const int& mappingType);
///
/// @brief Handle the adjustment update
///
void handleAdjustmentChange();
///
/// @brief Handle video mode change
/// @param mode The new videoMode
///
void handleVideoModeChange(const VideoMode& mode);
///
/// @brief Handle effect list change
///
void handleEffectListChange();
///
/// @brief Handle a config part change. This does NOT include (global) changes from other hyperion instances
/// @param type The settings type from enum
/// @param data The data as QJsonDocument
///
void handleSettingsChange(const settings::type& type, const QJsonDocument& data);
private:
/// pointer of Hyperion instance
Hyperion* _hyperion;
/// pointer of comp register
ComponentRegister* _componentRegister;
/// Bonjour instance
BonjourBrowserWrapper* _bonjour;
/// priority muxer instance
PriorityMuxer* _prioMuxer;
/// contains all available commands
QStringList _availableCommands;
/// contains active subscriptions
QStringList _subscribedCommands;
/// construct callback msg
void doCallback(const QString& cmd, const QVariant& data);
};

View File

@ -31,7 +31,7 @@ public:
/// @param hyperion Hyperion instance /// @param hyperion Hyperion instance
/// @param port port number on which to start listening for connections /// @param port port number on which to start listening for connections
/// ///
BoblightServer(const QJsonDocument& config); BoblightServer(Hyperion* hyperion, const QJsonDocument& config);
~BoblightServer(); ~BoblightServer();
/// ///

View File

@ -47,6 +47,8 @@ public:
void registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt = std::vector<std::pair<std::string, std::string>>()); void registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt = std::vector<std::pair<std::string, std::string>>());
inline BonjourRecord registeredRecord() const {return finalRecord; } inline BonjourRecord registeredRecord() const {return finalRecord; }
const quint16 & getPort() { return _port; };
signals: signals:
void error(DNSServiceErrorType error); void error(DNSServiceErrorType error);
void serviceRegistered(const BonjourRecord &record); void serviceRegistered(const BonjourRecord &record);
@ -62,6 +64,9 @@ private:
DNSServiceRef dnssref; DNSServiceRef dnssref;
QSocketNotifier *bonjourSocket; QSocketNotifier *bonjourSocket;
BonjourRecord finalRecord; BonjourRecord finalRecord;
// current port
quint16 _port = 0;
}; };
#endif // BONJOURSERVICEREGISTER_H #endif // BONJOURSERVICEREGISTER_H

View File

@ -19,7 +19,7 @@
#include "hyperion_request_generated.h" #include "hyperion_request_generated.h"
/// ///
/// Connection class to setup an connection to the hyperion server and execute commands. Used from standalone capture binaries (x11/dispamnx/...) /// Connection class to setup an connection to the hyperion server and execute commands.
/// ///
class FlatBufferConnection : public QObject class FlatBufferConnection : public QObject
{ {
@ -40,7 +40,7 @@ public:
~FlatBufferConnection(); ~FlatBufferConnection();
/// Do not read reply messages from Hyperion if set to true /// Do not read reply messages from Hyperion if set to true
void setSkipReply(bool skip); void setSkipReply(const bool& skip);
/// ///
/// Set all leds to the specified color /// Set all leds to the specified color
@ -116,8 +116,8 @@ private:
/// Host port /// Host port
uint16_t _port; uint16_t _port;
/// Skip receiving reply messages from Hyperion if set /// buffer for reply
bool _skipReply; QByteArray _receiveBuffer;
QTimer _timer; QTimer _timer;
QAbstractSocket::SocketState _prevSocketState; QAbstractSocket::SocketState _prevSocketState;

View File

@ -9,7 +9,6 @@
class QTcpServer; class QTcpServer;
class FlatBufferClient; class FlatBufferClient;
class NetOrigin;
/// ///
/// @brief A TcpServer to receive images of different formats with Google Flatbuffer /// @brief A TcpServer to receive images of different formats with Google Flatbuffer
@ -57,7 +56,6 @@ private:
private: private:
QTcpServer* _server; QTcpServer* _server;
NetOrigin* _netOrigin;
Logger* _log; Logger* _log;
int _timeout; int _timeout;
quint16 _port; quint16 _port;

View File

@ -42,7 +42,7 @@ public:
/// ///
///@brief Set new width and height for dispmanx, overwrite Grabber.h impl ///@brief Set new width and height for dispmanx, overwrite Grabber.h impl
virtual void setWidthHeight(int width, int height); virtual bool setWidthHeight(int width, int height);
private: private:
/// ///

View File

@ -14,6 +14,8 @@
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
#include <grabber/VideoStandard.h> #include <grabber/VideoStandard.h>
class QTimer;
/// Capture class for V4L2 devices /// Capture class for V4L2 devices
/// ///
/// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html /// @see http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
@ -23,7 +25,6 @@ class V4L2Grabber : public Grabber
public: public:
V4L2Grabber(const QString & device, V4L2Grabber(const QString & device,
int input,
VideoStandard videoStandard, VideoStandard videoStandard,
PixelFormat pixelFormat, PixelFormat pixelFormat,
int pixelDecimation int pixelDecimation
@ -71,7 +72,7 @@ public:
/// ///
/// @brief overwrite Grabber.h implementation /// @brief overwrite Grabber.h implementation
/// ///
virtual void setInputVideoStandard(int input, VideoStandard videoStandard); virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard);
public slots: public slots:
@ -86,6 +87,11 @@ signals:
private slots: private slots:
int read_frame(); int read_frame();
///
/// @brief Is called whenever the _readFrameAdaptTimer emits to unlock read_frame() through _readFrame bool
///
void unlockReadFrame() { _readFrame = true; };
private: private:
void getV4Ldevices(); void getV4Ldevices();
@ -161,4 +167,6 @@ private:
bool _initialized; bool _initialized;
bool _deviceAutoDiscoverEnabled; bool _deviceAutoDiscoverEnabled;
QTimer* _readFrameAdaptTimer;
bool _readFrame = false;
}; };

View File

@ -9,7 +9,6 @@ class V4L2Wrapper : public GrabberWrapper
public: public:
V4L2Wrapper(const QString & device, V4L2Wrapper(const QString & device,
int input,
VideoStandard videoStandard, VideoStandard videoStandard,
PixelFormat pixelFormat, PixelFormat pixelFormat,
int pixelDecimation ); int pixelDecimation );

View File

@ -42,7 +42,7 @@ public:
/// ///
/// @brief Apply new width/height values, overwrite Grabber.h implementation as X11 doesn't use width/height, just pixelDecimation to calc dimensions /// @brief Apply new width/height values, overwrite Grabber.h implementation as X11 doesn't use width/height, just pixelDecimation to calc dimensions
/// ///
virtual void setWidthHeight(int width, int height); virtual bool setWidthHeight(int width, int height) { return true; };
/// ///
/// @brief Apply new pixelDecimation /// @brief Apply new pixelDecimation

View File

@ -6,6 +6,7 @@
#include <utils/Image.h> #include <utils/Image.h>
class Hyperion; class Hyperion;
class QTimer;
/// ///
/// @brief Capture Control class which is a interface to the HyperionDaemon native capture classes. /// @brief Capture Control class which is a interface to the HyperionDaemon native capture classes.
@ -48,6 +49,11 @@ private slots:
/// ///
void handleV4lImage(const Image<ColorRgb> & image); void handleV4lImage(const Image<ColorRgb> & image);
///
/// @brief Is called from _v4lInactiveTimer to set source after specific time to inactive
///
void setV4lInactive();
private: private:
/// Hyperion instance /// Hyperion instance
Hyperion* _hyperion; Hyperion* _hyperion;
@ -59,4 +65,5 @@ private:
/// Reflect state of v4l capture and prio /// Reflect state of v4l capture and prio
bool _v4lCaptEnabled; bool _v4lCaptEnabled;
quint8 _v4lCaptPrio; quint8 _v4lCaptPrio;
QTimer* _v4lInactiveTimer;
}; };

View File

@ -33,9 +33,9 @@ public:
/// ///
/// @brief Check if a component is currently enabled /// @brief Check if a component is currently enabled
/// @param comp The component from enum /// @param comp The component from enum
/// @return True if component is running else false /// @return True if component is running else false. Not found is -1
/// ///
bool isComponentEnabled(const hyperion::Components& comp) const; int isComponentEnabled(const hyperion::Components& comp) const;
/// contains all components and their state /// contains all components and their state
std::map<hyperion::Components, bool> getRegister() { return _componentStates; }; std::map<hyperion::Components, bool> getRegister() { return _componentStates; };

View File

@ -36,7 +36,7 @@ public:
/// ///
/// @brief Apply new width/height values, on errors (collide with cropping) reject the values /// @brief Apply new width/height values, on errors (collide with cropping) reject the values
/// ///
virtual void setWidthHeight(int width, int height); virtual bool setWidthHeight(int width, int height);
/// ///
/// @brief Apply new pixelDecimation (used from x11) /// @brief Apply new pixelDecimation (used from x11)
@ -66,9 +66,9 @@ public:
virtual void setSignalDetectionEnable(bool enable) {}; virtual void setSignalDetectionEnable(bool enable) {};
/// ///
/// @brief Apply input and videoStanded (used from v4l) /// @brief Apply device and videoStanded (used from v4l)
/// ///
virtual void setInputVideoStandard(int input, VideoStandard videoStandard) {}; virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard) {};
/// ///
/// @brief Apply display index (used from x11) /// @brief Apply display index (used from x11)

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <utils/Logger.h> #include <utils/Logger.h>
#include <utils/Components.h> #include <utils/Components.h>
#include <hyperion/Hyperion.h>
#include <utils/Image.h> #include <utils/Image.h>
#include <utils/ColorRgb.h> #include <utils/ColorRgb.h>
#include <utils/VideoMode.h> #include <utils/VideoMode.h>
@ -98,9 +99,6 @@ protected:
QString _grabberName; QString _grabberName;
/// Pointer to Hyperion for writing led values
Hyperion * _hyperion;
/// The timer for generating events with the specified update rate /// The timer for generating events with the specified update rate
QTimer* _timer; QTimer* _timer;
@ -110,9 +108,6 @@ protected:
/// The Logger instance /// The Logger instance
Logger * _log; Logger * _log;
// forwarding enabled
bool _forward;
Grabber *_ggrabber; Grabber *_ggrabber;
/// The image used for grabbing frames /// The image used for grabbing frames

View File

@ -49,6 +49,7 @@ class ColorAdjustment;
class SettingsManager; class SettingsManager;
class BGEffectHandler; class BGEffectHandler;
class CaptureCont; class CaptureCont;
class BoblightServer;
/// ///
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through /// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
@ -105,6 +106,8 @@ public:
/// ///
PriorityMuxer* getMuxerInstance() { return &_muxer; }; PriorityMuxer* getMuxerInstance() { return &_muxer; };
ImageProcessor* getImageProcessor() { return _imageProcessor; };
/// ///
/// @brief Get a setting by settings::type from SettingsManager /// @brief Get a setting by settings::type from SettingsManager
/// @param type The settingsType from enum /// @param type The settingsType from enum
@ -145,7 +148,7 @@ public:
bool isCurrentPriority(const int priority) const; bool isCurrentPriority(const int priority) const;
/// ///
/// Returns a list of active priorities /// Returns a list of all registered priorities
/// ///
/// @return The list with priorities /// @return The list with priorities
/// ///
@ -279,6 +282,13 @@ public slots:
/// ///
const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1, const bool& clearEffect = true); const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1, const bool& clearEffect = true);
///
/// @brief Set the given priority to inactive
/// @param priority The priority
/// @return True on success false if not found
///
const bool setInputInactive(const quint8& priority);
/// ///
/// Writes a single color to all the leds for the given time and priority /// Writes a single color to all the leds for the given time and priority
/// Registers comp color or provided type against muxer /// Registers comp color or provided type against muxer
@ -540,4 +550,7 @@ private:
std::vector<ColorRgb> _ledBuffer; std::vector<ColorRgb> _ledBuffer;
/// buffer for leds (without adjustment) /// buffer for leds (without adjustment)
std::vector<ColorRgb> _rawLedBuffer; std::vector<ColorRgb> _rawLedBuffer;
/// Boblight instance
BoblightServer* _boblightServer;
}; };

View File

@ -162,6 +162,13 @@ public:
/// ///
const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1); const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1);
///
/// @brief Set the given priority to inactive
/// @param priority The priority
/// @return True on success false if not found
///
const bool setInputInactive(const quint8& priority);
/// ///
/// Clears the specified priority channel and update _currentPriority on success /// Clears the specified priority channel and update _currentPriority on success
/// ///

View File

@ -6,7 +6,6 @@
// qt incl // qt incl
#include <QJsonObject> #include <QJsonObject>
class SettingsTable;
class Hyperion; class Hyperion;
/// ///
@ -63,8 +62,6 @@ private:
Hyperion* _hyperion; Hyperion* _hyperion;
/// Logger instance /// Logger instance
Logger* _log; Logger* _log;
/// instance of database table interface
SettingsTable* _sTable;
/// the schema /// the schema
static QJsonObject schemaJson; static QJsonObject schemaJson;
/// the current config of this instance /// the current config of this instance

View File

@ -8,12 +8,10 @@
#include <utils/Logger.h> #include <utils/Logger.h>
#include <utils/settings.h> #include <utils/settings.h>
class Hyperion;
class QTcpServer; class QTcpServer;
class QTcpSocket; class QTcpSocket;
class JsonClientConnection; class JsonClientConnection;
class BonjourServiceRegister; class BonjourServiceRegister;
class ComponentRegister;
class NetOrigin; class NetOrigin;
/// ///
@ -50,12 +48,7 @@ private slots:
/// ///
void closedConnection(void); void closedConnection(void);
/// forward message to all json slaves
void forwardJsonMessage(const QJsonObject &message);
public slots: public slots:
/// process current forwarder state
void componentStateChanged(const hyperion::Components component, bool enable);
/// ///
/// forward message to a single json slaves /// forward message to a single json slaves
@ -75,18 +68,12 @@ private:
/// The TCP server object /// The TCP server object
QTcpServer * _server; QTcpServer * _server;
/// Link to Hyperion to get config state emiter
Hyperion * _hyperion;
/// List with open connections /// List with open connections
QSet<JsonClientConnection *> _openConnections; QSet<JsonClientConnection *> _openConnections;
/// the logger instance /// the logger instance
Logger * _log; Logger * _log;
/// Component Register pointer
ComponentRegister* _componentRegister;
NetOrigin* _netOrigin; NetOrigin* _netOrigin;
/// port /// port

View File

@ -25,8 +25,6 @@ class ProtoConnection;
class QTcpServer; class QTcpServer;
class Hyperion; class Hyperion;
class BonjourServiceRegister; class BonjourServiceRegister;
class ComponentRegister;
class NetOrigin;
namespace proto { namespace proto {
class HyperionRequest; class HyperionRequest;
@ -55,8 +53,6 @@ public:
uint16_t getPort() const; uint16_t getPort() const;
public slots: public slots:
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
void componentStateChanged(const hyperion::Components component, bool enable);
/// ///
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor /// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
@ -65,12 +61,6 @@ public slots:
/// ///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config); void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
signals:
///
/// Forwarding videoMode
///
void videoMode(const VideoMode VideoMode);
private slots: private slots:
/// ///
/// Slot which is called when a client tries to create a new connection /// Slot which is called when a client tries to create a new connection
@ -83,8 +73,6 @@ private slots:
/// ///
void closedConnection(ProtoClientConnection * connection); void closedConnection(ProtoClientConnection * connection);
void newMessage(const proto::HyperionRequest * message);
private: private:
/// Hyperion instance /// Hyperion instance
Hyperion * _hyperion; Hyperion * _hyperion;
@ -94,26 +82,13 @@ private:
/// List with open connections /// List with open connections
QSet<ProtoClientConnection *> _openConnections; QSet<ProtoClientConnection *> _openConnections;
QStringList _forwardClients;
/// Hyperion proto connection object for forwarding
QList<ProtoConnection*> _proxy_connections;
/// Logger instance /// Logger instance
Logger * _log; Logger * _log;
/// Component Register
ComponentRegister* _componentRegister;
/// Network Origin Check
NetOrigin* _netOrigin;
/// Service register /// Service register
BonjourServiceRegister * _serviceRegister = nullptr; BonjourServiceRegister * _serviceRegister = nullptr;
/// flag if forwarder is enabled
bool _forwarder_enabled;
uint16_t _port = 0; uint16_t _port = 0;
/// Start server /// Start server

View File

@ -11,15 +11,13 @@
// Hyperion includes // Hyperion includes
#include <utils/Logger.h> #include <utils/Logger.h>
#include <utils/Components.h> #include <utils/Components.h>
#include <utils/ColorRgb.h>
// settings // settings
#include <utils/settings.h> #include <utils/settings.h>
class Hyperion;
class UDPClientConnection;
class BonjourServiceRegister; class BonjourServiceRegister;
class QUdpSocket; class QUdpSocket;
class NetOrigin;
/// ///
/// This class creates a UDP server which accepts connections from boblight clients. /// This class creates a UDP server which accepts connections from boblight clients.
@ -67,6 +65,22 @@ public slots:
/// ///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config); void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
signals:
///
/// @brief forward register data to HyperionDaemon
///
void registerGlobalInput(const int priority, const hyperion::Components& component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = 0);
///
/// @brief forward led data to HyperionDaemon
///
const bool setGlobalInput(const int priority, const std::vector<ColorRgb>& ledColors, const int timeout_ms = -1, const bool& clearEffect = true);
///
/// @brief forward clear to HyperionDaemon
///
void clearGlobalPriority(const int& _priority, const hyperion::Components& component);
private slots: private slots:
/// ///
/// Slot which is called when a client tries to create a new connection /// Slot which is called when a client tries to create a new connection
@ -75,15 +89,10 @@ private slots:
void processTheDatagram(const QByteArray * datagram, const QHostAddress * sender); void processTheDatagram(const QByteArray * datagram, const QHostAddress * sender);
private: private:
/// Hyperion instance
Hyperion * _hyperion;
/// The UDP server object /// The UDP server object
QUdpSocket * _server; QUdpSocket * _server;
/// List with open connections
QSet<UDPClientConnection *> _openConnections;
/// hyperion priority /// hyperion priority
int _priority; int _priority;
@ -94,7 +103,7 @@ private:
Logger * _log; Logger * _log;
/// Bonjour Service Register /// Bonjour Service Register
BonjourServiceRegister* _bonjourService = nullptr; BonjourServiceRegister* _serviceRegister = nullptr;
/// state of connection /// state of connection
bool _isActive; bool _isActive;
@ -103,7 +112,4 @@ private:
QHostAddress _listenAddress; QHostAddress _listenAddress;
uint16_t _listenPort; uint16_t _listenPort;
QAbstractSocket::BindFlag _bondage; QAbstractSocket::BindFlag _bondage;
/// Check Network Origin
NetOrigin* _netOrigin;
}; };

View File

@ -22,7 +22,8 @@ enum Components
COMP_IMAGE, COMP_IMAGE,
COMP_EFFECT, COMP_EFFECT,
COMP_PROTOSERVER, COMP_PROTOSERVER,
COMP_LEDDEVICE COMP_LEDDEVICE,
COMP_FLATBUFSERVER
}; };
inline const char* componentToString(Components c) inline const char* componentToString(Components c)
@ -42,6 +43,7 @@ inline const char* componentToString(Components c)
case COMP_IMAGE: return "Image"; case COMP_IMAGE: return "Image";
case COMP_PROTOSERVER: return "Proto Server"; case COMP_PROTOSERVER: return "Proto Server";
case COMP_LEDDEVICE: return "LED device"; case COMP_LEDDEVICE: return "LED device";
case COMP_FLATBUFSERVER: return "Image Receiver";
default: return ""; default: return "";
} }
} }
@ -63,6 +65,7 @@ inline const char* componentToIdString(Components c)
case COMP_IMAGE: return "IMAGE"; case COMP_IMAGE: return "IMAGE";
case COMP_PROTOSERVER: return "PROTOSERVER"; case COMP_PROTOSERVER: return "PROTOSERVER";
case COMP_LEDDEVICE: return "LEDDEVICE"; case COMP_LEDDEVICE: return "LEDDEVICE";
case COMP_FLATBUFSERVER: return "FLATBUFSERVER";
default: return ""; default: return "";
} }
} }
@ -83,7 +86,7 @@ inline Components stringToComponent(QString component)
if (component == "IMAGE") return COMP_IMAGE; if (component == "IMAGE") return COMP_IMAGE;
if (component == "PROTOSERVER") return COMP_PROTOSERVER; if (component == "PROTOSERVER") return COMP_PROTOSERVER;
if (component == "LEDDEVICE") return COMP_LEDDEVICE; if (component == "LEDDEVICE") return COMP_LEDDEVICE;
if (component == "FLATBUFSERVER") return COMP_FLATBUFSERVER;
return COMP_INVALID; return COMP_INVALID;
} }

34
include/utils/NetUtils.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <utils/Logger.h>
#include <QTcpServer>
namespace NetUtils {
///
/// @brief Check if the port is available for listening
/// @param[in/out] port The port to test, will be incremented if port is in use
/// @param log The logger of the caller to print
/// @return True on success else false
///
static const bool portAvailable(quint16& port, Logger* log)
{
const quint16 prevPort = port;
QTcpServer server;
bool corrected = false;
while (!server.listen(QHostAddress::Any, port))
{
corrected = true;
Warning(log,"Port '%d' is already in use, will increment", port);
port ++;
}
server.close();
if(corrected)
{
Warning(log, "The requested Port '%d' was already in use, will use Port '%d' instead", prevPort, port);
return false;
}
return true;
}
}

View File

@ -16,6 +16,14 @@ class Stats : public QObject
public: public:
Stats(); Stats();
static Stats* getInstance() { return instance; };
static Stats* instance;
void handleDataUpdate(const QJsonObject& config);
private:
friend class HyperionDaemon;
Stats(const QJsonObject& config);
~Stats(); ~Stats();
private: private:

View File

@ -29,6 +29,7 @@ enum type {
WEBSERVER, WEBSERVER,
INSTCAPTURE, INSTCAPTURE,
NETWORK, NETWORK,
FLATBUFSERVER,
INVALID INVALID
}; };
@ -62,6 +63,7 @@ inline QString typeToString(const type& type)
case WEBSERVER: return "webConfig"; case WEBSERVER: return "webConfig";
case INSTCAPTURE: return "instCapture"; case INSTCAPTURE: return "instCapture";
case NETWORK: return "network"; case NETWORK: return "network";
case FLATBUFSERVER: return "flatbufServer";
default: return "invalid"; default: return "invalid";
} }
} }
@ -94,6 +96,7 @@ inline type stringToType(const QString& type)
else if (type == "webConfig") return WEBSERVER; else if (type == "webConfig") return WEBSERVER;
else if (type == "instCapture") return INSTCAPTURE; else if (type == "instCapture") return INSTCAPTURE;
else if (type == "network") return NETWORK; else if (type == "network") return NETWORK;
else if (type == "flatbufServer") return FLATBUFSERVER;
else return INVALID; else return INVALID;
} }
}; };

View File

@ -5,13 +5,13 @@
#include <QString> #include <QString>
#include <QJsonDocument> #include <QJsonDocument>
// hyperion / utils // utils include
#include <hyperion/Hyperion.h>
#include <utils/Logger.h> #include <utils/Logger.h>
// settings // settings
#include <utils/settings.h> #include <utils/settings.h>
class BonjourServiceRegister;
class StaticFileServing; class StaticFileServing;
class QtHttpServer; class QtHttpServer;
@ -42,7 +42,6 @@ public slots:
private: private:
Logger* _log; Logger* _log;
Hyperion* _hyperion;
QString _baseUrl; QString _baseUrl;
quint16 _port; quint16 _port;
StaticFileServing* _staticFileServing; StaticFileServing* _staticFileServing;
@ -50,6 +49,8 @@ private:
const QString WEBSERVER_DEFAULT_PATH = ":/webconfig"; const QString WEBSERVER_DEFAULT_PATH = ":/webconfig";
const quint16 WEBSERVER_DEFAULT_PORT = 8090; const quint16 WEBSERVER_DEFAULT_PORT = 8090;
BonjourServiceRegister * _serviceRegister = nullptr;
}; };
#endif // WEBSERVER_H #endif // WEBSERVER_H

View File

@ -8,6 +8,7 @@ add_subdirectory(commandline)
add_subdirectory(blackborder) add_subdirectory(blackborder)
add_subdirectory(jsonserver) add_subdirectory(jsonserver)
add_subdirectory(protoserver) add_subdirectory(protoserver)
add_subdirectory(flatbufserver)
add_subdirectory(bonjour) add_subdirectory(bonjour)
add_subdirectory(boblightserver) add_subdirectory(boblightserver)
add_subdirectory(udplistener) add_subdirectory(udplistener)

21
libsrc/api/CMakeLists.txt Normal file
View File

@ -0,0 +1,21 @@
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/api)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/api)
FILE ( GLOB_RECURSE Api_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" )
set(Api_RESOURCES ${CURRENT_SOURCE_DIR}/JSONRPC_schemas.qrc )
add_library(hyperion-api
${Api_SOURCES}
${Api_RESOURCES}
)
target_link_libraries(hyperion-api
hyperion
hyperion-utils
Qt5::Core
Qt5::Gui
Qt5::Network
)

1069
libsrc/api/JsonAPI.cpp Normal file

File diff suppressed because it is too large Load Diff

304
libsrc/api/JsonCB.cpp Normal file
View File

@ -0,0 +1,304 @@
// proj incl
#include <api/JsonCB.h>
// hyperion
#include <hyperion/Hyperion.h>
// components
#include <hyperion/ComponentRegister.h>
// bonjour wrapper
#include <bonjour/bonjourbrowserwrapper.h>
// priorityMuxer
#include <hyperion/PriorityMuxer.h>
#include <utils/ColorSys.h>
#include <QDateTime>
// Image to led map helper
#include <hyperion/ImageProcessor.h>
using namespace hyperion;
JsonCB::JsonCB(QObject* parent)
: QObject(parent)
, _hyperion(Hyperion::getInstance())
, _componentRegister(& _hyperion->getComponentRegister())
, _bonjour(BonjourBrowserWrapper::getInstance())
, _prioMuxer(_hyperion->getMuxerInstance())
{
_availableCommands << "components-update" << "sessions-update" << "priorities-update" << "imageToLedMapping-update"
<< "adjustment-update" << "videomode-update" << "effects-update" << "settings-update";
}
bool JsonCB::subscribeFor(const QString& type)
{
if(!_availableCommands.contains(type))
return false;
if(type == "components-update")
{
_subscribedCommands << type;
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCB::handleComponentState, Qt::UniqueConnection);
}
if(type == "sessions-update")
{
_subscribedCommands << type;
connect(_bonjour, &BonjourBrowserWrapper::browserChange, this, &JsonCB::handleBonjourChange, Qt::UniqueConnection);
}
if(type == "priorities-update")
{
_subscribedCommands << type;
connect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCB::handlePriorityUpdate, Qt::UniqueConnection);
connect(_prioMuxer, &PriorityMuxer::autoSelectChanged, this, &JsonCB::handlePriorityUpdate, Qt::UniqueConnection);
}
if(type == "imageToLedMapping-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCB::handleImageToLedsMappingChange, Qt::UniqueConnection);
}
if(type == "adjustment-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCB::handleAdjustmentChange, Qt::UniqueConnection);
}
if(type == "videomode-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::newVideoMode, this, &JsonCB::handleVideoModeChange, Qt::UniqueConnection);
}
if(type == "effects-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCB::handleEffectListChange, Qt::UniqueConnection);
}
if(type == "settings-update")
{
_subscribedCommands << type;
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleSettingsChange, Qt::UniqueConnection);
}
return true;
}
void JsonCB::doCallback(const QString& cmd, const QVariant& data)
{
QJsonObject obj;
obj["command"] = cmd;
if(static_cast<QMetaType::Type>(data.type()) == QMetaType::QJsonArray)
obj["data"] = data.toJsonArray();
else
obj["data"] = data.toJsonObject();
emit newCallback(obj);
}
void JsonCB::handleComponentState(const hyperion::Components comp, const bool state)
{
QJsonObject data;
data["name"] = componentToIdString(comp);
data["enabled"] = state;
doCallback("components-update", QVariant(data));
}
void JsonCB::handleBonjourChange(const QMap<QString,BonjourRecord>& bRegisters)
{
QJsonArray data;
for (const auto & session: bRegisters)
{
if (session.port<0) continue;
QJsonObject item;
item["name"] = session.serviceName;
item["type"] = session.registeredType;
item["domain"] = session.replyDomain;
item["host"] = session.hostName;
item["address"]= session.address;
item["port"] = session.port;
data.append(item);
}
doCallback("sessions-update", QVariant(data));
}
void JsonCB::handlePriorityUpdate()
{
QJsonObject data;
QJsonArray priorities;
uint64_t now = QDateTime::currentMSecsSinceEpoch();
QList<int> activePriorities = _prioMuxer->getPriorities();
activePriorities.removeAll(255);
int currentPriority = _prioMuxer->getCurrentPriority();
foreach (int priority, activePriorities) {
const Hyperion::InputInfo priorityInfo = _prioMuxer->getInputInfo(priority);
QJsonObject item;
item["priority"] = priority;
if (int(priorityInfo.timeoutTime_ms - now) > -1 )
{
item["duration_ms"] = int(priorityInfo.timeoutTime_ms - now);
}
// owner has optional informations to the component
if(!priorityInfo.owner.isEmpty())
item["owner"] = priorityInfo.owner;
item["componentId"] = QString(hyperion::componentToIdString(priorityInfo.componentId));
item["origin"] = priorityInfo.origin;
item["active"] = (priorityInfo.timeoutTime_ms >= -1);
item["visible"] = (priority == currentPriority);
if(priorityInfo.componentId == hyperion::COMP_COLOR && !priorityInfo.ledColors.empty())
{
QJsonObject LEDcolor;
// add RGB Value to Array
QJsonArray RGBValue;
RGBValue.append(priorityInfo.ledColors.begin()->red);
RGBValue.append(priorityInfo.ledColors.begin()->green);
RGBValue.append(priorityInfo.ledColors.begin()->blue);
LEDcolor.insert("RGB", RGBValue);
uint16_t Hue;
float Saturation, Luminace;
// add HSL Value to Array
QJsonArray HSLValue;
ColorSys::rgb2hsl(priorityInfo.ledColors.begin()->red,
priorityInfo.ledColors.begin()->green,
priorityInfo.ledColors.begin()->blue,
Hue, Saturation, Luminace);
HSLValue.append(Hue);
HSLValue.append(Saturation);
HSLValue.append(Luminace);
LEDcolor.insert("HSL", HSLValue);
item["value"] = LEDcolor;
}
priorities.append(item);
}
data["priorities"] = priorities;
data["priorities_autoselect"] = _hyperion->sourceAutoSelectEnabled();
doCallback("priorities-update", QVariant(data));
}
void JsonCB::handleImageToLedsMappingChange(const int& mappingType)
{
QJsonObject data;
data["imageToLedMappingType"] = ImageProcessor::mappingTypeToStr(mappingType);
doCallback("imageToLedMapping-update", QVariant(data));
}
void JsonCB::handleAdjustmentChange()
{
QJsonArray adjustmentArray;
for (const QString& adjustmentId : _hyperion->getAdjustmentIds())
{
const ColorAdjustment * colorAdjustment = _hyperion->getAdjustment(adjustmentId);
if (colorAdjustment == nullptr)
{
continue;
}
QJsonObject adjustment;
adjustment["id"] = adjustmentId;
QJsonArray whiteAdjust;
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentR());
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentG());
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentB());
adjustment.insert("white", whiteAdjust);
QJsonArray redAdjust;
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentR());
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentG());
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentB());
adjustment.insert("red", redAdjust);
QJsonArray greenAdjust;
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentR());
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentG());
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentB());
adjustment.insert("green", greenAdjust);
QJsonArray blueAdjust;
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentR());
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentG());
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentB());
adjustment.insert("blue", blueAdjust);
QJsonArray cyanAdjust;
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentR());
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentG());
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentB());
adjustment.insert("cyan", cyanAdjust);
QJsonArray magentaAdjust;
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentR());
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentG());
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentB());
adjustment.insert("magenta", magentaAdjust);
QJsonArray yellowAdjust;
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentR());
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentG());
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentB());
adjustment.insert("yellow", yellowAdjust);
adjustment["backlightThreshold"] = colorAdjustment->_rgbTransform.getBacklightThreshold();
adjustment["backlightColored"] = colorAdjustment->_rgbTransform.getBacklightColored();
adjustment["brightness"] = colorAdjustment->_rgbTransform.getBrightness();
adjustment["brightnessCompensation"] = colorAdjustment->_rgbTransform.getBrightnessCompensation();
adjustment["gammaRed"] = colorAdjustment->_rgbTransform.getGammaR();
adjustment["gammaGreen"] = colorAdjustment->_rgbTransform.getGammaG();
adjustment["gammaBlue"] = colorAdjustment->_rgbTransform.getGammaB();
adjustmentArray.append(adjustment);
}
doCallback("adjustment-update", QVariant(adjustmentArray));
}
void JsonCB::handleVideoModeChange(const VideoMode& mode)
{
QJsonObject data;
data["videomode"] = QString(videoMode2String(mode));
doCallback("videomode-update", QVariant(data));
}
void JsonCB::handleEffectListChange()
{
QJsonArray effectList;
QJsonObject effects;
const std::list<EffectDefinition> & effectsDefinitions = _hyperion->getEffects();
for (const EffectDefinition & effectDefinition : effectsDefinitions)
{
QJsonObject effect;
effect["name"] = effectDefinition.name;
effect["file"] = effectDefinition.file;
effect["script"] = effectDefinition.script;
effect["args"] = effectDefinition.args;
effectList.append(effect);
};
effects["effects"] = effectList;
doCallback("effects-update", QVariant(effects));
}
void JsonCB::handleSettingsChange(const settings::type& type, const QJsonDocument& data)
{
QJsonObject dat;
if(data.isObject())
dat[typeToString(type)] = data.object();
else
dat[typeToString(type)] = data.array();
doCallback("settings-update", QVariant(dat));
}

View File

@ -50,12 +50,16 @@ void BlackBorderProcessor::handleSettingsUpdate(const settings::type& type, cons
_maxInconsistentCnt = obj["maxInconsistentCnt"].toInt(10); _maxInconsistentCnt = obj["maxInconsistentCnt"].toInt(10);
_blurRemoveCnt = obj["blurRemoveCnt"].toInt(1); _blurRemoveCnt = obj["blurRemoveCnt"].toInt(1);
_detectionMode = obj["mode"].toString("default"); _detectionMode = obj["mode"].toString("default");
const double newThreshold = obj["threshold"].toDouble(5.0)/100.0;
if(_oldThreshold != obj["threshold"].toDouble(5.0/100)) if(_oldThreshold != newThreshold)
{ {
_oldThreshold = obj["threshold"].toDouble(5.0/100); _oldThreshold = newThreshold;
if(_detector != nullptr) delete _detector;
_detector = new BlackBorderDetector(obj["threshold"].toDouble(5.0/100)); if(_detector != nullptr)
delete _detector;
_detector = new BlackBorderDetector(newThreshold);
} }
Debug(Logger::getInstance("BLACKBORDER"), "Set mode to: %s", QSTRING_CSTR(_detectionMode)); Debug(Logger::getInstance("BLACKBORDER"), "Set mode to: %s", QSTRING_CSTR(_detectionMode));

View File

@ -15,23 +15,22 @@
#include <QHostInfo> #include <QHostInfo>
// hyperion util includes // hyperion util includes
//#include "hyperion/ImageProcessorFactory.h" #include <hyperion/ImageProcessor.h>
//#include "hyperion/ImageProcessor.h"
#include "utils/ColorRgb.h"
#include "HyperionConfig.h" #include "HyperionConfig.h"
#include <hyperion/Hyperion.h>
// project includes // project includes
#include "BoblightClientConnection.h" #include "BoblightClientConnection.h"
BoblightClientConnection::BoblightClientConnection(QTcpSocket *socket, const int priority) BoblightClientConnection::BoblightClientConnection(Hyperion* hyperion, QTcpSocket *socket, const int priority)
: QObject() : QObject()
, _locale(QLocale::C) , _locale(QLocale::C)
, _socket(socket) , _socket(socket)
//, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()) , _imageProcessor(hyperion->getImageProcessor())
, _hyperion(Hyperion::getInstance()) , _hyperion(hyperion)
, _receiveBuffer() , _receiveBuffer()
, _priority(priority) , _priority(priority)
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK) , _ledColors(hyperion->getLedCount(), ColorRgb::BLACK)
, _log(Logger::getInstance("BOBLIGHT")) , _log(Logger::getInstance("BOBLIGHT"))
, _clientAddress(QHostInfo::fromName(socket->peerAddress().toString()).hostName()) , _clientAddress(QHostInfo::fromName(socket->peerAddress().toString()).hostName())
{ {
@ -227,11 +226,11 @@ void BoblightClientConnection::sendLightMessage()
int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount()); int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount());
sendMessage(QByteArray(buffer, n)); sendMessage(QByteArray(buffer, n));
//double h0, h1, v0, v1; double h0, h1, v0, v1;
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i) for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
{ {
//_imageProcessor->getScanParameters(i, h0, h1, v0, v1); _imageProcessor->getScanParameters(i, h0, h1, v0, v1);
//n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1); n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
//sendMessage(QByteArray(buffer, n)); sendMessage(QByteArray(buffer, n));
} }
} }

View File

@ -5,9 +5,12 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QLocale> #include <QLocale>
// Hyperion includes // utils includes
#include <hyperion/Hyperion.h>
#include <utils/Logger.h> #include <utils/Logger.h>
#include <utils/ColorRgb.h>
class ImageProcessor;
class Hyperion;
/// ///
/// The Connection object created by \a BoblightServer when a new connection is establshed /// The Connection object created by \a BoblightServer when a new connection is establshed
@ -22,7 +25,7 @@ public:
/// @param socket The Socket object for this connection /// @param socket The Socket object for this connection
/// @param hyperion The Hyperion server /// @param hyperion The Hyperion server
/// ///
BoblightClientConnection(QTcpSocket * socket, const int priority); BoblightClientConnection(Hyperion* hyperion, QTcpSocket * socket, const int priority);
/// ///
/// Destructor /// Destructor
@ -74,6 +77,9 @@ private:
/// The TCP-Socket that is connected tot the boblight-client /// The TCP-Socket that is connected tot the boblight-client
QTcpSocket * _socket; QTcpSocket * _socket;
/// The processor for translating images to led-values
ImageProcessor * _imageProcessor;
/// Link to Hyperion for writing led-values to a priority channel /// Link to Hyperion for writing led-values to a priority channel
Hyperion * _hyperion; Hyperion * _hyperion;

View File

@ -12,9 +12,9 @@
using namespace hyperion; using namespace hyperion;
BoblightServer::BoblightServer(const QJsonDocument& config) BoblightServer::BoblightServer(Hyperion* hyperion,const QJsonDocument& config)
: QObject() : QObject()
, _hyperion(Hyperion::getInstance()) , _hyperion(hyperion)
, _server(new QTcpServer(this)) , _server(new QTcpServer(this))
, _openConnections() , _openConnections()
, _priority(0) , _priority(0)
@ -96,7 +96,7 @@ void BoblightServer::newConnection()
{ {
Info(_log, "new connection"); Info(_log, "new connection");
_hyperion->registerInput(_priority, hyperion::COMP_BOBLIGHTSERVER, QString("Boblight@%1").arg(socket->peerAddress().toString())); _hyperion->registerInput(_priority, hyperion::COMP_BOBLIGHTSERVER, QString("Boblight@%1").arg(socket->peerAddress().toString()));
BoblightClientConnection * connection = new BoblightClientConnection(socket, _priority); BoblightClientConnection * connection = new BoblightClientConnection(_hyperion, socket, _priority);
_openConnections.insert(connection); _openConnections.insert(connection);
// register slot for cleaning up after the connection closed // register slot for cleaning up after the connection closed

View File

@ -34,8 +34,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <utils/Logger.h> #include <utils/Logger.h>
#include <HyperionConfig.h> #include <HyperionConfig.h>
#include <hyperion/Hyperion.h> #include <utils/Stats.h>
BonjourServiceRegister::BonjourServiceRegister(QObject *parent) BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0) : QObject(parent), dnssref(0), bonjourSocket(0)
@ -54,10 +53,11 @@ BonjourServiceRegister::~BonjourServiceRegister()
void BonjourServiceRegister::registerService(const QString& service, const int& port) void BonjourServiceRegister::registerService(const QString& service, const int& port)
{ {
_port = port;
// zeroconf $configname@$hostname:port // zeroconf $configname@$hostname:port
QString prettyName = Hyperion::getInstance()->getQJsonConfig()["general"].toObject()["name"].toString(); // TODO add name of the main instance
registerService( registerService(
BonjourRecord(prettyName+"@"+QHostInfo::localHostName()+ ":" + QString::number(port), BonjourRecord(QHostInfo::localHostName()+ ":" + QString::number(port),
service, service,
QString() QString()
), ),

View File

@ -1,4 +1,4 @@
find_package(PythonLibs 3.4 REQUIRED) find_package(PythonLibs 3.5 REQUIRED)
# Include the python directory. Also include the parent (which is for example /usr/include) # Include the python directory. Also include the parent (which is for example /usr/include)
# which may be required when it is not includes by the (cross-) compiler by default. # which may be required when it is not includes by the (cross-) compiler by default.

View File

@ -81,7 +81,7 @@ void Effect::run()
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _hyperion->getLedCount())); PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _hyperion->getLedCount()));
// add minimumWriteTime variable to the interpreter // add minimumWriteTime variable to the interpreter
PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", Hyperion::getInstance()->getLatchTime())); PyObject_SetAttrString(module, "latchTime", Py_BuildValue("i", _hyperion->getLatchTime()));
// add a args variable to the interpreter // add a args variable to the interpreter
PyObject_SetAttrString(module, "args", EffectModule::json2python(_args)); PyObject_SetAttrString(module, "args", EffectModule::json2python(_args));

View File

@ -29,7 +29,6 @@ FlatBufferClient::FlatBufferClient(QTcpSocket* socket, const int &timeout, QObje
void FlatBufferClient::readyRead() void FlatBufferClient::readyRead()
{ {
qDebug()<<"readyRead";
_timeoutTimer->start(); _timeoutTimer->start();
_receiveBuffer += _socket->readAll(); _receiveBuffer += _socket->readAll();
@ -37,7 +36,6 @@ void FlatBufferClient::readyRead()
// check if we can read a header // check if we can read a header
while(_receiveBuffer.size() >= 4) while(_receiveBuffer.size() >= 4)
{ {
uint32_t messageSize = uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) | ((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) | ((_receiveBuffer[1]<<16) & 0x00FF0000) |
@ -47,10 +45,11 @@ void FlatBufferClient::readyRead()
// check if we can read a complete message // check if we can read a complete message
if((uint32_t) _receiveBuffer.size() < messageSize + 4) return; if((uint32_t) _receiveBuffer.size() < messageSize + 4) return;
// remove header + msg from buffer // extract message only and remove header + msg from buffer :: QByteArray::remove() does not return the removed data
const QByteArray& msg = _receiveBuffer.remove(0, messageSize + 4); const QByteArray msg = _receiveBuffer.right(messageSize);
_receiveBuffer.remove(0, messageSize + 4);
const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.mid(3, messageSize).constData()); const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.constData());
flatbuffers::Verifier verifier(msgData, messageSize); flatbuffers::Verifier verifier(msgData, messageSize);
if (flatbuf::VerifyHyperionRequestBuffer(verifier)) if (flatbuf::VerifyHyperionRequestBuffer(verifier))
@ -59,7 +58,6 @@ void FlatBufferClient::readyRead()
handleMessage(message); handleMessage(message);
continue; continue;
} }
qDebug()<<"Unable to pasrse msg";
sendErrorReply("Unable to parse message"); sendErrorReply("Unable to parse message");
} }
//emit newMessage(msgData,messageSize); //emit newMessage(msgData,messageSize);

View File

@ -7,16 +7,15 @@
// protoserver includes // protoserver includes
#include <flatbufserver/FlatBufferConnection.h> #include <flatbufserver/FlatBufferConnection.h>
FlatBufferConnection::FlatBufferConnection(const QString & address) : FlatBufferConnection::FlatBufferConnection(const QString & address)
_socket(), : _socket()
_skipReply(false), , _prevSocketState(QAbstractSocket::UnconnectedState)
_prevSocketState(QAbstractSocket::UnconnectedState), , _log(Logger::getInstance("FLATBUFCONNECTION"))
_log(Logger::getInstance("FLATBUFCONNECTION")) {
{
QStringList parts = address.split(":"); QStringList parts = address.split(":");
if (parts.size() != 2) if (parts.size() != 2)
{ {
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString()); throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse address (%1)").arg(address).toStdString());
} }
_host = parts[0]; _host = parts[0];
@ -24,19 +23,17 @@ FlatBufferConnection::FlatBufferConnection(const QString & address) :
_port = parts[1].toUShort(&ok); _port = parts[1].toUShort(&ok);
if (!ok) if (!ok)
{ {
throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString()); throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse the port (%1)").arg(parts[1]).toStdString());
} }
// try to connect to host // init connect
Info(_log, "Connecting to Hyperion: %s:%d", _host.toStdString().c_str(), _port); Info(_log, "Connecting to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
connectToHost(); connectToHost();
// start the connection timer // start the connection timer
_timer.setInterval(5000); _timer.setInterval(5000);
_timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost())); connect(&_timer, &QTimer::timeout, this, &FlatBufferConnection::connectToHost);
connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData()));
_timer.start(); _timer.start();
} }
@ -48,48 +45,43 @@ FlatBufferConnection::~FlatBufferConnection()
void FlatBufferConnection::readData() void FlatBufferConnection::readData()
{ {
qint64 bytesAvail; _receiveBuffer += _socket.readAll();
while((bytesAvail = _socket.bytesAvailable()))
// check if we can read a header
while(_receiveBuffer.size() >= 4)
{ {
// ignore until we get 4 bytes. uint32_t messageSize =
if (bytesAvail < 4) { ((_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;
// extract message only and remove header + msg from buffer :: QByteArray::remove() does not return the removed data
const QByteArray msg = _receiveBuffer.right(messageSize);
_receiveBuffer.remove(0, messageSize + 4);
const uint8_t* msgData = reinterpret_cast<const uint8_t*>(msg.constData());
flatbuffers::Verifier verifier(msgData, messageSize);
if (flatbuf::VerifyHyperionReplyBuffer(verifier))
{
auto message = flatbuf::GetHyperionReply(msgData);
parseReply(message);
continue; continue;
} }
Error(_log, "Unable to parse reply");
char sizeBuf[4];
_socket.read(sizeBuf, sizeof(sizeBuf));
uint32_t messageSize =
((sizeBuf[0]<<24) & 0xFF000000) |
((sizeBuf[1]<<16) & 0x00FF0000) |
((sizeBuf[2]<< 8) & 0x0000FF00) |
((sizeBuf[3] ) & 0x000000FF);
QByteArray buffer;
while((uint32_t)buffer.size() < messageSize)
{
_socket.waitForReadyRead();
buffer.append(_socket.read(messageSize - buffer.size()));
}
const uint8_t* replyData = reinterpret_cast<const uint8_t*>(buffer.constData());
flatbuffers::Verifier verifier(replyData, messageSize);
if (!flatbuf::VerifyHyperionReplyBuffer(verifier))
{
Error(_log, "Error while reading data from host");
return;
}
auto reply = flatbuf::GetHyperionReply(replyData);
parseReply(reply);
} }
} }
void FlatBufferConnection::setSkipReply(bool skip) void FlatBufferConnection::setSkipReply(const bool& skip)
{ {
_skipReply = skip; if(skip)
disconnect(&_socket, &QTcpSocket::readyRead, 0, 0);
else
connect(&_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection);
} }
void FlatBufferConnection::setColor(const ColorRgb & color, int priority, int duration) void FlatBufferConnection::setColor(const ColorRgb & color, int priority, int duration)
@ -191,24 +183,22 @@ bool FlatBufferConnection::parseReply(const flatbuf::HyperionReply *reply)
{ {
case flatbuf::Type_REPLY: case flatbuf::Type_REPLY:
{ {
if (!_skipReply) if (!reply->success())
{ {
if (!reply->success()) if (flatbuffers::IsFieldPresent(reply, flatbuf::HyperionReply::VT_ERROR))
{ {
if (flatbuffers::IsFieldPresent(reply, flatbuf::HyperionReply::VT_ERROR)) throw std::runtime_error("PROTOCONNECTION ERROR: " + reply->error()->str());
{
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply->error()->str());
}
else
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
} }
else else
{ {
success = true; throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
} }
} }
else
{
success = true;
}
break; break;
} }
case flatbuf::Type_VIDEO: case flatbuf::Type_VIDEO:

View File

@ -6,10 +6,6 @@
#include <QTcpServer> #include <QTcpServer>
#include <QTcpSocket> #include <QTcpSocket>
#include <QDebug>
FlatBufferServer::FlatBufferServer(const QJsonDocument& config, QObject* parent) FlatBufferServer::FlatBufferServer(const QJsonDocument& config, QObject* parent)
: QObject(parent) : QObject(parent)
, _server(new QTcpServer(this)) , _server(new QTcpServer(this))
@ -28,7 +24,6 @@ FlatBufferServer::~FlatBufferServer()
void FlatBufferServer::initServer() void FlatBufferServer::initServer()
{ {
qDebug()<<"Thread in InitServer is"<<this->thread();
connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection); connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection);
// apply config // apply config
@ -37,7 +32,6 @@ void FlatBufferServer::initServer()
void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{ {
qDebug()<<"Thread in handleSettingsUpdate is"<<this->thread();
if(type == settings::FLATBUFSERVER) if(type == settings::FLATBUFSERVER)
{ {
const QJsonObject& obj = config.object(); const QJsonObject& obj = config.object();
@ -60,7 +54,6 @@ void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJ
void FlatBufferServer::newConnection() void FlatBufferServer::newConnection()
{ {
qDebug()<<"Thread in newConnection is"<<this->thread();
while(_server->hasPendingConnections()) while(_server->hasPendingConnections())
{ {
if(QTcpSocket* socket = _server->nextPendingConnection()) if(QTcpSocket* socket = _server->nextPendingConnection())

View File

@ -30,12 +30,19 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
int result = vc_dispmanx_display_get_info(_vc_display, &vc_info); int result = vc_dispmanx_display_get_info(_vc_display, &vc_info);
// Keep compiler happy in 'release' mode // Keep compiler happy in 'release' mode
(void)result; (void)result;
assert(result == 0);
Info(_log, "Display opened with resolution: %dx%d", vc_info.width, vc_info.height);
// Close the displaye // Close the display
vc_dispmanx_display_close(_vc_display); vc_dispmanx_display_close(_vc_display);
if(result != 0)
{
Error(_log, "Failed to open display! Probably no permissions to access the capture interface");
setEnabled(false);
return;
}
else
Info(_log, "Display opened with resolution: %dx%d", vc_info.width, vc_info.height);
// init the resource and capture rectangle // init the resource and capture rectangle
setWidthHeight(width, height); setWidthHeight(width, height);
} }
@ -55,11 +62,12 @@ void DispmanxFrameGrabber::freeResources()
vc_dispmanx_resource_delete(_vc_resource); vc_dispmanx_resource_delete(_vc_resource);
} }
void DispmanxFrameGrabber::setWidthHeight(int width, int height) bool DispmanxFrameGrabber::setWidthHeight(int width, int height)
{ {
if(_width != width || _height != height) if(Grabber::setWidthHeight(width, height))
{ {
freeResources(); if(_vc_resource != 0)
vc_dispmanx_resource_delete(_vc_resource);
// Create the resources for capturing image // Create the resources for capturing image
uint32_t vc_nativeImageHandle; uint32_t vc_nativeImageHandle;
_vc_resource = vc_dispmanx_resource_create( _vc_resource = vc_dispmanx_resource_create(
@ -71,7 +79,9 @@ void DispmanxFrameGrabber::setWidthHeight(int width, int height)
// Define the capture rectangle with the same size // Define the capture rectangle with the same size
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height); vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
return true;
} }
return false;
} }
void DispmanxFrameGrabber::setFlags(const int vc_flags) void DispmanxFrameGrabber::setFlags(const int vc_flags)

View File

@ -4,7 +4,7 @@ DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHe
: GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz) : GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz)
, _grabber(grabWidth, grabHeight) , _grabber(grabWidth, grabHeight)
{ {
setImageProcessorEnabled(false);
} }
void DispmanxWrapper::action() void DispmanxWrapper::action()

View File

@ -82,7 +82,14 @@ void OsxFrameGrabber::setDisplayIndex(int index)
} }
image = CGDisplayCreateImage(_display); image = CGDisplayCreateImage(_display);
assert(image != NULL); if(image == NULL)
{
Error(_log, "Failed to open main display, disable capture interface");
setEnabled(false);
return;
}
else
setEnabled(true);
Info(_log, "Display opened with resolution: %dx%d@%dbit", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image)); Info(_log, "Display opened with resolution: %dx%d@%dbit", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image));

View File

@ -18,29 +18,29 @@
#include <QDirIterator> #include <QDirIterator>
#include <QFileInfo> #include <QFileInfo>
#include <QTimer>
#include "grabber/V4L2Grabber.h" #include "grabber/V4L2Grabber.h"
#define CLEAR(x) memset(&(x), 0, sizeof(x)) #define CLEAR(x) memset(&(x), 0, sizeof(x))
V4L2Grabber::V4L2Grabber(const QString & device V4L2Grabber::V4L2Grabber(const QString & device
, int input
, VideoStandard videoStandard , VideoStandard videoStandard
, PixelFormat pixelFormat , PixelFormat pixelFormat
, int pixelDecimation , int pixelDecimation
) )
: Grabber("V4L2:"+device) : Grabber("V4L2:"+device)
, _deviceName(device) , _deviceName()
, _input(input) , _input(-1)
, _videoStandard(videoStandard) , _videoStandard(videoStandard)
, _ioMethod(IO_METHOD_MMAP) , _ioMethod(IO_METHOD_MMAP)
, _fileDescriptor(-1) , _fileDescriptor(-1)
, _buffers() , _buffers()
, _pixelFormat(pixelFormat) , _pixelFormat(pixelFormat)
, _pixelDecimation(pixelDecimation) , _pixelDecimation(-1)
, _lineLength(-1) , _lineLength(-1)
, _frameByteSize(-1) , _frameByteSize(-1)
, _noSignalCounterThreshold(50) , _noSignalCounterThreshold(40)
, _noSignalThresholdColor(ColorRgb{0,0,0}) , _noSignalThresholdColor(ColorRgb{0,0,0})
, _signalDetectionEnabled(true) , _signalDetectionEnabled(true)
, _noSignalDetected(false) , _noSignalDetected(false)
@ -52,12 +52,17 @@ V4L2Grabber::V4L2Grabber(const QString & device
, _streamNotifier(nullptr) , _streamNotifier(nullptr)
, _initialized(false) , _initialized(false)
, _deviceAutoDiscoverEnabled(false) , _deviceAutoDiscoverEnabled(false)
, _readFrameAdaptTimer(new QTimer(this))
{ {
//_imageResampler.setHorizontalPixelDecimation(pixelDecimation); // setup stream notify locker with 10hz
//_imageResampler.setVerticalPixelDecimation(pixelDecimation); connect(_readFrameAdaptTimer, &QTimer::timeout, this, &V4L2Grabber::unlockReadFrame);
_readFrameAdaptTimer->setInterval(100);
setPixelDecimation(pixelDecimation);
getV4Ldevices(); getV4Ldevices();
// init
setDeviceVideoStandard(device, videoStandard);
} }
V4L2Grabber::~V4L2Grabber() V4L2Grabber::~V4L2Grabber()
@ -67,10 +72,12 @@ V4L2Grabber::~V4L2Grabber()
void V4L2Grabber::uninit() void V4L2Grabber::uninit()
{ {
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
// stop if the grabber was not stopped // stop if the grabber was not stopped
if (_initialized) if (_initialized)
{ {
Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName));
_readFrameAdaptTimer->stop();
stop(); stop();
uninit_device(); uninit_device();
close_device(); close_device();
@ -78,7 +85,6 @@ void V4L2Grabber::uninit()
} }
} }
bool V4L2Grabber::init() bool V4L2Grabber::init()
{ {
if (! _initialized) if (! _initialized)
@ -133,10 +139,15 @@ bool V4L2Grabber::init()
bool opened = false; bool opened = false;
try try
{ {
open_device(); // do not init with unknown device
opened = true; if(_deviceName != "unknown")
init_device(_videoStandard, _input); {
_initialized = true; open_device();
opened = true;
init_device(_videoStandard, _input);
_initialized = true;
_readFrameAdaptTimer->start();
}
} }
catch(std::exception& e) catch(std::exception& e)
{ {
@ -529,13 +540,13 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
break; break;
} }
// TODO Does never accept own sizes? use always _imageResampler instead
/*
// calc the size based on pixelDecimation // calc the size based on pixelDecimation
fmt.fmt.pix.width = fmt.fmt.pix.width / _pixelDecimation; fmt.fmt.pix.width = fmt.fmt.pix.width / _pixelDecimation;
fmt.fmt.pix.height = fmt.fmt.pix.height / _pixelDecimation; fmt.fmt.pix.height = fmt.fmt.pix.height / _pixelDecimation;
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// set the settings // set the settings
if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
{ {
@ -550,6 +561,9 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
throw_errno_exception("VIDIOC_G_FMT"); throw_errno_exception("VIDIOC_G_FMT");
return; return;
} }
*/
// set the line length
_lineLength = fmt.fmt.pix.bytesperline;
// store width & height // store width & height
_width = fmt.fmt.pix.width; _width = fmt.fmt.pix.width;
@ -701,6 +715,10 @@ void V4L2Grabber::stop_capturing()
int V4L2Grabber::read_frame() int V4L2Grabber::read_frame()
{ {
// read_frame() is called with 25Hz, adapt to 10Hz. In the end it's up to the stream notifier if we get calls or not
if(!_readFrame) return -1;
_readFrame = false;
bool rc = false; bool rc = false;
try try
@ -933,18 +951,30 @@ void V4L2Grabber::setPixelDecimation(int pixelDecimation)
{ {
if(_pixelDecimation != pixelDecimation) if(_pixelDecimation != pixelDecimation)
{ {
_pixelDecimation = pixelDecimation;
uninit(); uninit();
init(); // start if init is a success
if(init())
start();
_imageResampler.setHorizontalPixelDecimation(pixelDecimation);
_imageResampler.setVerticalPixelDecimation(pixelDecimation);
} }
} }
void V4L2Grabber::setInputVideoStandard(int input, VideoStandard videoStandard) void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStandard)
{ {
if(_input != input || _videoStandard != videoStandard) if(_deviceName != device || _videoStandard != videoStandard)
{ {
_input = input; // extract input of device
_videoStandard = videoStandard; QChar input = device.at(device.size() - 1);
_input = input.isNumber() ? input.digitValue() : -1;
uninit(); uninit();
init(); _deviceName = device;
_videoStandard = videoStandard;
// start if init is a success
if(init())
start();
} }
} }

View File

@ -6,13 +6,11 @@
#include <QTimer> #include <QTimer>
V4L2Wrapper::V4L2Wrapper(const QString &device, V4L2Wrapper::V4L2Wrapper(const QString &device,
int input,
VideoStandard videoStandard, VideoStandard videoStandard,
PixelFormat pixelFormat, PixelFormat pixelFormat,
int pixelDecimation ) int pixelDecimation )
: GrabberWrapper("V4L2:"+device, &_grabber, 0, 0, 10) : GrabberWrapper("V4L2:"+device, &_grabber, 0, 0, 10)
, _grabber(device, , _grabber(device,
input,
videoStandard, videoStandard,
pixelFormat, pixelFormat,
pixelDecimation) pixelDecimation)
@ -66,7 +64,7 @@ void V4L2Wrapper::readError(const char* err)
void V4L2Wrapper::action() void V4L2Wrapper::action()
{ {
// dummy as v4l get notifications from stream
} }
void V4L2Wrapper::setSignalDetectionEnable(bool enable) void V4L2Wrapper::setSignalDetectionEnable(bool enable)

View File

@ -110,6 +110,7 @@ bool X11Grabber::Setup()
bool result = (updateScreenDimensions(true) >=0); bool result = (updateScreenDimensions(true) >=0);
ErrorIf(!result, _log, "X11 Grabber start failed"); ErrorIf(!result, _log, "X11 Grabber start failed");
setEnabled(result);
return result; return result;
} }
@ -278,11 +279,6 @@ void X11Grabber::setVideoMode(VideoMode mode)
updateScreenDimensions(true); updateScreenDimensions(true);
} }
void X11Grabber::setWidthHeight(int width, int height)
{
// empty overwrite
}
void X11Grabber::setPixelDecimation(int pixelDecimation) void X11Grabber::setPixelDecimation(int pixelDecimation)
{ {
if(_pixelDecimation != pixelDecimation) if(_pixelDecimation != pixelDecimation)

View File

@ -17,6 +17,7 @@ target_link_libraries(hyperion
hyperion-utils hyperion-utils
leddevice leddevice
bonjour bonjour
boblightserver
effectengine effectengine
${QT_LIBRARIES} ${QT_LIBRARIES}
) )

View File

@ -1,12 +1,14 @@
#include <hyperion/CaptureCont.h> #include <hyperion/CaptureCont.h>
#include <hyperion/Hyperion.h> #include <hyperion/Hyperion.h>
#include <QTimer>
CaptureCont::CaptureCont(Hyperion* hyperion) CaptureCont::CaptureCont(Hyperion* hyperion)
: QObject() : QObject()
, _hyperion(hyperion) , _hyperion(hyperion)
, _systemCaptEnabled(false) , _systemCaptEnabled(false)
, _v4lCaptEnabled(false) , _v4lCaptEnabled(false)
, _v4lInactiveTimer(new QTimer(this))
{ {
// settings changes // settings changes
connect(_hyperion, &Hyperion::settingsChanged, this, &CaptureCont::handleSettingsUpdate); connect(_hyperion, &Hyperion::settingsChanged, this, &CaptureCont::handleSettingsUpdate);
@ -14,6 +16,11 @@ CaptureCont::CaptureCont(Hyperion* hyperion)
// comp changes // comp changes
connect(_hyperion, &Hyperion::componentStateChanged, this, &CaptureCont::componentStateChanged); connect(_hyperion, &Hyperion::componentStateChanged, this, &CaptureCont::componentStateChanged);
// inactive timer v4l
connect(_v4lInactiveTimer, &QTimer::timeout, this, &CaptureCont::setV4lInactive);
_v4lInactiveTimer->setSingleShot(true);
_v4lInactiveTimer->setInterval(1000);
// init // init
handleSettingsUpdate(settings::INSTCAPTURE, _hyperion->getSetting(settings::INSTCAPTURE)); handleSettingsUpdate(settings::INSTCAPTURE, _hyperion->getSetting(settings::INSTCAPTURE));
} }
@ -25,6 +32,7 @@ CaptureCont::~CaptureCont()
void CaptureCont::handleV4lImage(const Image<ColorRgb> & image) void CaptureCont::handleV4lImage(const Image<ColorRgb> & image)
{ {
_v4lInactiveTimer->start();
_hyperion->setInputImage(_v4lCaptPrio, image); _hyperion->setInputImage(_v4lCaptPrio, image);
} }
@ -40,7 +48,7 @@ void CaptureCont::setSystemCaptureEnable(const bool& enable)
{ {
if(enable) if(enable)
{ {
_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER, "System", "DoNotKnow"); _hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER);
connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage); connect(_hyperion, &Hyperion::systemImage, this, &CaptureCont::handleSystemImage);
} }
else else
@ -59,13 +67,14 @@ void CaptureCont::setV4LCaptureEnable(const bool& enable)
{ {
if(enable) if(enable)
{ {
_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L, "System", "DoNotKnow"); _hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L);
connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); connect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
} }
else else
{ {
disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage); disconnect(_hyperion, &Hyperion::v4lImage, this, &CaptureCont::handleV4lImage);
_hyperion->clear(_v4lCaptPrio); _hyperion->clear(_v4lCaptPrio);
_v4lInactiveTimer->stop();
} }
_v4lCaptEnabled = enable; _v4lCaptEnabled = enable;
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_V4L, enable); _hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_V4L, enable);
@ -104,3 +113,8 @@ void CaptureCont::componentStateChanged(const hyperion::Components component, bo
setV4LCaptureEnable(enable); setV4LCaptureEnable(enable);
} }
} }
void CaptureCont::setV4lInactive()
{
_hyperion->setInputInactive(_v4lCaptPrio);
}

View File

@ -55,9 +55,9 @@ bool ComponentRegister::setHyperionEnable(const bool& state)
return false; return false;
} }
bool ComponentRegister::isComponentEnabled(const hyperion::Components& comp) const int ComponentRegister::isComponentEnabled(const hyperion::Components& comp) const
{ {
return _componentStates.at(comp); return (_componentStates.count(comp)) ? _componentStates.at(comp) : -1;
} }
void ComponentRegister::componentStateChanged(const hyperion::Components comp, const bool activated) void ComponentRegister::componentStateChanged(const hyperion::Components comp, const bool activated)

View File

@ -24,12 +24,13 @@ Grabber::~Grabber()
void Grabber::setEnabled(bool enable) void Grabber::setEnabled(bool enable)
{ {
Info(_log,"Capture interface is now %s", enable ? "enabled" : "disabled");
_enabled = enable; _enabled = enable;
} }
void Grabber::setVideoMode(VideoMode mode) void Grabber::setVideoMode(VideoMode mode)
{ {
Debug(_log,"setvideomode %d", mode); Debug(_log,"Set videomode to %d", mode);
_videoMode = mode; _videoMode = mode;
if ( _useImageResampler ) if ( _useImageResampler )
{ {
@ -68,18 +69,20 @@ void Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTo
} }
} }
void Grabber::setWidthHeight(int width, int height) bool Grabber::setWidthHeight(int width, int height)
{ {
// eval changes with crop // eval changes with crop
if (width>0 && height>0) if ( (width>0 && height>0) && (_width != width || _height != height) )
{ {
if (_cropLeft + _cropRight >= width || _cropTop + _cropBottom >= height) if (_cropLeft + _cropRight >= width || _cropTop + _cropBottom >= height)
{ {
Error(_log, "Rejecting invalid width/height values as it collides with image cropping: width: %d, height: %d", width, height); Error(_log, "Rejecting invalid width/height values as it collides with image cropping: width: %d, height: %d", width, height);
return; return false;
} }
Debug(_log, "Set new width: %d, height: %d for capture", width, height);
_width = width; _width = width;
_height = height; _height = height;
return true;
} }
return false;
} }

View File

@ -3,19 +3,14 @@
#include <hyperion/Grabber.h> #include <hyperion/Grabber.h>
#include <HyperionConfig.h> #include <HyperionConfig.h>
//forwarder
#include <hyperion/MessageForwarder.h>
// qt // qt
#include <QTimer> #include <QTimer>
GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz) GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz)
: _grabberName(grabberName) : _grabberName(grabberName)
, _hyperion(Hyperion::getInstance())
, _timer(new QTimer(this)) , _timer(new QTimer(this))
, _updateInterval_ms(1000/updateRate_Hz) , _updateInterval_ms(1000/updateRate_Hz)
, _log(Logger::getInstance(grabberName)) , _log(Logger::getInstance(grabberName))
, _forward(true)
, _ggrabber(ggrabber) , _ggrabber(ggrabber)
, _image(0,0) , _image(0,0)
{ {
@ -24,8 +19,6 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned
_image.resize(width, height); _image.resize(width, height);
_forward = _hyperion->getForwarder()->protoForwardingEnabled();
connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action); connect(_timer, &QTimer::timeout, this, &GrabberWrapper::action);
} }
@ -105,7 +98,7 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
else else
obj = config.object(); obj = config.object();
if(type == settings::SYSTEMCAPTURE) if(type == settings::SYSTEMCAPTURE && !_grabberName.startsWith("V4L"))
{ {
// width/height // width/height
_ggrabber->setWidthHeight(obj["width"].toInt(96), obj["height"].toInt(96)); _ggrabber->setWidthHeight(obj["width"].toInt(96), obj["height"].toInt(96));
@ -138,7 +131,8 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
} }
} }
if(type == settings::V4L2) // v4l instances only!
if(type == settings::V4L2 && _grabberName.startsWith("V4L"))
{ {
// pixel decimation for v4l // pixel decimation for v4l
_ggrabber->setPixelDecimation(obj["sizeDecimation"].toInt(8)); _ggrabber->setPixelDecimation(obj["sizeDecimation"].toInt(8));
@ -160,8 +154,8 @@ void GrabberWrapper::handleSettingsUpdate(const settings::type& type, const QJso
obj["redSignalThreshold"].toDouble(0.0)/100.0, obj["redSignalThreshold"].toDouble(0.0)/100.0,
obj["greenSignalThreshold"].toDouble(0.0)/100.0, obj["greenSignalThreshold"].toDouble(0.0)/100.0,
obj["blueSignalThreshold"].toDouble(0.0)/100.0); obj["blueSignalThreshold"].toDouble(0.0)/100.0);
_ggrabber->setInputVideoStandard( _ggrabber->setDeviceVideoStandard(
obj["input"].toInt(0), obj["device"].toString("auto"),
parseVideoStandard(obj["standard"].toString("no-change"))); parseVideoStandard(obj["standard"].toString("no-change")));
} }

View File

@ -47,6 +47,9 @@
// CaptureControl (Daemon capture) // CaptureControl (Daemon capture)
#include <hyperion/CaptureCont.h> #include <hyperion/CaptureCont.h>
// Boblight
#include <boblightserver/BoblightServer.h>
Hyperion* Hyperion::_hyperion = nullptr; Hyperion* Hyperion::_hyperion = nullptr;
Hyperion* Hyperion::initInstance( HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath) Hyperion* Hyperion::initInstance( HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath)
@ -122,7 +125,7 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
const QJsonObject color = getSetting(settings::COLOR).object(); const QJsonObject color = getSetting(settings::COLOR).object();
// initialize leddevices // initialize leddevices
const QJsonObject ledDevice = getSetting(settings::DEVICE).object(); QJsonObject ledDevice = getSetting(settings::DEVICE).object();
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
_device = LedDeviceFactory::construct(ledDevice); _device = LedDeviceFactory::construct(ledDevice);
@ -159,6 +162,11 @@ Hyperion::Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString
// if there is no startup / background eff and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a prioritiy change) // if there is no startup / background eff and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a prioritiy change)
update(); update();
// boblight, can't live in global scope as it depends on layout
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
} }
Hyperion::~Hyperion() Hyperion::~Hyperion()
@ -178,6 +186,7 @@ void Hyperion::freeObjects(bool emitCloseSignal)
} }
// delete components on exit of hyperion core // delete components on exit of hyperion core
delete _boblightServer;
delete _captureCont; delete _captureCont;
delete _effectEngine; delete _effectEngine;
//delete _deviceSmooth; //delete _deviceSmooth;
@ -249,7 +258,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
else if(type == settings::DEVICE) else if(type == settings::DEVICE)
{ {
_lockUpdate = true; _lockUpdate = true;
const QJsonObject dev = config.object(); QJsonObject dev = config.object();
// handle hwLedCount update // handle hwLedCount update
_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount()); _hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount());
@ -281,7 +290,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
_deviceSmooth->startTimerDelayed(); _deviceSmooth->startTimerDelayed();
_lockUpdate = false; _lockUpdate = false;
} }
// update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer // update once to push single color sets / adjustments/ ledlayout resizes and update ledBuffer color
update(); update();
} }
@ -421,6 +430,11 @@ const bool Hyperion::setInputImage(const int priority, const Image<ColorRgb>& im
return false; return false;
} }
const bool Hyperion::setInputInactive(const quint8& priority)
{
return _muxer.setInputInactive(priority);
}
void Hyperion::setColor(int priority, const ColorRgb &color, const int timeout_ms, const QString& origin, bool clearEffects) void Hyperion::setColor(int priority, const ColorRgb &color, const int timeout_ms, const QString& origin, bool clearEffects)
{ {
// clear effect if this call does not come from an effect // clear effect if this call does not come from an effect
@ -602,7 +616,7 @@ void Hyperion::update()
// disable the black border detector for effects and ledmapping to 0 // disable the black border detector for effects and ledmapping to 0
if(compChanged) if(compChanged)
{ {
_imageProcessor->setBlackbarDetectDisable((_prevCompId == hyperion::COMP_EFFECT || _prevCompId == hyperion::COMP_GRABBER)); _imageProcessor->setBlackbarDetectDisable((_prevCompId == hyperion::COMP_EFFECT));
_imageProcessor->setHardLedMappingType((_prevCompId == hyperion::COMP_EFFECT) ? 0 : -1); _imageProcessor->setHardLedMappingType((_prevCompId == hyperion::COMP_EFFECT) ? 0 : -1);
} }
_imageProcessor->process(image, _ledBuffer); _imageProcessor->process(image, _ledBuffer);

View File

@ -228,7 +228,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
} }
_currentConfigId = cfg; _currentConfigId = cfg;
//DebugIf( enabled() && !_pause, _log, "set smoothing cfg: %d, interval: %d ms, settlingTime: %d ms, updateDelay: %d frames", _currentConfigId, _updateInterval, _settlingTime, _outputDelay ); //DebugIf( enabled() && !_pause, _log, "set smoothing cfg: %d, interval: %d ms, settlingTime: %d ms, updateDelay: %d frames", _currentConfigId, _updateInterval, _settlingTime, _outputDelay );
InfoIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId ); DebugIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId );
return true; return true;
} }

View File

@ -240,6 +240,12 @@ const bool PriorityMuxer::setInputImage(const int priority, const Image<ColorRgb
return true; return true;
} }
const bool PriorityMuxer::setInputInactive(const quint8& priority)
{
Image<ColorRgb> image;
return setInputImage(priority, image, -100);
}
const bool PriorityMuxer::clearInput(const uint8_t priority) const bool PriorityMuxer::clearInput(const uint8_t priority)
{ {
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority)) if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))

View File

@ -133,8 +133,6 @@ SettingsManager::~SettingsManager()
const QJsonDocument SettingsManager::getSetting(const settings::type& type) const QJsonDocument SettingsManager::getSetting(const settings::type& type)
{ {
//return _sTable->getSettingsRecord(settings::typeToString(type));
QString key = settings::typeToString(type); QString key = settings::typeToString(type);
if(_qconfig[key].isObject()) if(_qconfig[key].isObject())
return QJsonDocument(_qconfig[key].toObject()); return QJsonDocument(_qconfig[key].toObject());
@ -168,6 +166,23 @@ const bool SettingsManager::saveSettings(QJsonObject config, const bool& correct
return false; return false;
} }
// compare old data with new data to emit/save changes accordingly
for(const auto key : config.keys())
{
QString newData, oldData;
_qconfig[key].isObject()
? oldData = QString(QJsonDocument(_qconfig[key].toObject()).toJson(QJsonDocument::Compact))
: oldData = QString(QJsonDocument(_qconfig[key].toArray()).toJson(QJsonDocument::Compact));
config[key].isObject()
? newData = QString(QJsonDocument(config[key].toObject()).toJson(QJsonDocument::Compact))
: newData = QString(QJsonDocument(config[key].toArray()).toJson(QJsonDocument::Compact));
if(oldData != newData)
emit settingsChanged(settings::stringToType(key), QJsonDocument::fromJson(newData.toLocal8Bit()));
}
// store the current state // store the current state
_qconfig = config; _qconfig = config;

View File

@ -55,6 +55,10 @@
{ {
"$ref": "schema-protoServer.json" "$ref": "schema-protoServer.json"
}, },
"flatbufServer":
{
"$ref": "schema-flatbufServer.json"
},
"boblightServer" : "boblightServer" :
{ {
"$ref": "schema-boblightServer.json" "$ref": "schema-boblightServer.json"

View File

@ -16,6 +16,7 @@
<file alias="schema-forwarder.json">schema/schema-forwarder.json</file> <file alias="schema-forwarder.json">schema/schema-forwarder.json</file>
<file alias="schema-jsonServer.json">schema/schema-jsonServer.json</file> <file alias="schema-jsonServer.json">schema/schema-jsonServer.json</file>
<file alias="schema-protoServer.json">schema/schema-protoServer.json</file> <file alias="schema-protoServer.json">schema/schema-protoServer.json</file>
<file alias="schema-flatbufServer.json">schema/schema-flatbufServer.json</file>
<file alias="schema-boblightServer.json">schema/schema-boblightServer.json</file> <file alias="schema-boblightServer.json">schema/schema-boblightServer.json</file>
<file alias="schema-udpListener.json">schema/schema-udpListener.json</file> <file alias="schema-udpListener.json">schema/schema-udpListener.json</file>
<file alias="schema-webConfig.json">schema/schema-webConfig.json</file> <file alias="schema-webConfig.json">schema/schema-webConfig.json</file>

View File

@ -2,18 +2,21 @@
"type" : "object", "type" : "object",
"title" : "edt_dev_general_heading_title", "title" : "edt_dev_general_heading_title",
"required" : true, "required" : true,
"defaultProperties": ["ledCount","colorOrder","rewriteTime","minimumWriteTime"], "defaultProperties": ["hardwareLedCount","colorOrder","rewriteTime"],
"properties" : "properties" :
{ {
"type" : "type" :
{ {
"type" : "string" "type" : "string",
"propertyOrder" : 1
}, },
"ledCount" : "hardwareLedCount" :
{ {
"type" : "integer", "type" : "integer",
"minimum" : 0, "title" : "edt_dev_general_hardwareLedCount_title",
"title" : "edt_dev_general_ledCount_title", "minimum" : 1,
"default" : 1,
"access" : "expert",
"propertyOrder" : 2 "propertyOrder" : 2
}, },
"colorOrder" : "colorOrder" :

View File

@ -3,7 +3,7 @@
"required" : true, "required" : true,
"title" : "edt_conf_v4l2_heading_title", "title" : "edt_conf_v4l2_heading_title",
"minItems": 1, "minItems": 1,
"maxItems": 2, "maxItems": 1,
"items": "items":
{ {
"type" : "object", "type" : "object",
@ -16,17 +16,9 @@
"type" : "string", "type" : "string",
"title" : "edt_conf_v4l2_device_title", "title" : "edt_conf_v4l2_device_title",
"default" : "auto", "default" : "auto",
"minLength" : 4,
"required" : true, "required" : true,
"propertyOrder" : 2 "propertyOrder" : 1
},
"input" :
{
"type" : "integer",
"title" : "edt_conf_v4l2_input_title",
"minimum" : 0,
"default" : 0,
"required" : true,
"propertyOrder" : 3
}, },
"standard" : "standard" :
{ {
@ -38,7 +30,7 @@
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"] "enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM", "edt_conf_enum_NO_CHANGE"]
}, },
"required" : true, "required" : true,
"propertyOrder" : 4 "propertyOrder" : 2
}, },
"sizeDecimation" : "sizeDecimation" :
{ {
@ -48,7 +40,7 @@
"maximum" : 30, "maximum" : 30,
"default" : 6, "default" : 6,
"required" : true, "required" : true,
"propertyOrder" : 8 "propertyOrder" : 3
}, },
"cropLeft" : "cropLeft" :
{ {
@ -58,7 +50,7 @@
"default" : 0, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"required" : true, "required" : true,
"propertyOrder" : 11 "propertyOrder" : 4
}, },
"cropRight" : "cropRight" :
{ {
@ -68,7 +60,7 @@
"default" : 0, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"required" : true, "required" : true,
"propertyOrder" : 12 "propertyOrder" : 5
}, },
"cropTop" : "cropTop" :
{ {
@ -78,7 +70,7 @@
"default" : 0, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"required" : true, "required" : true,
"propertyOrder" : 13 "propertyOrder" : 6
}, },
"cropBottom" : "cropBottom" :
{ {
@ -88,7 +80,7 @@
"default" : 0, "default" : 0,
"append" : "edt_append_pixel", "append" : "edt_append_pixel",
"required" : true, "required" : true,
"propertyOrder" : 14 "propertyOrder" : 7
}, },
"signalDetection" : "signalDetection" :
{ {
@ -96,7 +88,7 @@
"title" : "edt_conf_v4l2_signalDetection_title", "title" : "edt_conf_v4l2_signalDetection_title",
"default" : false, "default" : false,
"required" : true, "required" : true,
"propertyOrder" : 15 "propertyOrder" : 8
}, },
"redSignalThreshold" : "redSignalThreshold" :
{ {
@ -112,7 +104,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 16 "propertyOrder" : 9
}, },
"greenSignalThreshold" : "greenSignalThreshold" :
{ {
@ -128,7 +120,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 17 "propertyOrder" : 10
}, },
"blueSignalThreshold" : "blueSignalThreshold" :
{ {
@ -144,7 +136,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 18 "propertyOrder" : 11
}, },
"sDVOffsetMin" : "sDVOffsetMin" :
{ {
@ -160,7 +152,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 19 "propertyOrder" : 12
}, },
"sDVOffsetMax" : "sDVOffsetMax" :
{ {
@ -176,7 +168,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 20 "propertyOrder" : 13
}, },
"sDHOffsetMin" : "sDHOffsetMin" :
{ {
@ -192,7 +184,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 21 "propertyOrder" : 14
}, },
"sDHOffsetMax" : "sDHOffsetMax" :
{ {
@ -208,7 +200,7 @@
} }
}, },
"required" : true, "required" : true,
"propertyOrder" : 22 "propertyOrder" : 15
} }
}, },
"additionalProperties" : false "additionalProperties" : false

View File

@ -8,7 +8,7 @@
{ {
"type" : "boolean", "type" : "boolean",
"required" : true, "required" : true,
"title" : "edt_conf_instC_systemEnable", "title" : "edt_conf_instC_systemEnable_title",
"default" : true, "default" : true,
"propertyOrder" : 1 "propertyOrder" : 1
}, },
@ -26,7 +26,7 @@
{ {
"type" : "boolean", "type" : "boolean",
"required" : true, "required" : true,
"title" : "edt_conf_instC_v4lEnable", "title" : "edt_conf_instC_v4lEnable_title",
"default" : false, "default" : false,
"propertyOrder" : 3 "propertyOrder" : 3
}, },

View File

@ -3,14 +3,6 @@
"title" : "edt_conf_webc_heading_title", "title" : "edt_conf_webc_heading_title",
"properties" : "properties" :
{ {
"enable" :
{
"type" : "boolean",
"title" : "edt_conf_general_enable_title",
"default" : true,
"access" : "expert",
"propertyOrder" : 1
},
"document_root" : "document_root" :
{ {
"type" : "string", "type" : "string",

View File

@ -5,11 +5,8 @@
#include <jsonserver/JsonServer.h> #include <jsonserver/JsonServer.h>
#include "JsonClientConnection.h" #include "JsonClientConnection.h"
// hyperion include // bonjour include
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
#include <bonjour/bonjourserviceregister.h> #include <bonjour/bonjourserviceregister.h>
#include <hyperion/ComponentRegister.h>
// qt includes // qt includes
#include <QTcpServer> #include <QTcpServer>
@ -20,27 +17,16 @@
JsonServer::JsonServer(const QJsonDocument& config) JsonServer::JsonServer(const QJsonDocument& config)
: QObject() : QObject()
, _server(new QTcpServer(this)) , _server(new QTcpServer(this))
, _hyperion(Hyperion::getInstance())
, _openConnections() , _openConnections()
, _log(Logger::getInstance("JSONSERVER")) , _log(Logger::getInstance("JSONSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{ {
Debug(_log, "Created instance"); Debug(_log, "Created instance");
// Set trigger for incoming connections // Set trigger for incoming connections
connect(_server, SIGNAL(newConnection()), this, SLOT(newConnection())); connect(_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
// receive state of forwarder
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonServer::componentStateChanged);
// listen for component register changes
connect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
// init // init
handleSettingsUpdate(settings::JSONSERVER, config); handleSettingsUpdate(settings::JSONSERVER, config);
// set initial state of forwarding
componentStateChanged(hyperion::COMP_FORWARDER, _componentRegister->isComponentEnabled(hyperion::COMP_FORWARDER));
} }
JsonServer::~JsonServer() JsonServer::~JsonServer()
@ -64,7 +50,13 @@ void JsonServer::start()
if(_serviceRegister == nullptr) if(_serviceRegister == nullptr)
{ {
_serviceRegister = new BonjourServiceRegister(); _serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-json._tcp", _port);
}
else if( _serviceRegister->getPort() != _port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-json._tcp", _port); _serviceRegister->registerService("_hyperiond-json._tcp", _port);
} }
} }
@ -123,38 +115,6 @@ void JsonServer::closedConnection(void)
connection->deleteLater(); connection->deleteLater();
} }
void JsonServer::componentStateChanged(const hyperion::Components component, bool enable)
{
if (component == hyperion::COMP_FORWARDER)
{
if(enable)
{
connect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
}
else
{
disconnect(_hyperion, &Hyperion::forwardJsonMessage, this, &JsonServer::forwardJsonMessage);
}
}
}
void JsonServer::forwardJsonMessage(const QJsonObject &message)
{
QTcpSocket client;
QStringList list = _hyperion->getForwarder()->getJsonSlaves();
for (const auto& entry : list)
{
QStringList splitted = entry.split(":");
client.connectToHost(splitted[0], splitted[1].toInt());
if ( client.waitForConnected(500) )
{
sendMessage(message,&client);
client.close();
}
}
}
void JsonServer::sendMessage(const QJsonObject & message, QTcpSocket * socket) void JsonServer::sendMessage(const QJsonObject & message, QTcpSocket * socket)
{ {
// serialize message // serialize message

View File

@ -16,6 +16,9 @@
// hyperion util includes // hyperion util includes
#include "utils/ColorRgb.h" #include "utils/ColorRgb.h"
// Hyperion includes
#include <hyperion/Hyperion.h>
// project includes // project includes
#include "ProtoClientConnection.h" #include "ProtoClientConnection.h"
@ -198,7 +201,7 @@ void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &messag
int priority = message.priority(); int priority = message.priority();
// clear priority // clear priority
_hyperion->clear(priority); //_hyperion->clear(priority);
// send reply // send reply
sendSuccessReply(); sendSuccessReply();
} }
@ -206,7 +209,7 @@ void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &messag
void ProtoClientConnection::handleClearallCommand() void ProtoClientConnection::handleClearallCommand()
{ {
// clear priority // clear priority
_hyperion->clearall(); //_hyperion->clearall();
// send reply // send reply
sendSuccessReply(); sendSuccessReply();

View File

@ -9,9 +9,6 @@
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
// Hyperion includes
#include <hyperion/Hyperion.h>
//Utils includes //Utils includes
#include <utils/VideoMode.h> #include <utils/VideoMode.h>
@ -19,6 +16,8 @@
#include "message.pb.h" #include "message.pb.h"
#include "protoserver/ProtoConnection.h" #include "protoserver/ProtoConnection.h"
class Hyperion;
/// ///
/// 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
/// ///

View File

@ -3,10 +3,9 @@
// qt incl // qt incl
#include <QTcpServer> #include <QTcpServer>
#include <QJsonObject>
// project includes // project includes
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
#include <protoserver/ProtoServer.h> #include <protoserver/ProtoServer.h>
#include "protoserver/ProtoConnection.h" #include "protoserver/ProtoConnection.h"
#include "ProtoClientConnection.h" #include "ProtoClientConnection.h"
@ -15,30 +14,13 @@
ProtoServer::ProtoServer(const QJsonDocument& config) ProtoServer::ProtoServer(const QJsonDocument& config)
: QObject() : QObject()
, _hyperion(Hyperion::getInstance())
, _server(new QTcpServer(this)) , _server(new QTcpServer(this))
, _openConnections() , _openConnections()
, _log(Logger::getInstance("PROTOSERVER")) , _log(Logger::getInstance("PROTOSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{ {
Debug(_log,"Instance created"); Debug(_log,"Instance created");
connect( _server, SIGNAL(newConnection()), this, SLOT(newConnection())); connect( _server, SIGNAL(newConnection()), this, SLOT(newConnection()));
handleSettingsUpdate(settings::PROTOSERVER, config); handleSettingsUpdate(settings::PROTOSERVER, config);
QStringList slaves = _hyperion->getForwarder()->getProtoSlaves();
for (const auto& entry : slaves)
{
ProtoConnection* p = new ProtoConnection(entry.toLocal8Bit().constData());
p->setSkipReply(true);
_proxy_connections << p;
}
// listen for component changes
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &ProtoServer::componentStateChanged);
// get inital forwarder state
componentStateChanged(hyperion::COMP_FORWARDER, _componentRegister->isComponentEnabled(hyperion::COMP_FORWARDER));
} }
ProtoServer::~ProtoServer() ProtoServer::~ProtoServer()
@ -46,9 +28,6 @@ ProtoServer::~ProtoServer()
foreach (ProtoClientConnection * connection, _openConnections) { foreach (ProtoClientConnection * connection, _openConnections) {
delete connection; delete connection;
} }
while (!_proxy_connections.isEmpty())
delete _proxy_connections.takeFirst();
} }
void ProtoServer::start() void ProtoServer::start()
@ -65,7 +44,13 @@ void ProtoServer::start()
if(_serviceRegister == nullptr) if(_serviceRegister == nullptr)
{ {
_serviceRegister = new BonjourServiceRegister(); _serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port);
}
else if( _serviceRegister->getPort() != _port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port); _serviceRegister->registerService("_hyperiond-proto._tcp", _port);
} }
} }
@ -110,37 +95,11 @@ void ProtoServer::newConnection()
// register slot for cleaning up after the connection closed // register slot for cleaning up after the connection closed
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*))); connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*))); //connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
// register forward signal for video mode
connect(this, SIGNAL(videoMode(VideoMode)), connection, SLOT(setVideoMode(VideoMode)));
} }
} }
} }
void ProtoServer::newMessage(const proto::HyperionRequest * message)
{
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->sendMessage(*message);
}
void ProtoServer::sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms)
{
if ( _forwarder_enabled )
{
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->setImage(image, priority, duration_ms);
}
}
void ProtoServer::componentStateChanged(const hyperion::Components component, bool enable)
{
if (component == hyperion::COMP_FORWARDER)
{
_forwarder_enabled = enable;
}
}
void ProtoServer::closedConnection(ProtoClientConnection *connection) void ProtoServer::closedConnection(ProtoClientConnection *connection)
{ {
Debug(_log, "Connection closed"); Debug(_log, "Connection closed");

View File

@ -1,4 +1,4 @@
find_package(PythonLibs 3.4 REQUIRED) find_package(PythonLibs 3.5 REQUIRED)
# Include the python directory. Also include the parent (which is for example /usr/include) # Include the python directory. Also include the parent (which is for example /usr/include)
# which may be required when it is not includes by the (cross-) compiler by default. # which may be required when it is not includes by the (cross-) compiler by default.

View File

@ -1,24 +1,21 @@
// project includes // project includes
#include <udplistener/UDPListener.h> #include <udplistener/UDPListener.h>
// hyperion includes // bonjour includes
#include <hyperion/Hyperion.h>
#include <bonjour/bonjourserviceregister.h> #include <bonjour/bonjourserviceregister.h>
// hyperion util includes // hyperion includes
#include "utils/ColorRgb.h"
#include "HyperionConfig.h" #include "HyperionConfig.h"
// qt includes // qt includes
#include <QUdpSocket> #include <QUdpSocket>
#include <QJsonObject>
using namespace hyperion; using namespace hyperion;
UDPListener::UDPListener(const QJsonDocument& config) : UDPListener::UDPListener(const QJsonDocument& config) :
QObject(), QObject(),
_hyperion(Hyperion::getInstance()),
_server(new QUdpSocket(this)), _server(new QUdpSocket(this)),
_openConnections(),
_priority(0), _priority(0),
_timeout(0), _timeout(0),
_log(Logger::getInstance("UDPLISTENER")), _log(Logger::getInstance("UDPLISTENER")),
@ -26,10 +23,6 @@ UDPListener::UDPListener(const QJsonDocument& config) :
_listenPort(0) _listenPort(0)
{ {
Debug(_log, "Instance created"); Debug(_log, "Instance created");
// listen for comp changes
connect(_hyperion, SIGNAL(componentStateChanged(hyperion::Components,bool)), this, SLOT(componentStateChanged(hyperion::Components,bool)));
// Set trigger for incoming connections
connect(_server, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
// init // init
handleSettingsUpdate(settings::UDPLISTENER, config); handleSettingsUpdate(settings::UDPLISTENER, config);
@ -40,7 +33,6 @@ UDPListener::~UDPListener()
// clear the current channel // clear the current channel
stop(); stop();
delete _server; delete _server;
_hyperion->clear(_priority);
} }
@ -67,12 +59,17 @@ void UDPListener::start()
WarningIf( ! joinGroupOK, _log, "Multicast failed"); WarningIf( ! joinGroupOK, _log, "Multicast failed");
} }
_isActive = true; _isActive = true;
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
if(_bonjourService == nullptr) if(_serviceRegister == nullptr)
{ {
_bonjourService = new BonjourServiceRegister(); _serviceRegister = new BonjourServiceRegister(this);
_bonjourService->registerService("_hyperiond-udp._udp", _listenPort); _serviceRegister->registerService("_hyperiond-udp._udp", _listenPort);
}
else if( _serviceRegister->getPort() != _listenPort)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-udp._udp", _listenPort);
} }
} }
} }
@ -85,8 +82,7 @@ void UDPListener::stop()
_server->close(); _server->close();
_isActive = false; _isActive = false;
Info(_log, "Stopped"); Info(_log, "Stopped");
_hyperion->clear(_priority); emit clearGlobalPriority(_priority, hyperion::COMP_UDPLISTENER);
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
} }
void UDPListener::componentStateChanged(const hyperion::Components component, bool enable) void UDPListener::componentStateChanged(const hyperion::Components component, bool enable)
@ -124,20 +120,19 @@ void UDPListener::readPendingDatagrams()
void UDPListener::processTheDatagram(const QByteArray * datagram, const QHostAddress * sender) void UDPListener::processTheDatagram(const QByteArray * datagram, const QHostAddress * sender)
{ {
int packetLedCount = datagram->size()/3; int packetLedCount = datagram->size()/3;
int hyperionLedCount = Hyperion::getInstance()->getLedCount(); //DebugIf( (packetLedCount != hyperionLedCount), _log, "packetLedCount (%d) != hyperionLedCount (%d)", packetLedCount, hyperionLedCount);
DebugIf( (packetLedCount != hyperionLedCount), _log, "packetLedCount (%d) != hyperionLedCount (%d)", packetLedCount, hyperionLedCount);
std::vector<ColorRgb> _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK); std::vector<ColorRgb> _ledColors(packetLedCount, ColorRgb::BLACK);
for (int ledIndex=0; ledIndex < qMin(packetLedCount, hyperionLedCount); ledIndex++) { for (int ledIndex=0; ledIndex < packetLedCount; ledIndex++) {
ColorRgb & rgb = _ledColors[ledIndex]; ColorRgb & rgb = _ledColors[ledIndex];
rgb.red = datagram->at(ledIndex*3+0); rgb.red = datagram->at(ledIndex*3+0);
rgb.green = datagram->at(ledIndex*3+1); rgb.green = datagram->at(ledIndex*3+1);
rgb.blue = datagram->at(ledIndex*3+2); rgb.blue = datagram->at(ledIndex*3+2);
} }
// TODO provide a setInput with origin arg to overwrite senders smarter // TODO provide a setInput with origin arg to overwrite senders smarter
_hyperion->registerInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString())); emit registerGlobalInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString()));
_hyperion->setInput(_priority, _ledColors, _timeout); emit setGlobalInput(_priority, _ledColors, _timeout);
} }
void UDPListener::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) void UDPListener::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)

View File

@ -13,11 +13,15 @@
#include <QDir> #include <QDir>
#include <QDateTime> #include <QDateTime>
Stats::Stats() Stats* Stats::instance = nullptr;
Stats::Stats(const QJsonObject& config)
: QObject() : QObject()
, _log(Logger::getInstance("STATS")) , _log(Logger::getInstance("STATS"))
, _hyperion(Hyperion::getInstance()) , _hyperion(Hyperion::getInstance())
{ {
Stats::instance = this;
// generate hash // generate hash
foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces()) foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
{ {
@ -38,8 +42,31 @@ Stats::Stats()
return; return;
} }
// prep data
handleDataUpdate(config);
// QNetworkRequest Header
_req.setRawHeader("Content-Type", "application/json");
_req.setRawHeader("Authorization", "Basic SHlwZXJpb25YbDQ5MlZrcXA6ZDQxZDhjZDk4ZjAwYjIw");
connect(&_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(resolveReply(QNetworkReply*)));
// 7 days interval
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendHTTP()));
timer->start(604800000);
// delay initial check
QTimer::singleShot(60000, this, SLOT(initialExec()));
}
Stats::~Stats()
{
}
void Stats::handleDataUpdate(const QJsonObject& config)
{
// prepare content // prepare content
QJsonObject config = _hyperion->getQJsonConfig();
SysInfo::HyperionSysInfo data = SysInfo::get(); SysInfo::HyperionSysInfo data = SysInfo::get();
QJsonObject system; QJsonObject system;
@ -63,25 +90,6 @@ Stats::Stats()
QJsonDocument doc(system); QJsonDocument doc(system);
_ba = doc.toJson(); _ba = doc.toJson();
// QNetworkRequest Header
_req.setRawHeader("Content-Type", "application/json");
_req.setRawHeader("Authorization", "Basic SHlwZXJpb25YbDQ5MlZrcXA6ZDQxZDhjZDk4ZjAwYjIw");
connect(&_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(resolveReply(QNetworkReply*)));
// 7 days interval
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendHTTP()));
timer->start(604800000);
//delay initial check
QTimer::singleShot(60000, this, SLOT(initialExec()));
}
Stats::~Stats()
{
} }
void Stats::initialExec() void Stats::initialExec()

View File

@ -13,11 +13,9 @@
#include <utils/Process.h> #include <utils/Process.h>
#include <utils/jsonschema/QJsonFactory.h> #include <utils/jsonschema/QJsonFactory.h>
CgiHandler::CgiHandler (Hyperion * hyperion, QObject * parent) CgiHandler::CgiHandler (QObject * parent)
: QObject(parent) : QObject(parent)
, _hyperion(hyperion)
, _args(QStringList()) , _args(QStringList())
, _hyperionConfig(_hyperion->getQJsonConfig())
, _baseUrl() , _baseUrl()
, _log(Logger::getInstance("WEBSERVER")) , _log(Logger::getInstance("WEBSERVER"))
{ {
@ -57,11 +55,6 @@ void CgiHandler::cmd_cfg_jsonserver()
if ( _args.at(0) == "cfg_jsonserver" ) if ( _args.at(0) == "cfg_jsonserver" )
{ {
quint16 jsonPort = 19444; quint16 jsonPort = 19444;
if (_hyperionConfig.contains("jsonServer"))
{
const QJsonObject jsonConfig = _hyperionConfig["jsonServer"].toObject();
jsonPort = jsonConfig["port"].toInt(jsonPort);
}
// send result as reply // send result as reply
_reply->addHeader ("Content-Type", "text/plain" ); _reply->addHeader ("Content-Type", "text/plain" );

View File

@ -5,7 +5,6 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <hyperion/Hyperion.h>
#include <utils/Logger.h> #include <utils/Logger.h>
#include "QtHttpReply.h" #include "QtHttpReply.h"
@ -15,7 +14,7 @@ class CgiHandler : public QObject {
Q_OBJECT Q_OBJECT
public: public:
CgiHandler (Hyperion * hyperion, QObject * parent = NULL); CgiHandler (QObject * parent = NULL);
virtual ~CgiHandler (void); virtual ~CgiHandler (void);
void setBaseUrl(const QString& url); void setBaseUrl(const QString& url);
@ -26,11 +25,9 @@ public:
void cmd_runscript (); void cmd_runscript ();
private: private:
Hyperion* _hyperion;
QtHttpReply * _reply; QtHttpReply * _reply;
QtHttpRequest * _request; QtHttpRequest * _request;
QStringList _args; QStringList _args;
const QJsonObject & _hyperionConfig;
QString _baseUrl; QString _baseUrl;
Logger * _log; Logger * _log;
}; };

View File

@ -19,67 +19,69 @@ class QtHttpReply;
class QtHttpClientWrapper; class QtHttpClientWrapper;
class QtHttpServerWrapper : public QTcpServer { class QtHttpServerWrapper : public QTcpServer {
Q_OBJECT Q_OBJECT
public: public:
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR); explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
virtual ~QtHttpServerWrapper (void); virtual ~QtHttpServerWrapper (void);
void setUseSecure (const bool ssl = true); void setUseSecure (const bool ssl = true);
protected: protected:
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE; void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
private: private:
bool m_useSsl; bool m_useSsl;
}; };
class QtHttpServer : public QObject { class QtHttpServer : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit QtHttpServer (QObject * parent = Q_NULLPTR); explicit QtHttpServer (QObject * parent = Q_NULLPTR);
static const QString & HTTP_VERSION; static const QString & HTTP_VERSION;
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &); typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
const QString & getServerName (void) const; const QString & getServerName (void) const;
quint16 getServerPort (void) const; quint16 getServerPort (void) const;
QString getErrorString (void) const; QString getErrorString (void) const;
// const bool isListening(void) { return m_sockServer->isListening(); };
public slots: public slots:
void start (quint16 port = 0); void start (quint16 port = 0);
void stop (void); void stop (void);
void setServerName (const QString & serverName); void setServerName (const QString & serverName);
void setUseSecure (const bool ssl = true); void setUseSecure (const bool ssl = true);
void setPrivateKey (const QSslKey & key); void setPrivateKey (const QSslKey & key);
void setCertificates (const QList<QSslCertificate> & certs); void setCertificates (const QList<QSslCertificate> & certs);
signals: signals:
void started (quint16 port); void started (quint16 port);
void stopped (void); void stopped (void);
void error (const QString & msg); void error (const QString & msg);
void clientConnected (const QString & guid); void clientConnected (const QString & guid);
void clientDisconnected (const QString & guid); void clientDisconnected (const QString & guid);
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply); void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private slots: private slots:
void onClientConnected (void); void onClientConnected (void);
void onClientDisconnected (void); void onClientDisconnected (void);
void onClientSslEncrypted (void); void onClientSslEncrypted (void);
void onClientSslPeerVerifyError (const QSslError & err); void onClientSslPeerVerifyError (const QSslError & err);
void onClientSslErrors (const QList<QSslError> & errors); void onClientSslErrors (const QList<QSslError> & errors);
void onClientSslModeChanged (QSslSocket::SslMode mode); void onClientSslModeChanged (QSslSocket::SslMode mode);
private: private:
bool m_useSsl; bool m_useSsl;
QSslKey m_sslKey; QSslKey m_sslKey;
QList<QSslCertificate> m_sslCerts; QList<QSslCertificate> m_sslCerts;
QString m_serverName; QString m_serverName;
QtHttpServerWrapper * m_sockServer; QtHttpServerWrapper * m_sockServer;
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash; QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
}; };
#endif // QTHTTPSERVER_H #endif // QTHTTPSERVER_H

View File

@ -10,11 +10,10 @@
#include <QResource> #include <QResource>
#include <exception> #include <exception>
StaticFileServing::StaticFileServing (Hyperion *hyperion, QObject * parent) StaticFileServing::StaticFileServing (QObject * parent)
: QObject (parent) : QObject (parent)
, _hyperion(hyperion)
, _baseUrl () , _baseUrl ()
, _cgi(hyperion, this) , _cgi(this)
, _log(Logger::getInstance("WEBSERVER")) , _log(Logger::getInstance("WEBSERVER"))
{ {
Q_INIT_RESOURCE(WebConfig); Q_INIT_RESOURCE(WebConfig);

View File

@ -1,22 +1,23 @@
#ifndef STATICFILESERVING_H #ifndef STATICFILESERVING_H
#define STATICFILESERVING_H #define STATICFILESERVING_H
#include <QMimeDatabase> // locales includes
#include "CgiHandler.h"
//#include "QtHttpServer.h" // qt includes
#include <QMimeDatabase>
#include "QtHttpRequest.h" #include "QtHttpRequest.h"
#include "QtHttpReply.h" #include "QtHttpReply.h"
#include "QtHttpHeader.h" #include "QtHttpHeader.h"
#include "CgiHandler.h"
#include <hyperion/Hyperion.h> //utils includes
#include <utils/Logger.h> #include <utils/Logger.h>
class StaticFileServing : public QObject { class StaticFileServing : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit StaticFileServing (Hyperion *hyperion, QObject * parent = nullptr); explicit StaticFileServing (QObject * parent = nullptr);
virtual ~StaticFileServing (void); virtual ~StaticFileServing (void);
void setBaseUrl(const QString& url); void setBaseUrl(const QString& url);
@ -25,7 +26,6 @@ public slots:
void onRequestNeedsReply (QtHttpRequest * request, QtHttpReply * reply); void onRequestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
private: private:
Hyperion * _hyperion;
QString _baseUrl; QString _baseUrl;
QMimeDatabase * _mimeDb; QMimeDatabase * _mimeDb;
CgiHandler _cgi; CgiHandler _cgi;

View File

@ -1,7 +1,11 @@
#pragma once #pragma once
// utils includes
#include <utils/Logger.h> #include <utils/Logger.h>
// qt includes
#include <QJsonObject>
class QtHttpServer; class QtHttpServer;
class QtHttpRequest; class QtHttpRequest;
class QtHttpClientWrapper; class QtHttpClientWrapper;

View File

@ -1,17 +1,21 @@
#include "webserver/WebServer.h" #include "webserver/WebServer.h"
#include "StaticFileServing.h" #include "StaticFileServing.h"
#include "QtHttpServer.h"
// bonjour // qt includes
#include "QtHttpServer.h"
#include <QFileInfo>
#include <QJsonObject>
// bonjour includes
#include <bonjour/bonjourserviceregister.h> #include <bonjour/bonjourserviceregister.h>
#include <bonjour/bonjourrecord.h> #include <bonjour/bonjourrecord.h>
#include <QFileInfo> // utils includes
#include <utils/NetUtils.h>
WebServer::WebServer(const QJsonDocument& config, QObject * parent) WebServer::WebServer(const QJsonDocument& config, QObject * parent)
: QObject(parent) : QObject(parent)
, _log(Logger::getInstance("WEBSERVER")) , _log(Logger::getInstance("WEBSERVER"))
, _hyperion(Hyperion::getInstance())
, _server(new QtHttpServer (this)) , _server(new QtHttpServer (this))
{ {
_server->setServerName (QStringLiteral ("Hyperion Webserver")); _server->setServerName (QStringLiteral ("Hyperion Webserver"));
@ -21,7 +25,7 @@ WebServer::WebServer(const QJsonDocument& config, QObject * parent)
connect (_server, &QtHttpServer::error, this, &WebServer::onServerError); connect (_server, &QtHttpServer::error, this, &WebServer::onServerError);
// create StaticFileServing // create StaticFileServing
_staticFileServing = new StaticFileServing (_hyperion, this); _staticFileServing = new StaticFileServing (this);
connect(_server, &QtHttpServer::requestNeedsReply, _staticFileServing, &StaticFileServing::onRequestNeedsReply); connect(_server, &QtHttpServer::requestNeedsReply, _staticFileServing, &StaticFileServing::onRequestNeedsReply);
Debug(_log, "Instance created"); Debug(_log, "Instance created");
@ -38,8 +42,17 @@ void WebServer::onServerStarted (quint16 port)
{ {
Info(_log, "Started on port %d name '%s'", port ,_server->getServerName().toStdString().c_str()); Info(_log, "Started on port %d name '%s'", port ,_server->getServerName().toStdString().c_str());
BonjourServiceRegister *bonjourRegister_http = new BonjourServiceRegister(); if(_serviceRegister == nullptr)
bonjourRegister_http->registerService("_hyperiond-http._tcp", port); {
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-http._tcp", port);
}
else if( _serviceRegister->getPort() != port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-http._tcp", port);
}
} }
void WebServer::onServerStopped () { void WebServer::onServerStopped () {
@ -57,10 +70,8 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
{ {
const QJsonObject& obj = config.object(); const QJsonObject& obj = config.object();
bool webconfigEnable = obj["enable"].toBool(true);
_baseUrl = obj["document_root"].toString(WEBSERVER_DEFAULT_PATH); _baseUrl = obj["document_root"].toString(WEBSERVER_DEFAULT_PATH);
if ( (_baseUrl != ":/webconfig") && !_baseUrl.trimmed().isEmpty()) if ( (_baseUrl != ":/webconfig") && !_baseUrl.trimmed().isEmpty())
{ {
QFileInfo info(_baseUrl); QFileInfo info(_baseUrl);
@ -81,10 +92,10 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
_port = obj["port"].toInt(WEBSERVER_DEFAULT_PORT); _port = obj["port"].toInt(WEBSERVER_DEFAULT_PORT);
stop(); stop();
} }
if ( webconfigEnable )
{ // eval if the port is available, will be incremented if not
start(); NetUtils::portAvailable(_port, _log);
} start();
} }
} }

View File

@ -1,13 +1,18 @@
#include "WebSocketClient.h" #include "WebSocketClient.h"
#include "QtHttpRequest.h"
#include "QtHttpHeader.h"
// hyperion includes
#include <hyperion/Hyperion.h> #include <hyperion/Hyperion.h>
// JsonAPI includes
#include <api/JsonAPI.h> #include <api/JsonAPI.h>
// qt includes
#include "QtHttpRequest.h"
#include "QtHttpHeader.h"
#include <QTcpSocket> #include <QTcpSocket>
#include <QtEndian> #include <QtEndian>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QJsonObject>
WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObject* parent) WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObject* parent)
: QObject(parent) : QObject(parent)

View File

@ -56,10 +56,9 @@ int main(int argc, char** argv)
// create the option parser and initialize all parameters // create the option parser and initialize all parameters
Parser parser("V4L capture application for Hyperion"); Parser parser("V4L capture application for Hyperion");
Option & argDevice = parser.add<Option> ('d', "device", "The device to use [default: %1]", "auto"); Option & argDevice = parser.add<Option> ('d', "device", "The device to use, can be /dev/video0 [default: %1 (auto detected)]", "auto");
SwitchOption<VideoStandard> & argVideoStandard= parser.add<SwitchOption<VideoStandard>>('v', "video-standard", "The used video standard. Valid values are PAL, NTSC, SECAM or no-change. [default: %1]", "no-change"); SwitchOption<VideoStandard> & argVideoStandard= parser.add<SwitchOption<VideoStandard>>('v', "video-standard", "The used video standard. Valid values are PAL, NTSC, SECAM or no-change. [default: %1]", "no-change");
SwitchOption<PixelFormat> & argPixelFormat = parser.add<SwitchOption<PixelFormat>> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, RGB32 or no-change. [default: %1]", "no-change"); SwitchOption<PixelFormat> & argPixelFormat = parser.add<SwitchOption<PixelFormat>> (0x0, "pixel-format", "The use pixel format. Valid values are YUYV, UYVY, RGB32 or no-change. [default: %1]", "no-change");
IntOption & argInput = parser.add<IntOption> (0x0, "input", "Input channel (optional)", "-1");
IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0"); IntOption & argCropWidth = parser.add<IntOption> (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0");
IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0"); IntOption & argCropHeight = parser.add<IntOption> (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0");
IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); IntOption & argCropLeft = parser.add<IntOption> (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)");
@ -109,7 +108,6 @@ int main(int argc, char** argv)
// initialize the grabber // initialize the grabber
V4L2Grabber grabber( V4L2Grabber grabber(
argDevice.value(parser), argDevice.value(parser),
argInput.getInt(parser),
argVideoStandard.switchValue(parser), argVideoStandard.switchValue(parser),
argPixelFormat.switchValue(parser), argPixelFormat.switchValue(parser),
std::max(1, argSizeDecimation.getInt(parser))); std::max(1, argSizeDecimation.getInt(parser)));

View File

@ -36,8 +36,9 @@ bool X11Wrapper::displayInit()
void X11Wrapper::capture() void X11Wrapper::capture()
{ {
_grabber.grabFrame(_screenshot, true); _grabber.grabFrame(_screenshot, !_inited);
emit sig_screenshot(_screenshot); emit sig_screenshot(_screenshot);
_inited = true;
} }
void X11Wrapper::setVideoMode(const VideoMode mode) void X11Wrapper::setVideoMode(const VideoMode mode)

View File

@ -50,4 +50,7 @@ private:
X11Grabber _grabber; X11Grabber _grabber;
Image<ColorRgb> _screenshot; Image<ColorRgb> _screenshot;
// prevent cont dimension updates
bool _inited = false;
}; };

View File

@ -1,5 +1,5 @@
find_package(PythonLibs 3.4 REQUIRED) find_package(PythonLibs 3.5 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}/..) include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}/..)
add_executable(hyperiond add_executable(hyperiond
@ -15,9 +15,9 @@ target_link_libraries(hyperiond
hyperion hyperion
effectengine effectengine
jsonserver jsonserver
boblightserver
udplistener udplistener
protoserver protoserver
flatbufserver
webserver webserver
bonjour bonjour
python python

View File

@ -14,6 +14,7 @@
#include <QPair> #include <QPair>
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <QThread>
#include <utils/Components.h> #include <utils/Components.h>
#include <utils/JsonUtils.h> #include <utils/JsonUtils.h>
@ -21,13 +22,15 @@
#include <hyperion/Hyperion.h> #include <hyperion/Hyperion.h>
#include <jsonserver/JsonServer.h> #include <jsonserver/JsonServer.h>
#include <protoserver/ProtoServer.h> #include <protoserver/ProtoServer.h>
#include <boblightserver/BoblightServer.h>
#include <udplistener/UDPListener.h> #include <udplistener/UDPListener.h>
#include <webserver/WebServer.h> #include <webserver/WebServer.h>
#include <utils/Stats.h> #include <utils/Stats.h>
#include <HyperionConfig.h> // Required to determine the cmake options #include <HyperionConfig.h> // Required to determine the cmake options
#include "hyperiond.h" #include "hyperiond.h"
// FlatBufferServer
#include <flatbufserver/FlatBufferServer.h>
// bonjour browser // bonjour browser
#include <bonjour/bonjourbrowserwrapper.h> #include <bonjour/bonjourbrowserwrapper.h>
@ -39,7 +42,7 @@
HyperionDaemon* HyperionDaemon::daemon = nullptr; HyperionDaemon* HyperionDaemon::daemon = nullptr;
HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObject *parent) HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObject *parent, const bool& logLvlOverwrite)
: QObject(parent) : QObject(parent)
, _log(Logger::getInstance("DAEMON")) , _log(Logger::getInstance("DAEMON"))
, _bonjourBrowserWrapper(new BonjourBrowserWrapper()) , _bonjourBrowserWrapper(new BonjourBrowserWrapper())
@ -47,7 +50,6 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje
, _webserver(nullptr) , _webserver(nullptr)
, _jsonServer(nullptr) , _jsonServer(nullptr)
, _protoServer(nullptr) , _protoServer(nullptr)
, _boblightServer(nullptr)
, _udpListener(nullptr) , _udpListener(nullptr)
, _v4l2Grabbers() , _v4l2Grabbers()
, _dispmanx(nullptr) , _dispmanx(nullptr)
@ -61,23 +63,19 @@ HyperionDaemon::HyperionDaemon(QString configFile, const QString rootPath, QObje
{ {
HyperionDaemon::daemon = this; HyperionDaemon::daemon = this;
// Register metas for thread queued connection
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
qRegisterMetaType<hyperion::Components>("hyperion::Components");
qRegisterMetaType<settings::type>("settings::type");
// init settings // init settings
_settingsManager = new SettingsManager(0,configFile); _settingsManager = new SettingsManager(0,configFile);
const QJsonObject& logConfig = _settingsManager->getSetting(settings::LOGGER).object(); // set inital log lvl if the loglvl wasn't overwritten by arg
if (Logger::getLogLevel() == Logger::WARNING) if(!logLvlOverwrite)
{ handleSettingsUpdate(settings::LOGGER, _settingsManager->getSetting(settings::LOGGER));
std::string level = logConfig["level"].toString("warn").toStdString(); // silent warn verbose debug
if (level == "silent") Logger::setLogLevel(Logger::OFF);
else if (level == "warn") Logger::setLogLevel(Logger::WARNING);
else if (level == "verbose") Logger::setLogLevel(Logger::INFO);
else if (level == "debug") Logger::setLogLevel(Logger::DEBUG);
}
else
{
Warning(Logger::getInstance("LOGGER"), "Logger settings overridden by command line argument");
}
// spawn all Hyperion instances before network services
_hyperion = Hyperion::initInstance(this, 0, configFile, rootPath); _hyperion = Hyperion::initInstance(this, 0, configFile, rootPath);
Info(_log, "Hyperion initialized"); Info(_log, "Hyperion initialized");
@ -141,7 +139,8 @@ void HyperionDaemon::freeObjects()
delete _webserver; delete _webserver;
delete _jsonServer; delete _jsonServer;
delete _protoServer; delete _protoServer;
delete _boblightServer; _flatBufferServer->thread()->quit();
_flatBufferServer->thread()->wait(1000);
delete _udpListener; delete _udpListener;
delete _bonjourBrowserWrapper; delete _bonjourBrowserWrapper;
@ -164,15 +163,14 @@ void HyperionDaemon::freeObjects()
_webserver = nullptr; _webserver = nullptr;
_jsonServer = nullptr; _jsonServer = nullptr;
_protoServer = nullptr; _protoServer = nullptr;
_boblightServer = nullptr;
_udpListener = nullptr; _udpListener = nullptr;
_stats = nullptr; _stats = nullptr;
} }
void HyperionDaemon::startNetworkServices() void HyperionDaemon::startNetworkServices()
{ {
// Create Stats before network services // Create Stats
_stats = new Stats(); _stats = new Stats(_settingsManager->getSettings());
// Create Json server // Create Json server
_jsonServer = new JsonServer(getSetting(settings::JSONSERVER)); _jsonServer = new JsonServer(getSetting(settings::JSONSERVER));
@ -181,11 +179,17 @@ void HyperionDaemon::startNetworkServices()
// Create Proto server // Create Proto server
_protoServer = new ProtoServer(getSetting(settings::PROTOSERVER)); _protoServer = new ProtoServer(getSetting(settings::PROTOSERVER));
connect(this, &HyperionDaemon::settingsChanged, _protoServer, &ProtoServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _protoServer, &ProtoServer::handleSettingsUpdate);
//QObject::connect(_hyperion, SIGNAL(videoMode(VideoMode)), _protoServer, SLOT(setVideoMode(VideoMode)));
// boblight server // Create FlatBuffer server & move to Thread
_boblightServer = new BoblightServer(getSetting(settings::BOBLSERVER)); _flatBufferServer = new FlatBufferServer(getSetting(settings::FLATBUFSERVER));
connect(this, &HyperionDaemon::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, _flatBufferServer, &FlatBufferServer::handleSettingsUpdate);
QThread* fbThread = new QThread(this);
_flatBufferServer->moveToThread(fbThread);
connect( fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer );
connect( fbThread, &QThread::finished, _flatBufferServer, &QObject::deleteLater );
connect( fbThread, &QThread::finished, fbThread, &QObject::deleteLater );
fbThread->start();
// Create UDP listener // Create UDP listener
_udpListener = new UDPListener(getSetting(settings::UDPLISTENER)); _udpListener = new UDPListener(getSetting(settings::UDPLISTENER));
@ -198,6 +202,17 @@ void HyperionDaemon::startNetworkServices()
void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config) void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{ {
if(type == settings::LOGGER)
{
const QJsonObject & logConfig = config.object();
std::string level = logConfig["level"].toString("warn").toStdString(); // silent warn verbose debug
if (level == "silent") Logger::setLogLevel(Logger::OFF);
else if (level == "warn") Logger::setLogLevel(Logger::WARNING);
else if (level == "verbose") Logger::setLogLevel(Logger::INFO);
else if (level == "debug") Logger::setLogLevel(Logger::DEBUG);
}
if(type == settings::SYSTEMCAPTURE) if(type == settings::SYSTEMCAPTURE)
{ {
const QJsonObject & grabberConfig = config.object(); const QJsonObject & grabberConfig = config.object();
@ -249,7 +264,6 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
else if (type == "amlogic" && _amlGrabber == nullptr) createGrabberAmlogic(); else if (type == "amlogic" && _amlGrabber == nullptr) createGrabberAmlogic();
else if (type == "osx" && _osxGrabber == nullptr) createGrabberOsx(grabberConfig); else if (type == "osx" && _osxGrabber == nullptr) createGrabberOsx(grabberConfig);
else if (type == "x11" && _x11Grabber == nullptr) createGrabberX11(grabberConfig); else if (type == "x11" && _x11Grabber == nullptr) createGrabberX11(grabberConfig);
else { Warning( _log, "unknown framegrabber type '%s'", QSTRING_CSTR(type)); }
} }
else if(type == settings::V4L2) else if(type == settings::V4L2)
{ {
@ -268,7 +282,6 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
#ifdef ENABLE_V4L2 #ifdef ENABLE_V4L2
V4L2Wrapper* grabber = new V4L2Wrapper( V4L2Wrapper* grabber = new V4L2Wrapper(
grabberConfig["device"].toString("auto"), grabberConfig["device"].toString("auto"),
grabberConfig["input"].toInt(0),
parseVideoStandard(grabberConfig["standard"].toString("no-change")), parseVideoStandard(grabberConfig["standard"].toString("no-change")),
parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")), parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")),
grabberConfig["sizeDecimation"].toInt(8) ); grabberConfig["sizeDecimation"].toInt(8) );
@ -294,10 +307,6 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
connect(this, &HyperionDaemon::videoMode, grabber, &V4L2Wrapper::setVideoMode); connect(this, &HyperionDaemon::videoMode, grabber, &V4L2Wrapper::setVideoMode);
connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate); connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate);
if (grabber->start())
{
Info(_log, "V4L2 grabber started");
}
_v4l2Grabbers.push_back(grabber); _v4l2Grabbers.push_back(grabber);
#endif #endif
} }

View File

@ -50,13 +50,13 @@ class Hyperion;
class SysTray; class SysTray;
class JsonServer; class JsonServer;
class ProtoServer; class ProtoServer;
class BoblightServer;
class UDPListener; class UDPListener;
class Stats; class Stats;
class BonjourBrowserWrapper; class BonjourBrowserWrapper;
class WebServer; class WebServer;
class SettingsManager; class SettingsManager;
class PythonInit; class PythonInit;
class FlatBufferServer;
class HyperionDaemon : public QObject class HyperionDaemon : public QObject
{ {
@ -65,7 +65,7 @@ class HyperionDaemon : public QObject
friend SysTray; friend SysTray;
public: public:
HyperionDaemon(QString configFile, QString rootPath, QObject *parent=nullptr); HyperionDaemon(QString configFile, QString rootPath, QObject *parent, const bool& logLvlOverwrite );
~HyperionDaemon(); ~HyperionDaemon();
quint16 getWebServerPort(); quint16 getWebServerPort();
@ -135,7 +135,6 @@ private:
WebServer* _webserver; WebServer* _webserver;
JsonServer* _jsonServer; JsonServer* _jsonServer;
ProtoServer* _protoServer; ProtoServer* _protoServer;
BoblightServer* _boblightServer;
UDPListener* _udpListener; UDPListener* _udpListener;
std::vector<V4L2Wrapper*> _v4l2Grabbers; std::vector<V4L2Wrapper*> _v4l2Grabbers;
DispmanxWrapper* _dispmanx; DispmanxWrapper* _dispmanx;
@ -145,6 +144,7 @@ private:
OsxWrapper* _osxGrabber; OsxWrapper* _osxGrabber;
Hyperion* _hyperion; Hyperion* _hyperion;
Stats* _stats; Stats* _stats;
FlatBufferServer* _flatBufferServer;
unsigned _grabber_width; unsigned _grabber_width;
unsigned _grabber_height; unsigned _grabber_height;

View File

@ -317,7 +317,7 @@ int main(int argc, char** argv)
HyperionDaemon* hyperiond = nullptr; HyperionDaemon* hyperiond = nullptr;
try try
{ {
hyperiond = new HyperionDaemon(configFiles[0], rootPath, qApp); hyperiond = new HyperionDaemon(configFiles[0], rootPath, qApp, bool(logLevelCheck));
} }
catch (std::exception& e) catch (std::exception& e)
{ {