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_USE_SHARED_AVAHI_LIBS ON )
SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS OFF )
SET ( DEFAULT_TESTS OFF )
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_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
FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json )
SET( JSON_FILES
@ -246,7 +250,7 @@ if (UNIX AND NOT APPLE)
endif ()
# 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)
message( STATUS "Found Qt Version: ${Qt5Core_VERSION}" )
IF ( "${Qt5Core_VERSION}" VERSION_LESS "${QT_MIN_VERSION}" )

View File

@ -6,24 +6,13 @@
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
```
### 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**
```
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
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
# ... or run it from compile directory
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).
## 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
See [Compilehowto](CompileHowto.md) and [CrossCompileHowto](CrossCompileHowto.txt).

View File

@ -27,6 +27,7 @@
"general_col_green" : "grün",
"general_col_blue" : "blau",
"general_button_savesettings" : "Einstellungen speichern",
"general_btn_yes" : "Ja",
"general_btn_ok" : "OK",
"general_btn_cancel" : "Abbrechen",
"general_btn_continue" : "Fortfahren",
@ -346,7 +347,7 @@
"edt_dev_enum_sub_min_warm_adjust" : "Minimale Anpassung: warm",
"edt_dev_enum_white_off" : "Weiß ist aus",
"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_rewriteTime_title" : "Aktualisierungszeit",
"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_v4l2_heading_title" : "USB Aufnahme",
"edt_conf_v4l2_device_title" : "Gerät",
"edt_conf_v4l2_device_expl" : "Der Pfad zum USB Aufnahmegerät.",
"edt_conf_v4l2_input_title" : "Eingang",
"edt_conf_v4l2_input_expl" : "Der Eingang des Pfades.",
"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_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_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_expl" : "Anzahl der Pixel auf der linken Seite die vom Bild entfernt werden.",
"edt_conf_v4l2_cropRight_title" : "Entferne rechts",
@ -498,7 +497,7 @@
"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_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_expl" : "Je höher die rote Schwelle je eher wird abgeschalten bei entsprechendem rot-Anteil.",
"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_sDHOffsetMax_title" : "Signal Erkennung HMax",
"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_type_title" : "Typ",
"edt_conf_fg_type_expl" : "Art der Plattform Aufnahme, standard ist 'auto'",

View File

@ -27,6 +27,7 @@
"general_col_green" : "green",
"general_col_blue" : "blue",
"general_button_savesettings" : "Save settings",
"general_btn_yes" : "Yes",
"general_btn_ok" : "OK",
"general_btn_cancel" : "Cancel",
"general_btn_continue" : "Continue",
@ -347,7 +348,7 @@
"edt_dev_enum_white_off" : "White off",
"edt_dev_general_heading_title" : "General Settings",
"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_rewriteTime_title" : "Refresh time",
"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_v4l2_heading_title" : "USB Capture",
"edt_conf_v4l2_device_title" : "Device",
"edt_conf_v4l2_device_expl" : "The path to the usb capture.",
"edt_conf_v4l2_input_title" : "Input",
"edt_conf_v4l2_input_expl" : "Input of this path.",
"edt_conf_v4l2_device_expl" : "The path to the usb capture interface. Set to 'auto' for auto detection. Example: '/dev/video0'",
"edt_conf_v4l2_standard_title" : "Video standard",
"edt_conf_v4l2_standard_expl" : "Select the video standard for your region.",
"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_standard_expl" : "Select the video standard for your region. 'Auto' keeps the chosen one from v4l interface",
"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_cropLeft_title" : "Crop left",
@ -505,7 +498,7 @@
"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_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_expl" : "Darkens low red values (recognized as black)",
"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_sDHOffsetMax_title" : "Signal Detection HMax",
"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_type_title" : "Type",
"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_json = null;
var conf_editor_proto = null;
var conf_editor_fbs = null;
var conf_editor_bobl = null;
var conf_editor_udpl = 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(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
$('#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'));
@ -43,6 +49,7 @@ $(document).ready( function() {
$('#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_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_udpl_heading_title"), 'editor_container_udplistener', 'btn_submit_udplistener'));
if(storedAccess != 'default')
@ -62,7 +69,7 @@ $(document).ready( function() {
requestWriteConfig(conf_editor_json.getValue());
});
//proto
//protobuffer
conf_editor_proto = createJsonEditor('editor_container_protoserver', {
protoServer : schema.protoServer
}, true, true);
@ -75,6 +82,19 @@ $(document).ready( function() {
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
conf_editor_bobl = createJsonEditor('editor_container_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_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_udpl_intro'), "editor_container_udplistener");
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
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()

File diff suppressed because one or more lines are too long

View File

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

View File

@ -6,6 +6,7 @@ install_file()
dest="$2"
if [ ! -e "$dest" ]
then
cp "$src" "${dest}"
return 1
else
@ -15,10 +16,7 @@ install_file()
}
echo "--- hyperion ambient light postinstall ---"
echo "- install configuration template"
mkdir -p /etc/hyperion
mkdir -p /usr/share/hyperion/custom-effects
echo "---Hyperion ambient light postinstall ---"
#check system
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
BOOT_BERRYBOOT=$(grep -m1 -c '\(/var/media\|/media/pi\)/berryboot' /etc/mtab)
#get current system ip + add default port
address=$(ip -o -4 a | awk '$2 == "eth0" { gsub(/\/.*/, "", $4); print $4 }')":8099"
#get current system ip
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
HYPERION_RUNNING=false
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=""
restart_msg=""
SERVICE_POSTFIX=""
if grep -m1 systemd /proc/1/comm > /dev/null
then
echo "--> init deamon: systemd"
# systemd
$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
start_msg="--> systemctl start hyperiond"
systemctl start hyperiond
install_file /usr/share/hyperion/service/hyperion.systemd /etc/systemd/system/hyperiond@.service
systemctl enable hyperiond"@${FOUND_USR}".service
start_msg="--> systemctl start hyperiond for user ${FOUND_USR}"
systemctl start hyperiond"@${FOUND_USR}"
elif [ -e /sbin/initctl ]
then
@ -100,9 +102,12 @@ if [ $CPU_RPI -eq 1 ]; then
fi
fi
echo ${start_msg}
echo "-----------------------------------------------------------------------------"
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
echo "-----------------------------------------------------------------------------"
echo "Webpage: www.hyperion-project.org"
@ -110,28 +115,12 @@ echo "Wiki: wiki.hyperion-project.org"
echo "Forum: forum.hyperion-project.org"
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/ ]
then
echo
echo "---------------------------------------------------------------------------------"
echo "- It seemd that you have an older version of hyperion installed in /opt/hyerion -"
echo "- please remove it and check your config to avoid problems -"
echo "- It seemd that you have an older version of hyperion installed in /opt/hyperion -"
echo "- please remove it to avoid problems -"
echo "---------------------------------------------------------------------------------"
fi

View File

@ -1,51 +1,56 @@
#!/bin/sh
# check which init script we should use
USE_SYSTEMD=`grep -m1 -c systemd /proc/1/comm`
USE_INITCTL=`which /sbin/initctl | wc -l`
USE_SERVICE=`which /usr/sbin/service | wc -l`
echo "---Hyperion ambient light preinst ---"
#check for hyperion install
if [ -d /usr/share/hyperion/bin ];then
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
echo '---> Stop Hyperion, if necessary'
if [ $USE_SYSTEMD -eq 1 ]; then
service hyperion stop 2>/dev/null
elif [ $USE_INITCTL -eq 1 ]; then
/sbin/initctl stop hyperion 2>/dev/null
elif [ $USE_SERVICE -eq 1 ]; then
/usr/sbin/service hyperion stop 2>/dev/null
fi
#Backup
echo "--> Move old config(s) and files to /usr/share/hyperion/Backup_Hyperion_1.0"
mkdir /usr/share/hyperion/Backup_Hyperion_1.0
mv /usr/share/hyperion /usr/share/hyperion/Backup_Hyperion_1.0
mv /etc/hyperion/* /usr/share/hyperion/Backup_Hyperion_1.0
# search for users in system, returns first entry
FOUND_USR=`who | grep -o '^\w*\b'` || "root"
#Disabling and delete service files
if [ $USE_SYSTEMD -eq 1 ]; then
# Delete and disable Hyperion systemd script
echo '---> Delete and disable Hyperion systemd service'
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
# stop running daemon before we install
if pgrep hyperiond > /dev/null 2>&1
then
if grep -m1 systemd /proc/1/comm > /dev/null
then
echo "--> stop init deamon: systemd"
# systemd
systemctl stop hyperiond"@${FOUND_USR}" 2> /dev/null
elif [ -e /sbin/initctl ]
then
echo "--> stop init deamon: upstart"
# upstart
initctl stop hyperiond
else
echo "--> stop init deamon: sysV"
# sysV
service hyperiond stop 2>/dev/null
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_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_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_RPM_PACKAGE_NAME "Hyperion" )

View File

@ -20,14 +20,14 @@
/// Device configuration contains the following fields:
/// * '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
/// 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)
/// * 'type' : The type of the device
/// * [device type specific configuration]
/// * '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
"device" :
{
"type" : "file",
"hardwareLedCount" : 1,
"output" : "/dev/null",
"rate" : 1000000,
"colorOrder" : "rgb",
@ -98,8 +98,7 @@
},
/// Configuration for the embedded V4L2 grabber
/// * device : V4L2 Device to use [default="/dev/video0"]
/// * input : V4L2 input to use [default=0]
/// * device : V4L2 Device to use [default="auto"] (Auto detection)
/// * standard : Video standard (PAL/NTSC/SECAM/NO_CHANGE) [default="NO_CHANGE"]
/// * sizeDecimation : Size decimation factor [default=8]
/// * cropLeft : Cropping from the left [default=0]
@ -118,7 +117,6 @@
[
{
"device" : "auto",
"input" : 0,
"standard" : "NO_CHANGE",
"sizeDecimation" : 8,
"priority" : 240,
@ -233,13 +231,22 @@
"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
"protoServer" :
{
"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
/// * enable : Enable or disable the boblight server (true/false)
/// * port : Port at which the boblight server is started
@ -269,12 +276,10 @@
},
/// Configuration of the Hyperion webserver
/// * enable : enable or disable the webserver (true/false)
/// * document_root : path to hyperion webapp files (webconfig developer only)
/// * port : the port where hyperion webapp is accasible
"webConfig" :
{
"enable" : true,
"document_root" : "/path/to/files",
"port" : 8090
},

View File

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

View File

@ -9,6 +9,48 @@ if(ENABLE_WS281XPWM)
external/rpi_ws281x/rpihw.c)
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")
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 port port number on which to start listening for connections
///
BoblightServer(const QJsonDocument& config);
BoblightServer(Hyperion* hyperion, const QJsonDocument& config);
~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>>());
inline BonjourRecord registeredRecord() const {return finalRecord; }
const quint16 & getPort() { return _port; };
signals:
void error(DNSServiceErrorType error);
void serviceRegistered(const BonjourRecord &record);
@ -62,6 +64,9 @@ private:
DNSServiceRef dnssref;
QSocketNotifier *bonjourSocket;
BonjourRecord finalRecord;
// current port
quint16 _port = 0;
};
#endif // BONJOURSERVICEREGISTER_H

View File

@ -19,7 +19,7 @@
#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
{
@ -40,7 +40,7 @@ public:
~FlatBufferConnection();
/// 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
@ -116,8 +116,8 @@ private:
/// Host port
uint16_t _port;
/// Skip receiving reply messages from Hyperion if set
bool _skipReply;
/// buffer for reply
QByteArray _receiveBuffer;
QTimer _timer;
QAbstractSocket::SocketState _prevSocketState;

View File

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

View File

@ -42,7 +42,7 @@ public:
///
///@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:
///

View File

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

View File

@ -9,7 +9,6 @@ class V4L2Wrapper : public GrabberWrapper
public:
V4L2Wrapper(const QString & device,
int input,
VideoStandard videoStandard,
PixelFormat pixelFormat,
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
///
virtual void setWidthHeight(int width, int height);
virtual bool setWidthHeight(int width, int height) { return true; };
///
/// @brief Apply new pixelDecimation

View File

@ -6,6 +6,7 @@
#include <utils/Image.h>
class Hyperion;
class QTimer;
///
/// @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);
///
/// @brief Is called from _v4lInactiveTimer to set source after specific time to inactive
///
void setV4lInactive();
private:
/// Hyperion instance
Hyperion* _hyperion;
@ -59,4 +65,5 @@ private:
/// Reflect state of v4l capture and prio
bool _v4lCaptEnabled;
quint8 _v4lCaptPrio;
QTimer* _v4lInactiveTimer;
};

View File

@ -33,9 +33,9 @@ public:
///
/// @brief Check if a component is currently enabled
/// @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
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
///
virtual void setWidthHeight(int width, int height);
virtual bool setWidthHeight(int width, int height);
///
/// @brief Apply new pixelDecimation (used from x11)
@ -66,9 +66,9 @@ public:
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)

View File

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

View File

@ -49,6 +49,7 @@ class ColorAdjustment;
class SettingsManager;
class BGEffectHandler;
class CaptureCont;
class BoblightServer;
///
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
@ -105,6 +106,8 @@ public:
///
PriorityMuxer* getMuxerInstance() { return &_muxer; };
ImageProcessor* getImageProcessor() { return _imageProcessor; };
///
/// @brief Get a setting by settings::type from SettingsManager
/// @param type The settingsType from enum
@ -145,7 +148,7 @@ public:
bool isCurrentPriority(const int priority) const;
///
/// Returns a list of active priorities
/// Returns a list of all registered 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);
///
/// @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
/// Registers comp color or provided type against muxer
@ -540,4 +550,7 @@ private:
std::vector<ColorRgb> _ledBuffer;
/// buffer for leds (without adjustment)
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);
///
/// @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
///

View File

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

View File

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

View File

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

View File

@ -11,15 +11,13 @@
// Hyperion includes
#include <utils/Logger.h>
#include <utils/Components.h>
#include <utils/ColorRgb.h>
// settings
#include <utils/settings.h>
class Hyperion;
class UDPClientConnection;
class BonjourServiceRegister;
class QUdpSocket;
class NetOrigin;
///
/// 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);
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:
///
/// 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);
private:
/// Hyperion instance
Hyperion * _hyperion;
/// The UDP server object
QUdpSocket * _server;
/// List with open connections
QSet<UDPClientConnection *> _openConnections;
/// hyperion priority
int _priority;
@ -94,7 +103,7 @@ private:
Logger * _log;
/// Bonjour Service Register
BonjourServiceRegister* _bonjourService = nullptr;
BonjourServiceRegister* _serviceRegister = nullptr;
/// state of connection
bool _isActive;
@ -103,7 +112,4 @@ private:
QHostAddress _listenAddress;
uint16_t _listenPort;
QAbstractSocket::BindFlag _bondage;
/// Check Network Origin
NetOrigin* _netOrigin;
};

View File

@ -22,7 +22,8 @@ enum Components
COMP_IMAGE,
COMP_EFFECT,
COMP_PROTOSERVER,
COMP_LEDDEVICE
COMP_LEDDEVICE,
COMP_FLATBUFSERVER
};
inline const char* componentToString(Components c)
@ -42,6 +43,7 @@ inline const char* componentToString(Components c)
case COMP_IMAGE: return "Image";
case COMP_PROTOSERVER: return "Proto Server";
case COMP_LEDDEVICE: return "LED device";
case COMP_FLATBUFSERVER: return "Image Receiver";
default: return "";
}
}
@ -63,6 +65,7 @@ inline const char* componentToIdString(Components c)
case COMP_IMAGE: return "IMAGE";
case COMP_PROTOSERVER: return "PROTOSERVER";
case COMP_LEDDEVICE: return "LEDDEVICE";
case COMP_FLATBUFSERVER: return "FLATBUFSERVER";
default: return "";
}
}
@ -83,7 +86,7 @@ inline Components stringToComponent(QString component)
if (component == "IMAGE") return COMP_IMAGE;
if (component == "PROTOSERVER") return COMP_PROTOSERVER;
if (component == "LEDDEVICE") return COMP_LEDDEVICE;
if (component == "FLATBUFSERVER") return COMP_FLATBUFSERVER;
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:
Stats();
static Stats* getInstance() { return instance; };
static Stats* instance;
void handleDataUpdate(const QJsonObject& config);
private:
friend class HyperionDaemon;
Stats(const QJsonObject& config);
~Stats();
private:

View File

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

View File

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

View File

@ -8,6 +8,7 @@ add_subdirectory(commandline)
add_subdirectory(blackborder)
add_subdirectory(jsonserver)
add_subdirectory(protoserver)
add_subdirectory(flatbufserver)
add_subdirectory(bonjour)
add_subdirectory(boblightserver)
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);
_blurRemoveCnt = obj["blurRemoveCnt"].toInt(1);
_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);
if(_detector != nullptr) delete _detector;
_detector = new BlackBorderDetector(obj["threshold"].toDouble(5.0/100));
_oldThreshold = newThreshold;
if(_detector != nullptr)
delete _detector;
_detector = new BlackBorderDetector(newThreshold);
}
Debug(Logger::getInstance("BLACKBORDER"), "Set mode to: %s", QSTRING_CSTR(_detectionMode));

View File

@ -15,23 +15,22 @@
#include <QHostInfo>
// hyperion util includes
//#include "hyperion/ImageProcessorFactory.h"
//#include "hyperion/ImageProcessor.h"
#include "utils/ColorRgb.h"
#include <hyperion/ImageProcessor.h>
#include "HyperionConfig.h"
#include <hyperion/Hyperion.h>
// project includes
#include "BoblightClientConnection.h"
BoblightClientConnection::BoblightClientConnection(QTcpSocket *socket, const int priority)
BoblightClientConnection::BoblightClientConnection(Hyperion* hyperion, QTcpSocket *socket, const int priority)
: QObject()
, _locale(QLocale::C)
, _socket(socket)
//, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
, _hyperion(Hyperion::getInstance())
, _imageProcessor(hyperion->getImageProcessor())
, _hyperion(hyperion)
, _receiveBuffer()
, _priority(priority)
, _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK)
, _ledColors(hyperion->getLedCount(), ColorRgb::BLACK)
, _log(Logger::getInstance("BOBLIGHT"))
, _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());
sendMessage(QByteArray(buffer, n));
//double h0, h1, v0, v1;
double h0, h1, v0, v1;
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
{
//_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);
//sendMessage(QByteArray(buffer, n));
_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);
sendMessage(QByteArray(buffer, n));
}
}

View File

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

View File

@ -12,9 +12,9 @@
using namespace hyperion;
BoblightServer::BoblightServer(const QJsonDocument& config)
BoblightServer::BoblightServer(Hyperion* hyperion,const QJsonDocument& config)
: QObject()
, _hyperion(Hyperion::getInstance())
, _hyperion(hyperion)
, _server(new QTcpServer(this))
, _openConnections()
, _priority(0)
@ -96,7 +96,7 @@ void BoblightServer::newConnection()
{
Info(_log, "new connection");
_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);
// 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 <HyperionConfig.h>
#include <hyperion/Hyperion.h>
#include <utils/Stats.h>
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0)
@ -54,10 +53,11 @@ BonjourServiceRegister::~BonjourServiceRegister()
void BonjourServiceRegister::registerService(const QString& service, const int& port)
{
_port = port;
// zeroconf $configname@$hostname:port
QString prettyName = Hyperion::getInstance()->getQJsonConfig()["general"].toObject()["name"].toString();
// TODO add name of the main instance
registerService(
BonjourRecord(prettyName+"@"+QHostInfo::localHostName()+ ":" + QString::number(port),
BonjourRecord(QHostInfo::localHostName()+ ":" + QString::number(port),
service,
QString()
),

View File

@ -117,6 +117,6 @@ void BonjourServiceResolver::bonjourResolveReply(DNSServiceRef sdRef, DNSService
void BonjourServiceResolver::finishConnect(const QHostInfo &hostInfo)
{
emit bonjourRecordResolved(hostInfo, bonjourPort);
emit bonjourRecordResolved(hostInfo, bonjourPort);
QMetaObject::invokeMethod(this, "cleanupResolve", Qt::QueuedConnection);
}

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)
# 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()));
// 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
PyObject_SetAttrString(module, "args", EffectModule::json2python(_args));

View File

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

View File

@ -7,16 +7,15 @@
// protoserver includes
#include <flatbufserver/FlatBufferConnection.h>
FlatBufferConnection::FlatBufferConnection(const QString & address) :
_socket(),
_skipReply(false),
_prevSocketState(QAbstractSocket::UnconnectedState),
_log(Logger::getInstance("FLATBUFCONNECTION"))
{
FlatBufferConnection::FlatBufferConnection(const QString & address)
: _socket()
, _prevSocketState(QAbstractSocket::UnconnectedState)
, _log(Logger::getInstance("FLATBUFCONNECTION"))
{
QStringList parts = address.split(":");
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];
@ -24,19 +23,17 @@ FlatBufferConnection::FlatBufferConnection(const QString & address) :
_port = parts[1].toUShort(&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);
connectToHost();
// start the connection timer
_timer.setInterval(5000);
_timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()));
connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData()));
connect(&_timer, &QTimer::timeout, this, &FlatBufferConnection::connectToHost);
_timer.start();
}
@ -48,48 +45,43 @@ FlatBufferConnection::~FlatBufferConnection()
void FlatBufferConnection::readData()
{
qint64 bytesAvail;
while((bytesAvail = _socket.bytesAvailable()))
_receiveBuffer += _socket.readAll();
// check if we can read a header
while(_receiveBuffer.size() >= 4)
{
// ignore until we get 4 bytes.
if (bytesAvail < 4) {
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if((uint32_t) _receiveBuffer.size() < messageSize + 4) return;
// 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;
}
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);
Error(_log, "Unable to parse 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)
@ -191,24 +183,22 @@ bool FlatBufferConnection::parseReply(const flatbuf::HyperionReply *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());
}
else
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply->error()->str());
}
else
{
success = true;
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
}
else
{
success = true;
}
break;
}
case flatbuf::Type_VIDEO:

View File

@ -6,10 +6,6 @@
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
FlatBufferServer::FlatBufferServer(const QJsonDocument& config, QObject* parent)
: QObject(parent)
, _server(new QTcpServer(this))
@ -28,7 +24,6 @@ FlatBufferServer::~FlatBufferServer()
void FlatBufferServer::initServer()
{
qDebug()<<"Thread in InitServer is"<<this->thread();
connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection);
// apply config
@ -37,7 +32,6 @@ void FlatBufferServer::initServer()
void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{
qDebug()<<"Thread in handleSettingsUpdate is"<<this->thread();
if(type == settings::FLATBUFSERVER)
{
const QJsonObject& obj = config.object();
@ -60,7 +54,6 @@ void FlatBufferServer::handleSettingsUpdate(const settings::type& type, const QJ
void FlatBufferServer::newConnection()
{
qDebug()<<"Thread in newConnection is"<<this->thread();
while(_server->hasPendingConnections())
{
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);
// Keep compiler happy in 'release' mode
(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);
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
setWidthHeight(width, height);
}
@ -55,11 +62,12 @@ void DispmanxFrameGrabber::freeResources()
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
uint32_t vc_nativeImageHandle;
_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
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
return true;
}
return false;
}
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)
, _grabber(grabWidth, grabHeight)
{
setImageProcessorEnabled(false);
}
void DispmanxWrapper::action()

View File

@ -82,7 +82,14 @@ void OsxFrameGrabber::setDisplayIndex(int index)
}
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));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -55,9 +55,9 @@ bool ComponentRegister::setHyperionEnable(const bool& state)
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)

View File

@ -24,12 +24,13 @@ Grabber::~Grabber()
void Grabber::setEnabled(bool enable)
{
Info(_log,"Capture interface is now %s", enable ? "enabled" : "disabled");
_enabled = enable;
}
void Grabber::setVideoMode(VideoMode mode)
{
Debug(_log,"setvideomode %d", mode);
Debug(_log,"Set videomode to %d", mode);
_videoMode = mode;
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
if (width>0 && height>0)
if ( (width>0 && height>0) && (_width != width || _height != 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);
return;
return false;
}
Debug(_log, "Set new width: %d, height: %d for capture", width, height);
_width = width;
_height = height;
return true;
}
return false;
}

View File

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

View File

@ -47,6 +47,9 @@
// CaptureControl (Daemon capture)
#include <hyperion/CaptureCont.h>
// Boblight
#include <boblightserver/BoblightServer.h>
Hyperion* Hyperion::_hyperion = nullptr;
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();
// initialize leddevices
const QJsonObject ledDevice = getSetting(settings::DEVICE).object();
QJsonObject ledDevice = getSetting(settings::DEVICE).object();
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
_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)
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()
@ -178,6 +186,7 @@ void Hyperion::freeObjects(bool emitCloseSignal)
}
// delete components on exit of hyperion core
delete _boblightServer;
delete _captureCont;
delete _effectEngine;
//delete _deviceSmooth;
@ -249,7 +258,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
else if(type == settings::DEVICE)
{
_lockUpdate = true;
const QJsonObject dev = config.object();
QJsonObject dev = config.object();
// handle hwLedCount update
_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount());
@ -281,7 +290,7 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
_deviceSmooth->startTimerDelayed();
_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();
}
@ -421,6 +430,11 @@ const bool Hyperion::setInputImage(const int priority, const Image<ColorRgb>& im
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)
{
// 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
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->process(image, _ledBuffer);

View File

@ -228,7 +228,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
}
_currentConfigId = cfg;
//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;
}

View File

@ -240,6 +240,12 @@ const bool PriorityMuxer::setInputImage(const int priority, const Image<ColorRgb
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)
{
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))

View File

@ -133,8 +133,6 @@ SettingsManager::~SettingsManager()
const QJsonDocument SettingsManager::getSetting(const settings::type& type)
{
//return _sTable->getSettingsRecord(settings::typeToString(type));
QString key = settings::typeToString(type);
if(_qconfig[key].isObject())
return QJsonDocument(_qconfig[key].toObject());
@ -168,6 +166,23 @@ const bool SettingsManager::saveSettings(QJsonObject config, const bool& correct
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
_qconfig = config;

View File

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

View File

@ -16,6 +16,7 @@
<file alias="schema-forwarder.json">schema/schema-forwarder.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-flatbufServer.json">schema/schema-flatbufServer.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-webConfig.json">schema/schema-webConfig.json</file>

View File

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

View File

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

View File

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

View File

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

View File

@ -5,11 +5,8 @@
#include <jsonserver/JsonServer.h>
#include "JsonClientConnection.h"
// hyperion include
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
// bonjour include
#include <bonjour/bonjourserviceregister.h>
#include <hyperion/ComponentRegister.h>
// qt includes
#include <QTcpServer>
@ -20,27 +17,16 @@
JsonServer::JsonServer(const QJsonDocument& config)
: QObject()
, _server(new QTcpServer(this))
, _hyperion(Hyperion::getInstance())
, _openConnections()
, _log(Logger::getInstance("JSONSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{
Debug(_log, "Created instance");
// Set trigger for incoming connections
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
handleSettingsUpdate(settings::JSONSERVER, config);
// set initial state of forwarding
componentStateChanged(hyperion::COMP_FORWARDER, _componentRegister->isComponentEnabled(hyperion::COMP_FORWARDER));
}
JsonServer::~JsonServer()
@ -64,7 +50,13 @@ void JsonServer::start()
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);
}
}
@ -123,38 +115,6 @@ void JsonServer::closedConnection(void)
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)
{
// serialize message

View File

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

View File

@ -9,9 +9,6 @@
#include <QStringList>
#include <QString>
// Hyperion includes
#include <hyperion/Hyperion.h>
//Utils includes
#include <utils/VideoMode.h>
@ -19,6 +16,8 @@
#include "message.pb.h"
#include "protoserver/ProtoConnection.h"
class Hyperion;
///
/// The Connection object created by a ProtoServer when a new connection is establshed
///

View File

@ -3,10 +3,9 @@
// qt incl
#include <QTcpServer>
#include <QJsonObject>
// project includes
#include <hyperion/Hyperion.h>
#include <hyperion/MessageForwarder.h>
#include <protoserver/ProtoServer.h>
#include "protoserver/ProtoConnection.h"
#include "ProtoClientConnection.h"
@ -15,30 +14,13 @@
ProtoServer::ProtoServer(const QJsonDocument& config)
: QObject()
, _hyperion(Hyperion::getInstance())
, _server(new QTcpServer(this))
, _openConnections()
, _log(Logger::getInstance("PROTOSERVER"))
, _componentRegister( & _hyperion->getComponentRegister())
{
Debug(_log,"Instance created");
connect( _server, SIGNAL(newConnection()), this, SLOT(newConnection()));
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()
@ -46,9 +28,6 @@ ProtoServer::~ProtoServer()
foreach (ProtoClientConnection * connection, _openConnections) {
delete connection;
}
while (!_proxy_connections.isEmpty())
delete _proxy_connections.takeFirst();
}
void ProtoServer::start()
@ -65,7 +44,13 @@ void ProtoServer::start()
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);
}
}
@ -110,37 +95,11 @@ void ProtoServer::newConnection()
// register slot for cleaning up after the connection closed
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
// register forward signal for video mode
connect(this, SIGNAL(videoMode(VideoMode)), connection, SLOT(setVideoMode(VideoMode)));
//connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
}
}
}
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)
{
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)
# which may be required when it is not includes by the (cross-) compiler by default.

View File

@ -1,24 +1,21 @@
// project includes
#include <udplistener/UDPListener.h>
// hyperion includes
#include <hyperion/Hyperion.h>
// bonjour includes
#include <bonjour/bonjourserviceregister.h>
// hyperion util includes
#include "utils/ColorRgb.h"
// hyperion includes
#include "HyperionConfig.h"
// qt includes
#include <QUdpSocket>
#include <QJsonObject>
using namespace hyperion;
UDPListener::UDPListener(const QJsonDocument& config) :
QObject(),
_hyperion(Hyperion::getInstance()),
_server(new QUdpSocket(this)),
_openConnections(),
_priority(0),
_timeout(0),
_log(Logger::getInstance("UDPLISTENER")),
@ -26,10 +23,6 @@ UDPListener::UDPListener(const QJsonDocument& config) :
_listenPort(0)
{
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
handleSettingsUpdate(settings::UDPLISTENER, config);
@ -40,7 +33,6 @@ UDPListener::~UDPListener()
// clear the current channel
stop();
delete _server;
_hyperion->clear(_priority);
}
@ -67,12 +59,17 @@ void UDPListener::start()
WarningIf( ! joinGroupOK, _log, "Multicast failed");
}
_isActive = true;
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
if(_bonjourService == nullptr)
if(_serviceRegister == nullptr)
{
_bonjourService = new BonjourServiceRegister();
_bonjourService->registerService("_hyperiond-udp._udp", _listenPort);
_serviceRegister = new BonjourServiceRegister(this);
_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();
_isActive = false;
Info(_log, "Stopped");
_hyperion->clear(_priority);
_hyperion->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
emit clearGlobalPriority(_priority, hyperion::COMP_UDPLISTENER);
}
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)
{
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];
rgb.red = datagram->at(ledIndex*3+0);
rgb.green = datagram->at(ledIndex*3+1);
rgb.blue = datagram->at(ledIndex*3+2);
}
// TODO provide a setInput with origin arg to overwrite senders smarter
_hyperion->registerInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString()));
_hyperion->setInput(_priority, _ledColors, _timeout);
emit registerGlobalInput(_priority, hyperion::COMP_UDPLISTENER, QString("UDPListener@%1").arg(sender->toString()));
emit setGlobalInput(_priority, _ledColors, _timeout);
}
void UDPListener::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)

View File

@ -13,11 +13,15 @@
#include <QDir>
#include <QDateTime>
Stats::Stats()
Stats* Stats::instance = nullptr;
Stats::Stats(const QJsonObject& config)
: QObject()
, _log(Logger::getInstance("STATS"))
, _hyperion(Hyperion::getInstance())
{
Stats::instance = this;
// generate hash
foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
{
@ -38,8 +42,31 @@ Stats::Stats()
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
QJsonObject config = _hyperion->getQJsonConfig();
SysInfo::HyperionSysInfo data = SysInfo::get();
QJsonObject system;
@ -63,25 +90,6 @@ Stats::Stats()
QJsonDocument doc(system);
_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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,21 @@
#include "webserver/WebServer.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/bonjourrecord.h>
#include <QFileInfo>
// utils includes
#include <utils/NetUtils.h>
WebServer::WebServer(const QJsonDocument& config, QObject * parent)
: QObject(parent)
, _log(Logger::getInstance("WEBSERVER"))
, _hyperion(Hyperion::getInstance())
, _server(new QtHttpServer (this))
{
_server->setServerName (QStringLiteral ("Hyperion Webserver"));
@ -21,7 +25,7 @@ WebServer::WebServer(const QJsonDocument& config, QObject * parent)
connect (_server, &QtHttpServer::error, this, &WebServer::onServerError);
// create StaticFileServing
_staticFileServing = new StaticFileServing (_hyperion, this);
_staticFileServing = new StaticFileServing (this);
connect(_server, &QtHttpServer::requestNeedsReply, _staticFileServing, &StaticFileServing::onRequestNeedsReply);
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());
BonjourServiceRegister *bonjourRegister_http = new BonjourServiceRegister();
bonjourRegister_http->registerService("_hyperiond-http._tcp", port);
if(_serviceRegister == nullptr)
{
_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 () {
@ -57,10 +70,8 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
{
const QJsonObject& obj = config.object();
bool webconfigEnable = obj["enable"].toBool(true);
_baseUrl = obj["document_root"].toString(WEBSERVER_DEFAULT_PATH);
if ( (_baseUrl != ":/webconfig") && !_baseUrl.trimmed().isEmpty())
{
QFileInfo info(_baseUrl);
@ -81,10 +92,10 @@ void WebServer::handleSettingsUpdate(const settings::type& type, const QJsonDocu
_port = obj["port"].toInt(WEBSERVER_DEFAULT_PORT);
stop();
}
if ( webconfigEnable )
{
start();
}
// eval if the port is available, will be incremented if not
NetUtils::portAvailable(_port, _log);
start();
}
}

View File

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

View File

@ -56,10 +56,9 @@ int main(int argc, char** argv)
// create the option parser and initialize all parameters
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<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 & 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)");
@ -109,7 +108,6 @@ int main(int argc, char** argv)
// initialize the grabber
V4L2Grabber grabber(
argDevice.value(parser),
argInput.getInt(parser),
argVideoStandard.switchValue(parser),
argPixelFormat.switchValue(parser),
std::max(1, argSizeDecimation.getInt(parser)));

View File

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

View File

@ -50,4 +50,7 @@ private:
X11Grabber _grabber;
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}/..)
add_executable(hyperiond
@ -15,9 +15,9 @@ target_link_libraries(hyperiond
hyperion
effectengine
jsonserver
boblightserver
udplistener
protoserver
flatbufserver
webserver
bonjour
python

View File

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

View File

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

View File

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