Merge pull request #539 from Paulchen-Panther/BugFixes2

Improvements ...
This commit is contained in:
Rick164 2019-04-02 19:34:11 +02:00 committed by GitHub
commit 908b82f8bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 1083 additions and 104 deletions

5
.gitmodules vendored
View File

@ -5,3 +5,8 @@
[submodule "dependencies/external/flatbuffers"]
path = dependencies/external/flatbuffers
url = https://github.com/google/flatbuffers
branch = master
[submodule "dependencies/external/protobuf"]
path = dependencies/external/protobuf
url = https://github.com/hyperion-project/protobuf.git
branch = master

View File

@ -1,3 +1,11 @@
linux: &linux
os: linux
dist: trusty
services:
- docker
osx: &osx
os: osx
cache:
- ccache
- directories:
@ -5,27 +13,48 @@ cache:
notifications:
email: false
language: cpp
services:
- docker
matrix:
include:
- os: linux
dist: trusty
env:
- DOCKER_TAG=ubuntu1604
- DOCKER_NAME="Ubuntu 16.04"
- os: linux
dist: trusty
env:
- DOCKER_TAG=cross-qemu-rpistretch
- DOCKER_NAME="Raspberry Pi"
- os: osx
osx_image: xcode8.3
env:
- HOMEBREW_CACHE=$HOME/brew-cache
before_install:
- ./.travis/travis_install.sh
jobs:
include:
- <<: *linux
name: "AMD64 (x64)"
env:
- DOCKER_TAG=amd64
- DOCKER_NAME="Debian Stretch (AMD64)"
- <<: *linux
name: "i386 (x86)"
env:
- DOCKER_TAG=i386
- DOCKER_NAME="Debian Stretch (i386)"
- <<: *linux
name: "ARMv6hf (Raspberry Pi v1 & ZERO)"
env:
- DOCKER_TAG=armv6hf
- DOCKER_NAME="Debian Stretch (Raspberry Pi v1 & ZERO)"
- PLATFORM="rpi"
- <<: *linux
name: "ARMv7hf (Raspberry Pi 2 & 3)"
env:
- DOCKER_TAG=armv7hf
- DOCKER_NAME="Debian Stretch (Raspberry Pi 2 & 3)"
- PLATFORM="rpi"
- <<: *linux
name: "ARMv8 (Generic AARCH64)"
env:
- DOCKER_TAG=aarch64
- DOCKER_NAME="ARMv8 (Generic AARCH64)"
- PLATFORM="amlogic"
- <<: *osx
osx_image: xcode8.3
name: "macOS 10.12 (Xcode 8.3.3)"
env:
- HOMEBREW_CACHE=$HOME/brew-cache
script:
- ./.travis/travis_build.sh
after_success:
- ./.travis/travis_deploy.sh

View File

@ -3,7 +3,9 @@
# for executing in non travis environment
[ -z "$TRAVIS_OS_NAME" ] && TRAVIS_OS_NAME="$(uname -s | tr '[:upper:]' '[:lower:]')"
PLATFORM=x86
if [ -z "${PLATFORM}" ]; then
PLATFORM=x86
fi
BUILD_TYPE=Debug
PACKAGES=""
@ -23,10 +25,11 @@ echo "compile jobs: ${JOBS:=4}"
[ -n "${TRAVIS_TAG:-}" ] && BUILD_TYPE=Release
# Determine package creation; True for cron and tag builds
# Commented because tests are currently broken
[ "${TRAVIS_EVENT_TYPE:-}" == 'cron' ] || [ -n "${TRAVIS_TAG:-}" ] && PACKAGES=package
# Determie -dev appends to platform;
[ "${TRAVIS_EVENT_TYPE:-}" != 'cron' -a -z "${TRAVIS_TAG:-}" ] && PLATFORM=${PLATFORM}-dev
# [ "${TRAVIS_EVENT_TYPE:-}" != 'cron' -a -z "${TRAVIS_TAG:-}" ] && PLATFORM=${PLATFORM}-dev
# Build the package on osx
if [[ "$TRAVIS_OS_NAME" == 'osx' || "$TRAVIS_OS_NAME" == 'darwin' ]]
@ -48,10 +51,10 @@ then
docker run --rm \
-v "${TRAVIS_BUILD_DIR}/deploy:/deploy" \
-v "${TRAVIS_BUILD_DIR}:/source:ro" \
hyperionorg/hyperion-ci:$DOCKER_TAG \
hyperionproject/hyperion-ci:$DOCKER_TAG \
/bin/bash -c "mkdir build && cp -r /source/. /build &&
cd /build && mkdir build && cd build &&
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} .. || exit 2 &&
cmake -DPLATFORM=${PLATFORM} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} .. || exit 2 &&
make -j $(nproc) ${PACKAGES} || exit 3 &&
echo '---> Copy binaries and packages to host folder: ${TRAVIS_BUILD_DIR}/deploy' &&
cp -v /build/build/bin/h* /deploy/ 2>/dev/null || : &&

View File

@ -24,6 +24,7 @@ SET ( DEFAULT_QT ON )
SET ( DEFAULT_WS281XPWM OFF )
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
SET ( DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF )
SET ( DEFAULT_TESTS OFF )
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
@ -164,6 +165,9 @@ message(STATUS "ENABLE_PROFILER = ${ENABLE_PROFILER}")
SET ( FLATBUFFERS_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/flatbuf )
SET ( FLATBUFFERS_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/flatbuf )
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
# check all json files
FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json )
SET( JSON_FILES
@ -233,6 +237,7 @@ CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-psabi")
endif()
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

View File

@ -1,13 +1,21 @@
# With Docker
If you are using [Docker](https://www.docker.com/), you can compile Hyperion inside a docker container. This keeps your system clean and with a simple script it's easy to use. Supported is also cross compilation for Raspberry Pi (Raspbian stretch)
If you are using [Docker](https://www.docker.com/), you can compile Hyperion inside a docker container. This keeps your system clean and with a simple script it's easy to use. Supported is also cross compilation for Raspberry Pi (Debian Stretch)
To compile Hyperion for Ubuntu 16.04 (x64) or higher just execute the following command
To compile Hyperion for Debain Stretch (x64 architecture) or higher just execute the following command
```
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh
```
To compile Hyperion for Raspberry Pi
To compile Hyperion for i386 architecture
```
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -t cross-qemu-rpistretch
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -t i386
```
To compile Hyperion for Raspberry Pi v1 & ZERO
```
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -t armv6hf
```
To compile Hyperion for Raspberry Pi 2 & 3
```
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -t armv7hf
```
The compiled binaries and packages will be available at the deploy folder next to the script
Note: call the script with `./docker-compile.sh -h` for more options

View File

@ -1,7 +1,7 @@
HYPERION
========
# HYPERION
[![Build Status](https://travis-ci.org/hyperion-project/hyperion.ng.svg?branch=master)](https://travis-ci.org/hyperion-project/hyperion.ng)
[![GitHub license](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/hyperion-project/hyperion.ng/master/LICENSE)
This is a pre alpha development repository for the next major version of hyperion
@ -16,6 +16,7 @@ If you want to use hyperion as 'normal user', please use [current stable version
Besides of that .... Feel free to join us! We are looking always for people who wants to participate.
--------
## About
Hyperion is an opensource 'AmbiLight' implementation with support for many LED devices and video grabbers.

View File

@ -21,6 +21,7 @@
"general_comp_UDPLISTENER" : "UDP Listener",
"general_comp_BOBLIGHTSERVER" : "Boblight Server",
"general_comp_FLATBUFSERVER" : "Flatbuffers Server",
"general_comp_PROTOSERVER" : "Protocol Buffers Server",
"general_comp_GRABBER" : "Plattform Aufnahme",
"general_comp_V4L" : "USB Aufnahme",
"general_comp_LEDDEVICE" : "LED Hardware",
@ -48,7 +49,7 @@
"dashboard_infobox_label_latesthyp" : "Aktuellste Hyperion Version:",
"dashboard_infobox_label_platform" : "Plattform:",
"dashboard_infobox_label_instance" : "Instanz:",
"dashboard_infobox_label_ports" : "Port flatbuf:",
"dashboard_infobox_label_ports" : "Ports (flat|proto):",
"dashboard_infobox_message_updatewarning" : "Eine aktuellere Version von Hyperion ist verfügbar! (V$1)",
"dashboard_infobox_message_updatesuccess" : "Du nutzt die aktuellste Version von Hyperion.",
"dashboard_infobox_label_statush" : "Hyperion Status:",
@ -169,6 +170,7 @@
"conf_network_bobl_intro" : "Boblight Empfänger",
"conf_network_udpl_intro" : "UDP Empfänger",
"conf_network_fbs_intro" : "Google Flatbuffers Empfänger. Wird genutzt für schnellen Bildempfang.",
"conf_network_proto_intro" : "Der PROTO-Port dieser Hyperion-Instanz, wird genutzt für \"Bildstreams\" (HyperionScreenCap, Kodi Addon, ...)",
"conf_network_forw_intro" : "Leite alles an eine zweite Hyperion Instanz weiter, diese kann dann mit einer anderen LED Steuerung genutzt werden",
"conf_logging_label_intro" : "Überprüfe die Meldungen im Prokotoll um zu erfahren was Hyperion gerade beschäftigt. Je nach eingestellter Protokoll-Stufe siehst du mehr oder weniger Informationen.",
"conf_logging_btn_pbupload" : "Bericht für Supportanfrage hochladen",
@ -572,6 +574,9 @@
"edt_conf_fbs_heading_title" : "Flatbuffers Server",
"edt_conf_fbs_timeout_title" : "Zeitüberschreitung",
"edt_conf_fbs_timeout_expl" : "Wenn für die angegebene Zeit keine Daten empfangen werden, wird die Komponente (vorübergehend) deaktiviert",
"edt_conf_pbs_heading_title" : "Protocol Buffers Server",
"edt_conf_pbs_timeout_title" : "Zeitüberschreitung",
"edt_conf_pbs_timeout_expl" : "Wenn für die angegebene Zeit keine Daten empfangen werden, wird die Komponente (vorübergehend) deaktiviert",
"edt_conf_bobls_heading_title" : "Boblight Server",
"edt_conf_udpl_heading_title" : "UDP Listener",
"edt_conf_udpl_address_title" : "Adresse",

View File

@ -21,6 +21,7 @@
"general_comp_UDPLISTENER" : "UDP Listener",
"general_comp_BOBLIGHTSERVER" : "Boblight Server",
"general_comp_FLATBUFSERVER" : "Flatbuffers Server",
"general_comp_PROTOSERVER" : "Protocol Buffers Server",
"general_comp_GRABBER" : "Platform Capture",
"general_comp_V4L" : "USB Capture",
"general_comp_LEDDEVICE" : "LED device",
@ -48,7 +49,7 @@
"dashboard_infobox_label_latesthyp" : "Latest Hyperion version:",
"dashboard_infobox_label_platform" : "Platform:",
"dashboard_infobox_label_instance" : "Instance:",
"dashboard_infobox_label_ports" : "Port flatbuf:",
"dashboard_infobox_label_ports" : "Ports (flat|proto):",
"dashboard_infobox_message_updatewarning" : "A newer version of Hyperion is available! ($1)",
"dashboard_infobox_message_updatesuccess" : "You run the latest version of Hyperion.",
"dashboard_infobox_label_statush" : "Hyperion status:",
@ -169,6 +170,7 @@
"conf_network_bobl_intro" : "Receiver for Boblight",
"conf_network_udpl_intro" : "Receiver for UDP",
"conf_network_fbs_intro" : "Google Flatbuffers Receiver. Used for fast image transmission.",
"conf_network_proto_intro" : "The PROTO-Port of this Hyperion instance, used for picture streams (HyperionScreenCap, Kodi Addon, ...)",
"conf_network_forw_intro" : "Forward all input to a second Hyperion instance which could be driven with another led controller",
"conf_logging_label_intro" : "Area to check log messages, depending on loglevel setting you see more or less information.",
"conf_logging_btn_pbupload" : "Upload report for support request",
@ -573,6 +575,9 @@
"edt_conf_fbs_heading_title" : "Flatbuffers Server",
"edt_conf_fbs_timeout_title" : "Timeout",
"edt_conf_fbs_timeout_expl" : "If no data are received for the given period, the component will be (soft) disabled.",
"edt_conf_pbs_heading_title" : "Protocol Buffers Server",
"edt_conf_pbs_timeout_title" : "Timeout",
"edt_conf_pbs_timeout_expl" : "If no data are received for the given period, the component will be (soft) disabled.",
"edt_conf_bobls_heading_title" : "Boblight Server",
"edt_conf_udpl_heading_title" : "UDP Listener",
"edt_conf_udpl_address_title" : "Address",

View File

@ -77,7 +77,7 @@ $(document).ready( function() {
$('#dash_leddevice').html(serverInfo.ledDevices.active);
$('#dash_currv').html(currentVersion);
$('#dash_instance').html(serverConfig.general.name);
$('#dash_ports').html(serverConfig.flatbufServer.port);
$('#dash_ports').html(serverConfig.flatbufServer.port+' | '+serverConfig.protoServer.port);
$.get( "https://raw.githubusercontent.com/hyperion-project/hyperion.ng/master/version.json", function( data ) {
parsedUpdateJSON = JSON.parse(data);

View File

@ -21,6 +21,11 @@ $(document).ready( function() {
$('#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")));
//protoserver
$('#conf_cont').append(createRow('conf_cont_proto'))
$('#conf_cont_proto').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_pbs_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#conf_cont_proto').append(createHelpTable(schema.protoServer.properties, $.i18n("edt_conf_pbs_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'));
@ -44,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_fbs_heading_title"), 'editor_container_fbserver', 'btn_submit_fbserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_pbs_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#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')
@ -76,6 +82,19 @@ $(document).ready( function() {
requestWriteConfig(conf_editor_fbs.getValue());
});
//protobuffer
conf_editor_proto = createJsonEditor('editor_container_protoserver', {
protoServer : schema.protoServer
}, true, true);
conf_editor_proto.on('change',function() {
conf_editor_proto.validate().length ? $('#btn_submit_protoserver').attr('disabled', true) : $('#btn_submit_protoserver').attr('disabled', false);
});
$('#btn_submit_protoserver').off().on('click',function() {
requestWriteConfig(conf_editor_proto.getValue());
});
//boblight
conf_editor_bobl = createJsonEditor('editor_container_boblightserver', {
boblightServer : schema.boblightServer
@ -123,6 +142,7 @@ $(document).ready( function() {
{
createHint("intro", $.i18n('conf_network_json_intro'), "editor_container_jsonserver");
createHint("intro", $.i18n('conf_network_fbs_intro'), "editor_container_fbserver");
createHint("intro", $.i18n('conf_network_proto_intro'), "editor_container_protoserver");
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

@ -156,9 +156,12 @@ $(document).ready(function() {
case "FLATBUFSERVER":
owner = $.i18n('general_comp_FLATBUFSERVER');
break;
case "PROTOSERVER":
owner = $.i18n('general_comp_PROTOSERVER');
break;
}
if(duration && compId != "GRABBER" && compId != "PROTOSERVER")
if(duration && compId != "GRABBER" && compId != "FLATBUFSERVER" && compId != "PROTOSERVER")
owner += '<br/><span style="font-size:80%; color:grey;">'+$.i18n('remote_input_duration')+' '+duration.toFixed(0)+$.i18n('edt_append_s')+'</span>';
var btn = '<button id="srcBtn'+i+'" type="button" '+btn_state+' class="btn btn-'+btn_type+' btn_input_selection" onclick="requestSetSource('+priority+');">'+btn_text+'</button>';

View File

@ -5,8 +5,8 @@ DOCKER="docker"
GIT_REPO_URL="https://github.com/hyperion-project/hyperion.ng.git"
# cmake build type
BUILD_TYPE="Release"
# the image tag at hyperionorg/hyperion-ci
BUILD_TARGET="ubuntu1604"
# the image tag at hyperionproject/hyperion-ci
BUILD_TARGET="amd64"
# build packages (.deb .zip ...)
BUILD_PACKAGES=true
# packages string inserted to cmake cmd
@ -42,8 +42,8 @@ function printHelp {
echo "########################################################
## A script to compile Hyperion inside a docker container
## Requires installed Docker: https://www.docker.com/
## Without arguments it will compile Hyperion for Ubuntu 16.04 (x64) or higher.
## Supports Raspberry Pi (armv6) cross compilation (Raspbian Stretch)
## Without arguments it will compile Hyperion for Debain Stretch (x64) or higher.
## Supports Raspberry Pi (armv6hf, armv7hf) cross compilation (Debian Stretch)
##
## Homepage: https://www.hyperion-project.org
## Forum: https://forum.hyperion-project.org
@ -51,10 +51,10 @@ echo "########################################################
# These are possible arguments to modify the script behaviour with their default values
#
# docker-compile.sh -h # Show this help message
# docker-compile.sh -t ubuntu1604 # The docker tag, one of ubuntu1604 | cross-qemu-rpistretch
# docker-compile.sh -t amd64 # The docker tag, one of amd64 | i386 | armv6hf | armv7hf
# docker-compile.sh -b Release # cmake Release or Debug build
# docker-compile.sh -p true # If true build packages with CPack
# More informations to docker tags at: https://hub.docker.com/r/hyperionorg/hyperion-ci/"
# More informations to docker tags at: https://hub.docker.com/r/hyperionproject/hyperion-ci/"
}
while getopts t:b:p:h option

View File

@ -247,6 +247,15 @@
"timeout" : 5
},
/// The configuration of the Protobuffer server which enables the Protobuffer remote interface
/// * port : Port at which the protobuffer server is started
"protoServer" :
{
"enable" : true,
"port" : 19445,
"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

View File

@ -140,6 +140,13 @@
"timeout" : 5
},
"protoServer" :
{
"enable" : true,
"port" : 19445,
"timeout" : 5
},
"boblightServer" :
{
"enable" : false,

View File

@ -9,6 +9,10 @@ if(ENABLE_WS281XPWM)
external/rpi_ws281x/rpihw.c)
endif()
#=============================================================================
# FLATBUFFER
#=============================================================================
set(USE_SYSTEM_FLATBUFFERS_LIBS ${DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS} CACHE BOOL "use flatbuffers library from system")
if (USE_SYSTEM_FLATBUFFERS_LIBS)
@ -63,3 +67,115 @@ function(compile_flattbuffer_schema SRC_FBS OUTPUT_DIR)
DEPENDS flatc)
endif()
endfunction()
#=============================================================================
# PROTOBUFFER
#=============================================================================
set(USE_SYSTEM_PROTO_LIBS ${DEFAULT_USE_SYSTEM_PROTO_LIBS} CACHE BOOL "use protobuf library from system")
if (USE_SYSTEM_PROTO_LIBS)
find_package(Protobuf REQUIRED)
if (ENABLE_AMLOGIC)
set(PROTOBUF_INCLUDE_DIRS "${Protobuf_INCLUDE_DIRS}" PARENT_SCOPE)
set(PROTOBUF_PROTOC_EXECUTABLE "${Protobuf_PROTOC_EXECUTABLE}" PARENT_SCOPE)
endif()
include_directories(${PROTOBUF_INCLUDE_DIRS})
else ()
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library")
add_subdirectory(external/protobuf)
if(CMAKE_CROSSCOMPILING)
# when crosscompiling import the protoc executable targets from a file generated by a native build
option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND")
include(${IMPORT_PROTOC})
else()
# export the protoc compiler so it can be used when cross compiling
export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake")
endif()
# define the include for the protobuf library at the parent scope
set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src")
set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE)
# define the protoc executable at the parent scope
get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION)
set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE)
endif()
message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE})
#=============================================================================
# Copyright 2009 Kitware, Inc.
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(PROTOBUF_GENERATE_CPP SRCS HDRS)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS)
foreach(DIR ${PROTOBUF_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
if(CMAKE_CROSSCOMPILING OR USE_SYSTEM_PROTO_LIBS)
set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE})
else()
set(PROTOC_DEPENDENCY protoc_compiler)
endif()
set(${SRCS})
set(${HDRS})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY}
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM
)
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()

1
dependencies/external/protobuf vendored Submodule

@ -0,0 +1 @@
Subproject commit adce8a99fdab90f290d659b6b3bf2d09b721e24a

@ -1 +1 @@
Subproject commit f580777219062568d2e43e998ecb0950deff9e99
Subproject commit 6c5ade93d1af78cd19e60ee5ecc34adfd111b186

View File

@ -41,13 +41,13 @@ private slots:
/// @brief forward system image
/// @param image The image
///
void handleSystemImage(const Image<ColorRgb>& image);
void handleSystemImage(const QString& name, const Image<ColorRgb>& image);
///
/// @brief forward v4l image
/// @param image The image
///
void handleV4lImage(const Image<ColorRgb> & image);
void handleV4lImage(const QString& name, const Image<ColorRgb> & image);
///
/// @brief Is called from _v4lInactiveTimer to set source after specific time to inactive
@ -66,10 +66,12 @@ private:
/// Reflect state of System capture and prio
bool _systemCaptEnabled;
quint8 _systemCaptPrio;
QString _systemCaptName;
QTimer* _systemInactiveTimer;
/// Reflect state of v4l capture and prio
bool _v4lCaptEnabled;
quint8 _v4lCaptPrio;
QString _v4lCaptName;
QTimer* _v4lInactiveTimer;
};

View File

@ -54,7 +54,7 @@ public:
int ret = grabber.grabFrame(_image);
if (ret >= 0)
{
emit systemImage(_image);
emit systemImage(_grabberName, _image);
return true;
}
return false;
@ -92,7 +92,7 @@ signals:
///
/// @brief Emit the final processed image
///
void systemImage(const Image<ColorRgb>& image);
void systemImage(const QString& name, const Image<ColorRgb>& image);
protected:

View File

@ -411,7 +411,7 @@ signals:
void forwardJsonMessage(QJsonObject);
/// Signal which is emitted, when a new proto image should be forwarded
void forwardProtoMessage(Image<ColorRgb>);
void forwardProtoMessage(const QString, const Image<ColorRgb>);
///
/// @brief Is emitted from clients who request a videoMode change

View File

@ -70,7 +70,7 @@ private slots:
/// @brief Forward image to all proto slaves
/// @param image The PROTO image to send
///
void forwardProtoMessage(const Image<ColorRgb> &image);
void forwardProtoMessage(const QString& name, const Image<ColorRgb> &image);
///
/// @brief Forward message to a single json slave

View File

@ -0,0 +1,67 @@
#pragma once
// util
#include <utils/Logger.h>
#include <utils/settings.h>
// qt
#include <QVector>
class QTcpServer;
class ProtoClientConnection;
///
/// @brief This class creates a TCP server which accepts connections wich can then send
/// in Protocol Buffer encoded commands. This interface to Hyperion is used by various
/// third-party applications
///
class ProtoServer : public QObject
{
Q_OBJECT
public:
ProtoServer(const QJsonDocument& config, QObject* parent = nullptr);
~ProtoServer();
public slots:
///
/// @brief Handle settings update
/// @param type The type from enum
/// @param config The configuration
///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
void initServer();
private slots:
///
/// @brief Is called whenever a new socket wants to connect
///
void newConnection();
///
/// @brief is called whenever a client disconnected
///
void clientDisconnected();
private:
///
/// @brief Start the server with current _port
///
void startServer();
///
/// @brief Stop server
///
void stopServer();
private:
QTcpServer* _server;
Logger* _log;
int _timeout;
quint16 _port;
const QJsonDocument _config;
QVector<ProtoClientConnection*> _openConnections;
};

View File

@ -84,7 +84,6 @@ private slots:
void processTheDatagram(const QByteArray * datagram, const QHostAddress * sender);
private:
/// The UDP server object
QUdpSocket * _server;

View File

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

View File

@ -29,13 +29,15 @@ public:
signals:
///
/// @brief PIPE SystemCapture images from GrabberWrapper to Hyperion class
/// @param name The name of the platform capture that is currently active
/// @param image The prepared image
///
void setSystemImage(const Image<ColorRgb>& image);
void setSystemImage(const QString& name, const Image<ColorRgb>& image);
///
/// @brief PIPE v4lCapture images from v4lCapture over HyperionDaemon to Hyperion class
/// @param name The name of the v4l capture (path) that is currently active
/// @param image The prepared image
///
void setV4lImage(const Image<ColorRgb> & image);
void setV4lImage(const QString& name, const Image<ColorRgb> & image);
};

View File

@ -29,6 +29,7 @@ enum type {
INSTCAPTURE,
NETWORK,
FLATBUFSERVER,
PROTOSERVER,
INVALID
};
@ -62,6 +63,7 @@ inline QString typeToString(const type& type)
case INSTCAPTURE: return "instCapture";
case NETWORK: return "network";
case FLATBUFSERVER: return "flatbufServer";
case PROTOSERVER: return "protoServer";
default: return "invalid";
}
}
@ -73,7 +75,7 @@ inline QString typeToString(const type& type)
///
inline type stringToType(const QString& type)
{
if (type == "backgroundEffect") return BGEFFECT;
if (type == "backgroundEffect") return BGEFFECT;
else if (type == "foregroundEffect") return FGEFFECT;
else if (type == "blackborderdetector") return BLACKBORDER;
else if (type == "boblightServer") return BOBLSERVER;
@ -94,6 +96,7 @@ inline type stringToType(const QString& type)
else if (type == "instCapture") return INSTCAPTURE;
else if (type == "network") return NETWORK;
else if (type == "flatbufServer") return FLATBUFSERVER;
else return INVALID;
else if (type == "protoServer") return PROTOSERVER;
else return INVALID;
}
};

View File

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

View File

@ -31,7 +31,7 @@ public:
/// @param timeout The timeout when a client is automatically disconnected and the priority unregistered
/// @param parent The parent
///
explicit FlatBufferClient(QTcpSocket* socket, const int &timeout, QObject *parent = nullptr);
explicit FlatBufferClient(QTcpSocket* socket, const int &timeout, QObject *parent = nullptr);
signals:
///
@ -59,12 +59,12 @@ private slots:
///
/// @brief Is called whenever the socket got new data to read
///
void readyRead();
void readyRead();
///
/// @brief Is called when the socket closed the connection, also requests thread exit
///
void disconnected();
void disconnected();
private:
///

View File

@ -62,8 +62,6 @@ void FlatBufferServer::newConnection()
FlatBufferClient *client = new FlatBufferClient(socket, _timeout, this);
// internal
connect(client, &FlatBufferClient::clientDisconnected, this, &FlatBufferServer::clientDisconnected);
// forward data
//connect(clientThread, &FlatBufferClient::);
_openConnections.append(client);
}
}

View File

@ -46,7 +46,11 @@ int FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
{
case 16: pixelFormat = PIXELFORMAT_BGR16; break;
case 24: pixelFormat = PIXELFORMAT_BGR24; break;
#ifdef ENABLE_AMLOGIC
case 32: pixelFormat = PIXELFORMAT_RGB32; break;
#else
case 32: pixelFormat = PIXELFORMAT_BGR32; break;
#endif
default:
Error(_log, "Unknown pixel format: %d bits per pixel", vinfo.bits_per_pixel);
close(_fbfd);

View File

@ -54,6 +54,9 @@ V4L2Grabber::V4L2Grabber(const QString & device
{
setPixelDecimation(pixelDecimation);
getV4Ldevices();
// init
setDeviceVideoStandard(device, videoStandard);
}
V4L2Grabber::~V4L2Grabber()

View File

@ -53,7 +53,7 @@ void V4L2Wrapper::setSignalDetectionOffset(double verticalMin, double horizontal
void V4L2Wrapper::newFrame(const Image<ColorRgb> &image)
{
emit systemImage(image);
emit systemImage(_grabberName, image);
}
void V4L2Wrapper::readError(const char* err)

View File

@ -13,8 +13,10 @@ CaptureCont::CaptureCont(Hyperion* hyperion)
: QObject()
, _hyperion(hyperion)
, _systemCaptEnabled(false)
, _systemCaptName()
, _systemInactiveTimer(new QTimer(this))
, _v4lCaptEnabled(false)
, _v4lCaptName()
, _v4lInactiveTimer(new QTimer(this))
{
// settings changes
@ -41,14 +43,24 @@ CaptureCont::~CaptureCont()
{
}
void CaptureCont::handleV4lImage(const Image<ColorRgb> & image)
void CaptureCont::handleV4lImage(const QString& name, const Image<ColorRgb> & image)
{
if(_v4lCaptName != name)
{
_hyperion->registerInput(_v4lCaptPrio, hyperion::COMP_V4L, "System", name);
_v4lCaptName = name;
}
_v4lInactiveTimer->start();
_hyperion->setInputImage(_v4lCaptPrio, image);
}
void CaptureCont::handleSystemImage(const Image<ColorRgb>& image)
void CaptureCont::handleSystemImage(const QString& name, const Image<ColorRgb>& image)
{
if(_systemCaptName != name)
{
_hyperion->registerInput(_systemCaptPrio, hyperion::COMP_GRABBER, "System", name);
_systemCaptName = name;
}
_systemInactiveTimer->start();
_hyperion->setInputImage(_systemCaptPrio, image);
}

View File

@ -210,7 +210,7 @@ void MessageForwarder::forwardJsonMessage(const QJsonObject &message)
}
}
void MessageForwarder::forwardProtoMessage(const Image<ColorRgb> &image)
void MessageForwarder::forwardProtoMessage(const QString& name, const Image<ColorRgb> &image)
{
if (_forwarder_enabled)
{

View File

@ -41,6 +41,7 @@ SettingsManager::SettingsManager(Hyperion* hyperion, const quint8& instance, con
Info(_log, "Selected configuration file: %s", QSTRING_CSTR(configFile));
QJsonSchemaChecker schemaCheckerT;
schemaCheckerT.setSchema(schemaJson);
if(!JsonUtils::readFile(configFile, _qconfig, _log))
throw std::runtime_error("Failed to load config!");
@ -96,6 +97,7 @@ SettingsManager::SettingsManager(const quint8& instance, const QString& configFi
Info(_log, "Selected configuration file: %s", QSTRING_CSTR(configFile));
QJsonSchemaChecker schemaCheckerT;
schemaCheckerT.setSchema(schemaJson);
if(!JsonUtils::readFile(configFile, _qconfig, _log))
throw std::runtime_error("Failed to load config!");

View File

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

View File

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

@ -0,0 +1,36 @@
{
"type" : "object",
"required" : true,
"title" : "edt_conf_pbs_heading_title",
"properties" :
{
"enable" :
{
"type" : "boolean",
"required" : true,
"title" : "edt_conf_general_enable_title",
"default" : true,
"propertyOrder" : 1
},
"port" :
{
"type" : "integer",
"required" : true,
"title" : "edt_conf_general_port_title",
"minimum" : 1024,
"maximum" : 65535,
"default" : 19445
},
"timeout" :
{
"type" : "integer",
"required" : true,
"title" : "edt_conf_pbs_timeout_title",
"append" : "edt_append_s",
"minimum" : 1,
"default" : 5,
"propertyOrder" : 3
}
},
"additionalProperties" : false
}

View File

@ -0,0 +1,44 @@
# Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${PROTOBUF_INCLUDE_DIRS}
)
set(ProtoServer_PROTOS ${CURRENT_SOURCE_DIR}/message.proto )
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS ${ProtoServer_PROTOS} )
### Split protoclient from protoserver as protoserver relates to HyperionDaemon and standalone capture binarys can't link to it
add_library(protoclient
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
${ProtoServer_PROTO_SRCS}
${ProtoServer_PROTO_HDRS}
)
add_library(protoserver
${CURRENT_HEADER_DIR}/ProtoServer.h
${CURRENT_SOURCE_DIR}/ProtoServer.cpp
)
# disable warnings for auto generated proto files, we can't change the files ....
SET_SOURCE_FILES_PROPERTIES ( ${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_HDRS} ${ProtoServer_PROTOS} PROPERTIES COMPILE_FLAGS -w )
target_link_libraries(protoclient
hyperion
hyperion-utils
protobuf
Qt5::Gui
)
target_link_libraries(protoserver
hyperion
hyperion-utils
protoclient
Qt5::Gui
)

View File

@ -0,0 +1,238 @@
// project includes
#include "ProtoClientConnection.h"
// qt
#include <QTcpSocket>
#include <QHostAddress>
#include <QTimer>
#include <QRgb>
// Hyperion includes
#include <hyperion/Hyperion.h>
ProtoClientConnection::ProtoClientConnection(QTcpSocket* socket, const int &timeout, QObject *parent)
: QObject(parent)
, _log(Logger::getInstance("PROTOSERVER"))
, _socket(socket)
, _clientAddress(socket->peerAddress().toString())
, _timeoutTimer(new QTimer(this))
, _timeout(timeout * 1000)
, _priority()
, _hyperion(Hyperion::getInstance())
{
// timer setup
_timeoutTimer->setSingleShot(true);
_timeoutTimer->setInterval(_timeout);
connect(_timeoutTimer, &QTimer::timeout, this, &ProtoClientConnection::forceClose);
// connect socket signals
connect(_socket, &QTcpSocket::readyRead, this, &ProtoClientConnection::readyRead);
connect(_socket, &QTcpSocket::disconnected, this, &ProtoClientConnection::disconnected);
}
void ProtoClientConnection::readyRead()
{
_receiveBuffer += _socket->readAll();
// check if we can read a message size
if (_receiveBuffer.size() <= 4)
{
return;
}
// read the message size
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
{
return;
}
// read a message
proto::HyperionRequest message;
if (!message.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
{
sendErrorReply("Unable to parse message");
}
// handle the message
handleMessage(message);
// remove message data from buffer
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
}
void ProtoClientConnection::forceClose()
{
_socket->close();
}
void ProtoClientConnection::disconnected()
{
Debug(_log, "Socket Closed");
_socket->deleteLater();
_hyperion->clear(_priority);
emit clientDisconnected();
}
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
{
switch (message.command())
{
case proto::HyperionRequest::COLOR:
if (!message.HasExtension(proto::ColorRequest::colorRequest))
{
sendErrorReply("Received COLOR command without ColorRequest");
break;
}
handleColorCommand(message.GetExtension(proto::ColorRequest::colorRequest));
break;
case proto::HyperionRequest::IMAGE:
if (!message.HasExtension(proto::ImageRequest::imageRequest))
{
sendErrorReply("Received IMAGE command without ImageRequest");
break;
}
handleImageCommand(message.GetExtension(proto::ImageRequest::imageRequest));
break;
case proto::HyperionRequest::CLEAR:
if (!message.HasExtension(proto::ClearRequest::clearRequest))
{
sendErrorReply("Received CLEAR command without ClearRequest");
break;
}
handleClearCommand(message.GetExtension(proto::ClearRequest::clearRequest));
break;
case proto::HyperionRequest::CLEARALL:
handleClearallCommand();
break;
default:
handleNotImplemented();
}
}
void ProtoClientConnection::handleColorCommand(const proto::ColorRequest &message)
{
// extract parameters
int priority = message.priority();
int duration = message.has_duration() ? message.duration() : -1;
ColorRgb color;
color.red = qRed(message.rgbcolor());
color.green = qGreen(message.rgbcolor());
color.blue = qBlue(message.rgbcolor());
// make sure the prio is registered before setColor()
if(priority != _priority)
{
_hyperion->clear(_priority);
_hyperion->registerInput(priority, hyperion::COMP_PROTOSERVER, "Proto@"+_clientAddress);
_priority = priority;
}
// set output
_hyperion->setColor(_priority, color, duration);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleImageCommand(const proto::ImageRequest &message)
{
// extract parameters
int priority = message.priority();
int duration = message.has_duration() ? message.duration() : -1;
int width = message.imagewidth();
int height = message.imageheight();
const std::string & imageData = message.imagedata();
// make sure the prio is registered before setInput()
if(priority != _priority)
{
_hyperion->clear(_priority);
_hyperion->registerInput(priority, hyperion::COMP_PROTOSERVER, "Proto@"+_clientAddress);
_priority = priority;
}
// check consistency of the size of the received data
if ((int) imageData.size() != width*height*3)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
// create ImageRgb
Image<ColorRgb> image(width, height);
memcpy(image.memptr(), imageData.c_str(), imageData.size());
_hyperion->setInputImage(_priority, image, duration);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &message)
{
// extract parameters
int priority = message.priority();
// clear priority
_hyperion->clear(priority);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleClearallCommand()
{
// clear priority
_hyperion->clearall();
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleNotImplemented()
{
sendErrorReply("Command not implemented");
}
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
{
std::string serializedReply = message.SerializeAsString();
uint32_t size = serializedReply.size();
uint8_t sizeData[] = {uint8_t(size >> 24), uint8_t(size >> 16), uint8_t(size >> 8), uint8_t(size)};
_socket->write((const char *) sizeData, sizeof(sizeData));
_socket->write(serializedReply.data(), serializedReply.length());
_socket->flush();
}
void ProtoClientConnection::sendSuccessReply()
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(true);
// send reply
sendMessage(reply);
}
void ProtoClientConnection::sendErrorReply(const std::string &error)
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(false);
reply.set_error(error);
// send reply
sendMessage(reply);
}

View File

@ -0,0 +1,135 @@
#pragma once
// util
#include <utils/Logger.h>
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/Components.h>
// protobuffer PROTO
#include "message.pb.h"
class QTcpSocket;
class QTimer;
class Hyperion;
namespace proto {
class HyperionRequest;
}
///
/// The Connection object created by a ProtoServer when a new connection is established
///
class ProtoClientConnection : public QObject
{
Q_OBJECT
public:
///
/// @brief Construct the client
/// @param socket The socket
/// @param timeout The timeout when a client is automatically disconnected and the priority unregistered
/// @param parent The parent
///
explicit ProtoClientConnection(QTcpSocket* socket, const int &timeout, QObject *parent);
signals:
///
/// @brief Emits whenever the client disconnected
///
void clientDisconnected();
public slots:
///
/// @brief close the socket and call disconnected()
///
void forceClose();
private slots:
///
/// @brief Is called whenever the socket got new data to read
///
void readyRead();
///
/// @brief Is called when the socket closed the connection, also requests thread exit
///
void disconnected();
private:
///
/// Handle an incoming Proto message
///
/// @param message the incoming message as string
///
void handleMessage(const proto::HyperionRequest &message);
///
/// Handle an incoming Proto Color message
///
/// @param message the incoming message
///
void handleColorCommand(const proto::ColorRequest & message);
///
/// Handle an incoming Proto Image message
///
/// @param message the incoming message
///
void handleImageCommand(const proto::ImageRequest & message);
///
/// Handle an incoming Proto Clear message
///
/// @param message the incoming message
///
void handleClearCommand(const proto::ClearRequest & message);
///
/// Handle an incoming Proto Clearall message
///
void handleClearallCommand();
///
/// Handle an incoming Proto message of unknown type
///
void handleNotImplemented();
///
/// Send a message to the connected client
///
/// @param message The Proto message to send
///
void sendMessage(const google::protobuf::Message &message);
///
/// Send a standard reply indicating success
///
void sendSuccessReply();
///
/// Send an error message back to the client
///
/// @param error String describing the error
///
void sendErrorReply(const std::string & error);
private:
Logger*_log;
/// The TCP-Socket that is connected tot the Proto-client
QTcpSocket* _socket;
/// address of client
const QString _clientAddress;
QTimer*_timeoutTimer;
int _timeout;
int _priority;
/// Link to Hyperion for writing led-values to a priority channel
Hyperion* _hyperion;
/// The buffer used for reading data from the socket
QByteArray _receiveBuffer;
};

View File

@ -0,0 +1,104 @@
#include <protoserver/ProtoServer.h>
#include "ProtoClientConnection.h"
// qt
#include <QJsonObject>
#include <QTcpServer>
#include <QTcpSocket>
ProtoServer::ProtoServer(const QJsonDocument& config, QObject* parent)
: QObject(parent)
, _server(new QTcpServer(this))
, _log(Logger::getInstance("PROTOSERVER"))
, _timeout(5000)
, _config(config)
{
}
ProtoServer::~ProtoServer()
{
stopServer();
delete _server;
}
void ProtoServer::initServer()
{
connect(_server, &QTcpServer::newConnection, this, &ProtoServer::newConnection);
// apply config
handleSettingsUpdate(settings::PROTOSERVER, _config);
}
void ProtoServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{
if(type == settings::PROTOSERVER)
{
const QJsonObject& obj = config.object();
quint16 port = obj["port"].toInt(19445);
// port check
if(_server->serverPort() != port)
{
stopServer();
_port = port;
}
// new timeout just for new connections
_timeout = obj["timeout"].toInt(5000);
// enable check
obj["enable"].toBool(true) ? startServer() : stopServer();
}
}
void ProtoServer::newConnection()
{
while(_server->hasPendingConnections())
{
if(QTcpSocket * socket = _server->nextPendingConnection())
{
Debug(_log, "New connection from %s", QSTRING_CSTR(socket->peerAddress().toString()));
ProtoClientConnection * client = new ProtoClientConnection(socket, _timeout, this);
// internal
connect(client, &ProtoClientConnection::clientDisconnected, this, &ProtoServer::clientDisconnected);
_openConnections.append(client);
}
}
}
void ProtoServer::clientDisconnected()
{
ProtoClientConnection* client = qobject_cast<ProtoClientConnection*>(sender());
client->deleteLater();
_openConnections.removeAll(client);
}
void ProtoServer::startServer()
{
if(!_server->isListening())
{
if(!_server->listen(QHostAddress::Any, _port))
{
Error(_log,"Failed to bind port %d", _port);
}
else
{
Info(_log,"Started on port %d", _port);
}
}
}
void ProtoServer::stopServer()
{
if(_server->isListening())
{
// close client connections
for(const auto& client : _openConnections)
{
client->forceClose();
}
_server->close();
Info(_log, "Stopped");
}
}

View File

@ -0,0 +1,80 @@
package proto;
message HyperionRequest {
enum Command {
COLOR = 1;
IMAGE = 2;
CLEAR = 3;
CLEARALL = 4;
}
// command specification
required Command command = 1;
// extensions to define all specific requests
extensions 10 to 100;
}
message ColorRequest {
extend HyperionRequest {
optional ColorRequest colorRequest = 10;
}
// priority to use when setting the color
required int32 priority = 1;
// integer value containing the rgb color (0x00RRGGBB)
required int32 RgbColor = 2;
// duration of the request (negative results in infinite)
optional int32 duration = 3;
}
message ImageRequest {
extend HyperionRequest {
optional ImageRequest imageRequest = 11;
}
// priority to use when setting the image
required int32 priority = 1;
// width of the image
required int32 imagewidth = 2;
// height of the image
required int32 imageheight = 3;
// image data
required bytes imagedata = 4;
// duration of the request (negative results in infinite)
optional int32 duration = 5;
}
message ClearRequest {
extend HyperionRequest {
optional ClearRequest clearRequest = 12;
}
// priority which need to be cleared
required int32 priority = 1;
}
message HyperionReply {
enum Type {
REPLY = 1;
VIDEO = 2;
}
// Identifies which field is filled in.
required Type type = 1;
// flag indication success or failure
optional bool success = 2;
// string indicating the reason for failure (if applicable)
optional string error = 3;
// Proto Messages for video mode
optional int32 video = 4;
}

View File

@ -5,6 +5,7 @@
#include <bonjour/bonjourserviceregister.h>
// hyperion includes
#include <hyperion/Hyperion.h>
#include "HyperionConfig.h"
// qt includes
@ -22,6 +23,9 @@ UDPListener::UDPListener(const QJsonDocument& config) :
_isActive(false),
_listenPort(0)
{
// listen for component change
connect(Hyperion::getInstance(), &Hyperion::componentStateChanged, this, &UDPListener::componentStateChanged);
// init
handleSettingsUpdate(settings::UDPLISTENER, config);
}
@ -70,6 +74,8 @@ void UDPListener::start()
_serviceRegister->registerService("_hyperiond-udp._udp", _listenPort);
}
}
Hyperion::getInstance()->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
}
void UDPListener::stop()
@ -80,7 +86,7 @@ void UDPListener::stop()
_server->close();
_isActive = false;
Info(_log, "Stopped");
// emit clearGlobalPriority(_priority, hyperion::COMP_UDPLISTENER);
Hyperion::getInstance()->getComponentRegister().componentStateChanged(COMP_UDPLISTENER, _isActive);
}
void UDPListener::componentStateChanged(const hyperion::Components component, bool enable)

View File

@ -1,4 +1,5 @@
find_package(PythonLibs 3.4 REQUIRED)
find_package(Qt5Widgets REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}/..)
add_executable(hyperiond
@ -16,6 +17,7 @@ target_link_libraries(hyperiond
jsonserver
udplistener
flatbufserver
protoserver
webserver
bonjour
ssdp
@ -66,6 +68,8 @@ if (ENABLE_QT)
target_link_libraries(hyperiond qt-grabber)
endif ()
target_link_libraries(hyperiond Qt5::Widgets)
install ( TARGETS hyperiond DESTINATION "share/hyperion/bin/" COMPONENT "${PLATFORM}" )
install ( DIRECTORY ${CMAKE_SOURCE_DIR}/bin/service DESTINATION "share/hyperion/" COMPONENT "${PLATFORM}" )
install ( FILES ${CMAKE_SOURCE_DIR}/effects/readme.txt DESTINATION "share/hyperion/effects" COMPONENT "${PLATFORM}" )

View File

@ -26,9 +26,12 @@
#include <HyperionConfig.h> // Required to determine the cmake options
#include "hyperiond.h"
// FlatBufferServer
// Flatbuffer Server
#include <flatbufserver/FlatBufferServer.h>
// Protobuffer Server
#include <protoserver/ProtoServer.h>
// bonjour browser
#include <bonjour/bonjourbrowserwrapper.h>
@ -145,6 +148,8 @@ void HyperionDaemon::freeObjects()
delete _jsonServer;
_flatBufferServer->thread()->quit();
_flatBufferServer->thread()->wait(1000);
_protoServer->thread()->quit();
_protoServer->thread()->wait(1000);
//ssdp before webserver
_ssdp->thread()->quit();
_ssdp->thread()->wait(1000);
@ -166,17 +171,18 @@ void HyperionDaemon::freeObjects()
_v4l2Grabbers.clear();
_bonjourBrowserWrapper = nullptr;
_amlGrabber = nullptr;
_dispmanx = nullptr;
_fbGrabber = nullptr;
_osxGrabber = nullptr;
_qtGrabber = nullptr;
_flatBufferServer = nullptr;
_ssdp = nullptr;
_webserver = nullptr;
_jsonServer = nullptr;
_udpListener = nullptr;
_stats = nullptr;
_amlGrabber = nullptr;
_dispmanx = nullptr;
_fbGrabber = nullptr;
_osxGrabber = nullptr;
_qtGrabber = nullptr;
_flatBufferServer = nullptr;
_protoServer = nullptr;
_ssdp = nullptr;
_webserver = nullptr;
_jsonServer = nullptr;
_udpListener = nullptr;
_stats = nullptr;
}
void HyperionDaemon::startNetworkServices()
@ -198,6 +204,16 @@ void HyperionDaemon::startNetworkServices()
connect(this, &HyperionDaemon::settingsChanged, _flatBufferServer, &FlatBufferServer::handleSettingsUpdate);
fbThread->start();
// Create Proto server in thread
_protoServer = new ProtoServer(getSetting(settings::PROTOSERVER));
QThread* pThread = new QThread(this);
_protoServer->moveToThread(pThread);
connect( pThread, &QThread::started, _protoServer, &ProtoServer::initServer );
connect( pThread, &QThread::finished, _protoServer, &QObject::deleteLater );
connect( pThread, &QThread::finished, pThread, &QObject::deleteLater );
connect(this, &HyperionDaemon::settingsChanged, _protoServer, &ProtoServer::handleSettingsUpdate);
pThread->start();
// Create UDP listener
_udpListener = new UDPListener(getSetting(settings::UDPLISTENER));
connect(this, &HyperionDaemon::settingsChanged, _udpListener, &UDPListener::handleSettingsUpdate);
@ -411,13 +427,8 @@ void HyperionDaemon::handleSettingsUpdate(const settings::type& type, const QJso
connect(this, &HyperionDaemon::settingsChanged, grabber, &V4L2Wrapper::handleSettingsUpdate);
if (enableV4l)
{
v4lEnableCount++;
// init
grabber->setDeviceVideoStandard(grabberConfig["device"].toString("auto"), parseVideoStandard(grabberConfig["standard"].toString("no-change")));
}
_v4l2Grabbers.push_back(grabber);
#endif
}

View File

@ -63,6 +63,7 @@ class SettingsManager;
class PythonInit;
class SSDPHandler;
class FlatBufferServer;
class ProtoServer;
class HyperionDaemon : public QObject
{
@ -130,33 +131,34 @@ private:
void createGrabberX11(const QJsonObject & grabberConfig);
void createGrabberQt(const QJsonObject & grabberConfig);
Logger* _log;
BonjourBrowserWrapper* _bonjourBrowserWrapper;
PythonInit* _pyInit;
WebServer* _webserver;
JsonServer* _jsonServer;
UDPListener* _udpListener;
Logger* _log;
BonjourBrowserWrapper* _bonjourBrowserWrapper;
PythonInit* _pyInit;
WebServer* _webserver;
JsonServer* _jsonServer;
UDPListener* _udpListener;
std::vector<V4L2Wrapper*> _v4l2Grabbers;
DispmanxWrapper* _dispmanx;
X11Wrapper* _x11Grabber;
AmlogicWrapper* _amlGrabber;
FramebufferWrapper* _fbGrabber;
OsxWrapper* _osxGrabber;
QtWrapper* _qtGrabber;
Hyperion* _hyperion;
Stats* _stats;
SSDPHandler* _ssdp;
FlatBufferServer* _flatBufferServer;
DispmanxWrapper* _dispmanx;
X11Wrapper* _x11Grabber;
AmlogicWrapper* _amlGrabber;
FramebufferWrapper* _fbGrabber;
OsxWrapper* _osxGrabber;
QtWrapper* _qtGrabber;
Hyperion* _hyperion;
Stats* _stats;
SSDPHandler* _ssdp;
FlatBufferServer* _flatBufferServer;
ProtoServer* _protoServer;
unsigned _grabber_width;
unsigned _grabber_height;
unsigned _grabber_frequency;
unsigned _grabber_cropLeft;
unsigned _grabber_cropRight;
unsigned _grabber_cropTop;
unsigned _grabber_cropBottom;
int _grabber_ge2d_mode;
QString _grabber_device;
unsigned _grabber_width;
unsigned _grabber_height;
unsigned _grabber_frequency;
unsigned _grabber_cropLeft;
unsigned _grabber_cropRight;
unsigned _grabber_cropTop;
unsigned _grabber_cropBottom;
int _grabber_ge2d_mode;
QString _grabber_device;
QString _prevType;