mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Various Cleanups (#1075)
* LedDevice - Address clang findings * Fix Windows Warnings * Ensure newInput is initialised * Clean-up unused elements for Plaform Capture * Fix initialization problem and spellings * Address clang findings and spelling corrections * LedDevice clean-ups * Cleanups * Align that getLedCount is int * Have "display" as default for Grabbers * Fix config during start-up for missing elements * Framegrabber Clean-up - Remove non supported grabbers from selection, filter valid options * Typo * Framegrabber.json - Fix property numbering * Preselect active Grabbertype * Sort Grabbernames * Align options with selected element * Fix deletion of pointer to incomplete type 'BonjourBrowserWrapper' * Address macOS compile warnings * Have default layout = 1 LED only to avoid errors as in #673 * Address lgtm findings * Address finding that params passed to LedDevice discovery were not considered * Cleanups after merging with latest master * Update Changelog * Address lgtm findings * Fix comment * Test Fix * Fix Python Warning * Handle Dummy Device assignment correctly * Address delete called on non-final 'commandline::Option' that has virtual functions but non-virtual destructor * Correct that QTimer.start accepts only int * Have Release Python GIL & reset threat state chnage downward compatible * Correct format specifier * LedDevice - add assertions * Readonly DB - Fix merge issue * Smoothing - Fix wrong defaults * LedDevice - correct assertion * Show smoothing config set# in debug and related values. * Suppress error on windows, if default file is "/dev/null" * CMAKE - Allow to define QT_BASE_DIR dynamically via environment-variable * Ignore Visual Studio specific files Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
This commit is contained in:
parent
d28540a7fe
commit
efc2046ab5
4
.gitignore
vendored
4
.gitignore
vendored
@ -25,3 +25,7 @@ libsrc/flatbufserver/hyperion_request_generated.h
|
|||||||
|
|
||||||
# Kdevelop project files
|
# Kdevelop project files
|
||||||
*.kdev*
|
*.kdev*
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017/2019 cache/options directory
|
||||||
|
.vs/
|
||||||
|
CMakeSettings.json
|
||||||
|
46
CHANGELOG.md
46
CHANGELOG.md
@ -9,20 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Breaking
|
### Breaking
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Cololight support (Cololight Plus & Strip) incl. configuration wizard
|
- Grabber: DirectX9 support (#1039)
|
||||||
- Provide additional details on Hardware/CPU information
|
|
||||||
- Allow execution with option "--version", while another hyperion daemon is running
|
|
||||||
- New language support: Russian and Chinese (simplified) (#1005)
|
|
||||||
- Added libcec to deb/rpm dependency list
|
|
||||||
- Updated some language files
|
|
||||||
- New LED Device SK9822 (#1005)
|
|
||||||
- Support SK9822 type LEDs with adaptive brightness control via SPI (#1017)
|
|
||||||
- Provide additional details on Hardware/CPU information (#1045)
|
|
||||||
- Allow execution with option "--version", while another hyperion daemon is running
|
|
||||||
- New blackbar detection mode "Letterbox", that considers only bars at the top and bottom of picture
|
- New blackbar detection mode "Letterbox", that considers only bars at the top and bottom of picture
|
||||||
- Systray icons added - Issue #925 (#1040)
|
|
||||||
- DirectX9 Grabber (#1039)
|
- LED-Devices: Cololight support (Cololight Plus & Strip) incl. configuration wizard
|
||||||
- Added DirectX SDK to CompileHowto
|
- LED-Devices: SK9822 support (#1005,#1017)
|
||||||
|
|
||||||
|
- UX: New language support: Russian and Chinese (simplified) (#1005)
|
||||||
|
- UX: Additional details on Hardware/CPU information (#1045)
|
||||||
|
- UX: Systray icons added - Issue #925 (#1040)
|
||||||
|
|
||||||
|
- Read-Only configuration database support
|
||||||
- Hide Window Systray icon on Hyperion exit & Install DirectX Redistributable
|
- Hide Window Systray icon on Hyperion exit & Install DirectX Redistributable
|
||||||
- Read-Only configuration database support
|
- Read-Only configuration database support
|
||||||
|
|
||||||
@ -30,26 +27,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- boblight: reduce cpu time spent on memcopy and parsing rgb values (#1016)
|
- boblight: reduce cpu time spent on memcopy and parsing rgb values (#1016)
|
||||||
- Windows Installer/Uninstaller notification when Hyperion is running (#1033)
|
- Windows Installer/Uninstaller notification when Hyperion is running (#1033)
|
||||||
- Updated Windows Dependencies
|
- Updated Windows Dependencies
|
||||||
|
- Documentation: Optimized images (#1058)
|
||||||
|
- UX: Default LED-layout is now one LED only to avoid errors as in #673
|
||||||
|
- UX: Change links from http to https (#1067)
|
||||||
|
- Change links from http to https (#1067)
|
||||||
- Cleanup packages.cmake & extend NSIS plugin directory
|
- Cleanup packages.cmake & extend NSIS plugin directory
|
||||||
- Optimize images (#1058)
|
- Optimize images (#1058)
|
||||||
- Update LICENSE
|
|
||||||
- Change links from http to https (#1067)
|
|
||||||
- UI: Separate LED-Layout creation from UI code
|
|
||||||
- Docs: Refreshed EN JSON API documentation
|
- Docs: Refreshed EN JSON API documentation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Properly save Hue light state between sessions (#1014)
|
- Color calibration for Kodi 18 (#1044)
|
||||||
- AVAHI included in Webserver (#996)
|
- LED-Devices: Karatelight, allow an 8-LED configuration (#1037)
|
||||||
- Also allow an 8-LED configuration when using Karatelight (#1037)
|
- LED-Devices: Save Hue light state between sessions (#1014)
|
||||||
- Fix #1007 - LED's retain last state after clearing a source (#1008)
|
- LED-Devices: LED's retain last state after clearing a source (#1008)
|
||||||
- Fix Lightpack issue #1015 (#1049)
|
- LED-Devices: Lightpack issue #1015 (#1049)
|
||||||
- Fix #771 color calibration for Kodi 18 (#1044)
|
|
||||||
- Fix various JSON API issues (#1036)
|
- Fix various JSON API issues (#1036)
|
||||||
- Fix issue #909, Have ratio correction first and then scale (#1047)
|
- Fix issue #909, Have ratio correction first and then scale (#1047)
|
||||||
- Fix display argument in hyperion-qt (#1027)
|
- Fix display argument in hyperion-qt (#1027)
|
||||||
- Fix typos (#1051)
|
|
||||||
- Fix Python reset thread state
|
- Fix Python reset thread state
|
||||||
|
- AVAHI included in Webserver (#996)
|
||||||
|
- Fix add libcec to deb/rpm dependency list
|
||||||
|
- Fix Hyperion configuration is corrected during start-up, if required
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Replace Multi-Lightpack by multi-instance Lightpack configuration (#1049)
|
- Replace Multi-Lightpack by multi-instance Lightpack configuration (#1049)
|
||||||
|
@ -302,13 +302,41 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
|||||||
# Qt5 default install path with msvc2017 64bit component
|
# Qt5 default install path with msvc2017 64bit component
|
||||||
# The Qt5_DIR should point to Qt5Config.cmake -> C:/Qt/5.xx/msvc2017_64/lib/cmake/Qt5
|
# The Qt5_DIR should point to Qt5Config.cmake -> C:/Qt/5.xx/msvc2017_64/lib/cmake/Qt5
|
||||||
# The CMAKE_PREFIX_PATH should point to the install directory -> C:/Qt/5.xx/msvc2017_64
|
# The CMAKE_PREFIX_PATH should point to the install directory -> C:/Qt/5.xx/msvc2017_64
|
||||||
|
#
|
||||||
|
# Alternatively, use Qt5_BASE_DIR environment variable to point to Qt version to be used
|
||||||
|
# In MSVC19 add into CMakeSettings.json
|
||||||
|
#
|
||||||
|
# "environments": [
|
||||||
|
# {
|
||||||
|
# "Qt5_BASE_DIR": "D:/Qt/5.15.1/msvc2019_64"
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
|
||||||
|
if (NOT DEFINED ENV{Qt5_BASE_DIR})
|
||||||
FIRSTSUBDIR(SUBDIRQT "C:/Qt")
|
FIRSTSUBDIR(SUBDIRQT "C:/Qt")
|
||||||
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${SUBDIRQT}/msvc2019_64")
|
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${SUBDIRQT}/msvc2019_64")
|
||||||
if (NOT DEFINED ENV{Qt5_DIR})
|
else()
|
||||||
message(STATUS "Set Qt5 module path: ${SUBDIRQT}")
|
message(STATUS "Qt5_BASE_DIR: $ENV{Qt5_BASE_DIR}")
|
||||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${SUBDIRQT}/msvc2019_64/lib/cmake/Qt5")
|
message(STATUS "Add Qt5_BASE_DIR: $ENV{Qt5_BASE_DIR} to CMAKE_PREFIX_PATH")
|
||||||
|
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "$ENV{Qt5_BASE_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT DEFINED ENV{Qt5_DIR})
|
||||||
|
if (NOT DEFINED ENV{Qt5_BASE_DIR})
|
||||||
|
SET (qt_module_path "${SUBDIRQT}/msvc2019_64/lib/cmake/Qt5")
|
||||||
|
else ()
|
||||||
|
SET (qt_module_path "$ENV{Qt5_BASE_DIR}/lib/cmake/Qt5")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
SET (qt_module_path "$ENV{Qt5_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Add ${qt_module_path} to CMAKE_MODULE_PATH")
|
||||||
|
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${qt_module_path}")
|
||||||
|
|
||||||
|
#message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
|
||||||
|
#message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}")
|
||||||
|
|
||||||
# Search for DirectX9
|
# Search for DirectX9
|
||||||
if (ENABLE_DX)
|
if (ENABLE_DX)
|
||||||
find_package(DirectX9 REQUIRED)
|
find_package(DirectX9 REQUIRED)
|
||||||
|
@ -21,6 +21,7 @@ import socket
|
|||||||
import serial
|
import serial
|
||||||
import serial.threaded
|
import serial.threaded
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
class SerialToNet(serial.threaded.Protocol):
|
class SerialToNet(serial.threaded.Protocol):
|
||||||
"""serial->socket"""
|
"""serial->socket"""
|
||||||
@ -152,7 +153,7 @@ to this service over the network.
|
|||||||
|
|
||||||
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
srv.bind(('', args.localport))
|
srv.bind(('0.0.0.0', args.localport))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
intentional_exit = False
|
intentional_exit = False
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
<label class="ltdlabel" for="ip_cl_top" data-i18n="conf_leds_layout_cl_top">Top</label>
|
<label class="ltdlabel" for="ip_cl_top" data-i18n="conf_leds_layout_cl_top">Top</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledCLconstr " id="ip_cl_top" type="number" value="10" min="0" step="1"></input>
|
<input class="form-control ledCLconstr " id="ip_cl_top" type="number" value="1" min="0" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<label class="ltdlabel" for="ip_cl_bottom" data-i18n="conf_leds_layout_cl_bottom">Bottom</label>
|
<label class="ltdlabel" for="ip_cl_bottom" data-i18n="conf_leds_layout_cl_bottom">Bottom</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledCLconstr" id="ip_cl_bottom" type="number" value="10" min="0" step="1"></input>
|
<input class="form-control ledCLconstr" id="ip_cl_bottom" type="number" value="0" min="0" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<label class="ltdlabel" for="ip_cl_left" data-i18n="conf_leds_layout_cl_left">Left</label>
|
<label class="ltdlabel" for="ip_cl_left" data-i18n="conf_leds_layout_cl_left">Left</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledCLconstr" id="ip_cl_left" type="number" value="6" min="0" step="1"></input>
|
<input class="form-control ledCLconstr" id="ip_cl_left" type="number" value="0" min="0" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -77,7 +77,7 @@
|
|||||||
<label class="ltdlabel" for="ip_cl_right" data-i18n="conf_leds_layout_cl_right">Right</label>
|
<label class="ltdlabel" for="ip_cl_right" data-i18n="conf_leds_layout_cl_right">Right</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledCLconstr" id="ip_cl_right" type="number" value="6" min="0" step="1"></input>
|
<input class="form-control ledCLconstr" id="ip_cl_right" type="number" value="0" min="0" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -266,7 +266,7 @@
|
|||||||
<label class="ltdlabel" for="ip_ma_ledshoriz" data-i18n="conf_leds_layout_ma_horiz">Horizontal</label>
|
<label class="ltdlabel" for="ip_ma_ledshoriz" data-i18n="conf_leds_layout_ma_horiz">Horizontal</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledMAconstr" id="ip_ma_ledshoriz" type="number" value="10" min="1" step="1"></input>
|
<input class="form-control ledMAconstr" id="ip_ma_ledshoriz" type="number" value="1" min="1" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -275,7 +275,7 @@
|
|||||||
<label class="ltdlabel" for="ip_ma_ledsvert" data-i18n="conf_leds_layout_ma_vert">Vertical</label>
|
<label class="ltdlabel" for="ip_ma_ledsvert" data-i18n="conf_leds_layout_ma_vert">Vertical</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="itd input-group">
|
<td class="itd input-group">
|
||||||
<input class="form-control ledMAconstr" id="ip_ma_ledsvert" type="number" value="10" min="1" step="1"></input>
|
<input class="form-control ledMAconstr" id="ip_ma_ledsvert" type="number" value="1" min="1" step="1"></input>
|
||||||
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
<div class="input-group-addon" data-i18n="edt_append_leds">LEDs</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -359,10 +359,10 @@ function migrateLedConfig(slConfig){
|
|||||||
|
|
||||||
//Default Classic layout
|
//Default Classic layout
|
||||||
newLedConfig.classic = {
|
newLedConfig.classic = {
|
||||||
"top" : 8,
|
"top" : 1,
|
||||||
"bottom" : 8,
|
"bottom" : 0,
|
||||||
"left" : 5,
|
"left" : 0,
|
||||||
"right" : 5,
|
"right" : 0,
|
||||||
"glength" : 0,
|
"glength" : 0,
|
||||||
"gpos" : 0,
|
"gpos" : 0,
|
||||||
"position" : 0,
|
"position" : 0,
|
||||||
@ -386,8 +386,8 @@ function migrateLedConfig(slConfig){
|
|||||||
newLedConfig.classic.overlap = slConfig.overlap;
|
newLedConfig.classic.overlap = slConfig.overlap;
|
||||||
|
|
||||||
//Default Matrix layout
|
//Default Matrix layout
|
||||||
newLedConfig["matrix"] = { "ledshoriz": 10,
|
newLedConfig["matrix"] = { "ledshoriz": 1,
|
||||||
"ledsvert" : 10,
|
"ledsvert" : 1,
|
||||||
"cabling" : "snake",
|
"cabling" : "snake",
|
||||||
"start" : "top-left"
|
"start" : "top-left"
|
||||||
}
|
}
|
||||||
|
@ -454,9 +454,9 @@ function requestAdjustment(type, value, complete)
|
|||||||
sendToHyperion("adjustment", "", '"adjustment": {"'+type+'": '+value+'}');
|
sendToHyperion("adjustment", "", '"adjustment": {"'+type+'": '+value+'}');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestLedDeviceDiscovery(type)
|
async function requestLedDeviceDiscovery(type, params)
|
||||||
{
|
{
|
||||||
let data = { ledDeviceType: type };
|
let data = { ledDeviceType: type, params: params };
|
||||||
|
|
||||||
return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) );
|
return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) );
|
||||||
}
|
}
|
||||||
|
@ -389,7 +389,7 @@ function showInfoDialog(type,header,message)
|
|||||||
|
|
||||||
$(document).on('click', '[data-dismiss-modal]', function () {
|
$(document).on('click', '[data-dismiss-modal]', function () {
|
||||||
var target = $(this).attr('data-dismiss-modal');
|
var target = $(this).attr('data-dismiss-modal');
|
||||||
$(target).modal('hide');
|
$.find(target).modal.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +439,8 @@ function startWizardCC() {
|
|||||||
$('#wiz_cc_kodiip').off().on('change', function () {
|
$('#wiz_cc_kodiip').off().on('change', function () {
|
||||||
|
|
||||||
kodiAddress = $(this).val().trim();
|
kodiAddress = $(this).val().trim();
|
||||||
|
$('#wizp1_body').find("kodiAddress").val(kodiAddress);
|
||||||
|
|
||||||
$('#kodi_status').html('');
|
$('#kodi_status').html('');
|
||||||
|
|
||||||
// Remove Kodi's default Web-Socket port (9090) from display and ensure Kodi's default REST-API port (8080) is mapped to web-socket port to ease migration
|
// Remove Kodi's default Web-Socket port (9090) from display and ensure Kodi's default REST-API port (8080) is mapped to web-socket port to ease migration
|
||||||
@ -1585,7 +1587,7 @@ function beginWizardAtmoOrb() {
|
|||||||
lights = [];
|
lights = [];
|
||||||
configuredLights = [];
|
configuredLights = [];
|
||||||
|
|
||||||
configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
|
var configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
|
||||||
if (configruedOrbIds.length !== 0) {
|
if (configruedOrbIds.length !== 0) {
|
||||||
configuredLights = configruedOrbIds.split(",").map(Number);
|
configuredLights = configruedOrbIds.split(",").map(Number);
|
||||||
}
|
}
|
||||||
@ -1648,13 +1650,16 @@ function beginWizardAtmoOrb() {
|
|||||||
async function discover_atmoorb_lights(multiCastGroup, multiCastPort) {
|
async function discover_atmoorb_lights(multiCastGroup, multiCastPort) {
|
||||||
var light = {};
|
var light = {};
|
||||||
|
|
||||||
if (multiCastGroup === "")
|
var params = {};
|
||||||
multiCastGroup = "239.255.255.250";
|
if (multiCastGroup !== "")
|
||||||
|
{
|
||||||
|
params.multiCastGroup = multiCastGroup;
|
||||||
|
}
|
||||||
|
|
||||||
if (multiCastPort === "")
|
if (multiCastPort !== 0)
|
||||||
multiCastPort = 49692;
|
{
|
||||||
|
params.multiCastPort = multiCastPort;
|
||||||
let params = { multiCastGroup: multiCastGroup, multiCastPort: multiCastPort };
|
}
|
||||||
|
|
||||||
// Get discovered lights
|
// Get discovered lights
|
||||||
const res = await requestLedDeviceDiscovery('atmoorb', params);
|
const res = await requestLedDeviceDiscovery('atmoorb', params);
|
||||||
|
@ -120,7 +120,7 @@
|
|||||||
|
|
||||||
"backgroundEffect" :
|
"backgroundEffect" :
|
||||||
{
|
{
|
||||||
"enable" : true,
|
"enable" : false,
|
||||||
"type" : "effect",
|
"type" : "effect",
|
||||||
"color" : [255,138,0],
|
"color" : [255,138,0],
|
||||||
"effect" : "Warm mood blobs"
|
"effect" : "Warm mood blobs"
|
||||||
@ -197,10 +197,10 @@
|
|||||||
{
|
{
|
||||||
"classic":
|
"classic":
|
||||||
{
|
{
|
||||||
"top" : 8,
|
"top" : 1,
|
||||||
"bottom" : 8,
|
"bottom" : 0,
|
||||||
"left" : 5,
|
"left" : 0,
|
||||||
"right" : 5,
|
"right" : 0,
|
||||||
"glength" : 0,
|
"glength" : 0,
|
||||||
"gpos" : 0,
|
"gpos" : 0,
|
||||||
"position" : 0,
|
"position" : 0,
|
||||||
@ -221,8 +221,8 @@
|
|||||||
|
|
||||||
"matrix":
|
"matrix":
|
||||||
{
|
{
|
||||||
"ledshoriz": 10,
|
"ledshoriz": 1,
|
||||||
"ledsvert" : 10,
|
"ledsvert" : 1,
|
||||||
"cabling" : "snake",
|
"cabling" : "snake",
|
||||||
"start" : "top-left"
|
"start" : "top-left"
|
||||||
}
|
}
|
||||||
@ -231,160 +231,10 @@
|
|||||||
"leds":
|
"leds":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"hmax": 0.125,
|
"hmax": 1,
|
||||||
"hmin": 0,
|
"hmin": 0,
|
||||||
"vmax": 0.08,
|
"vmax": 0.08,
|
||||||
"vmin": 0
|
"vmin": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.25,
|
|
||||||
"hmin": 0.125,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.375,
|
|
||||||
"hmin": 0.25,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.5,
|
|
||||||
"hmin": 0.375,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.625,
|
|
||||||
"hmin": 0.5,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.75,
|
|
||||||
"hmin": 0.625,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.875,
|
|
||||||
"hmin": 0.75,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.875,
|
|
||||||
"vmax": 0.08,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.95,
|
|
||||||
"vmax": 0.2,
|
|
||||||
"vmin": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.95,
|
|
||||||
"vmax": 0.4,
|
|
||||||
"vmin": 0.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.95,
|
|
||||||
"vmax": 0.6,
|
|
||||||
"vmin": 0.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.95,
|
|
||||||
"vmax": 0.8,
|
|
||||||
"vmin": 0.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.95,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 1,
|
|
||||||
"hmin": 0.875,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.875,
|
|
||||||
"hmin": 0.75,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.75,
|
|
||||||
"hmin": 0.625,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.625,
|
|
||||||
"hmin": 0.5,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.5,
|
|
||||||
"hmin": 0.375,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.375,
|
|
||||||
"hmin": 0.25,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.25,
|
|
||||||
"hmin": 0.125,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.125,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.92
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.05,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 1,
|
|
||||||
"vmin": 0.8
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.05,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 0.8,
|
|
||||||
"vmin": 0.6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.05,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 0.6,
|
|
||||||
"vmin": 0.4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.05,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 0.4,
|
|
||||||
"vmin": 0.2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hmax": 0.05,
|
|
||||||
"hmin": 0,
|
|
||||||
"vmax": 0.2,
|
|
||||||
"vmin": 0
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ namespace hyperion
|
|||||||
///
|
///
|
||||||
struct BlackBorder
|
struct BlackBorder
|
||||||
{
|
{
|
||||||
/// Falg indicating if the border is unknown
|
/// Flag indicating if the border is unknown
|
||||||
bool unknown;
|
bool unknown;
|
||||||
|
|
||||||
/// The size of the detected horizontal border
|
/// The size of the detected horizontal border
|
||||||
@ -48,7 +48,7 @@ namespace hyperion
|
|||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
/// Constructs a black-border detector
|
/// Constructs a black-border detector
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
/// @param[in] threshold The threshold which the black-border detector should use
|
||||||
///
|
///
|
||||||
BlackBorderDetector(double threshold);
|
BlackBorderDetector(double threshold);
|
||||||
|
|
||||||
@ -67,9 +67,9 @@ namespace hyperion
|
|||||||
template <typename Pixel_T>
|
template <typename Pixel_T>
|
||||||
BlackBorder process(const Image<Pixel_T> & image) const
|
BlackBorder process(const Image<Pixel_T> & image) const
|
||||||
{
|
{
|
||||||
// test center and 33%, 66% of width/heigth
|
// test centre and 33%, 66% of width/height
|
||||||
// 33 and 66 will check left and top
|
// 33 and 66 will check left and top
|
||||||
// center will check right and bottom sids
|
// centre will check right and bottom sides
|
||||||
int width = image.width();
|
int width = image.width();
|
||||||
int height = image.height();
|
int height = image.height();
|
||||||
int width33percent = width / 3;
|
int width33percent = width / 3;
|
||||||
@ -281,7 +281,7 @@ namespace hyperion
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if a given color is considered black and therefor could be part of the border.
|
/// Checks if a given color is considered black and therefore could be part of the border.
|
||||||
///
|
///
|
||||||
/// @param[in] color The color to check
|
/// @param[in] color The color to check
|
||||||
///
|
///
|
||||||
@ -295,7 +295,7 @@ namespace hyperion
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Threshold for the blackborder detector [0 .. 255]
|
/// Threshold for the black-border detector [0 .. 255]
|
||||||
const uint8_t _blackborderThreshold;
|
const uint8_t _blackborderThreshold;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -44,14 +44,14 @@ namespace hyperion
|
|||||||
void setEnabled(bool enable);
|
void setEnabled(bool enable);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets the _hardDisabled state, if True prevents the enable from COMP_BLACKBORDER state emit (mimiks wrong state to external!)
|
/// Sets the _hardDisabled state, if True prevents the enable from COMP_BLACKBORDER state emit (mimics wrong state to external!)
|
||||||
/// It's not possible to enable bb from this method, if the user requsted a disable!
|
/// It's not possible to enable black-border detection from this method, if the user requested a disable!
|
||||||
/// @param disable The new state
|
/// @param disable The new state
|
||||||
///
|
///
|
||||||
void setHardDisable(bool disable);
|
void setHardDisable(bool disable);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Processes the image. This performs detecion of black-border on the given image and
|
/// Processes the image. This performs detection of black-border on the given image and
|
||||||
/// updates the current border accordingly. If the current border is updated the method call
|
/// updates the current border accordingly. If the current border is updated the method call
|
||||||
/// will return true else false
|
/// will return true else false
|
||||||
///
|
///
|
||||||
@ -64,10 +64,11 @@ namespace hyperion
|
|||||||
{
|
{
|
||||||
// get the border for the single image
|
// get the border for the single image
|
||||||
BlackBorder imageBorder;
|
BlackBorder imageBorder;
|
||||||
if (!enabled())
|
|
||||||
{
|
|
||||||
imageBorder.horizontalSize = 0;
|
imageBorder.horizontalSize = 0;
|
||||||
imageBorder.verticalSize = 0;
|
imageBorder.verticalSize = 0;
|
||||||
|
|
||||||
|
if (!enabled())
|
||||||
|
{
|
||||||
imageBorder.unknown=true;
|
imageBorder.unknown=true;
|
||||||
_currentBorder = imageBorder;
|
_currentBorder = imageBorder;
|
||||||
return true;
|
return true;
|
||||||
@ -98,7 +99,7 @@ namespace hyperion
|
|||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
/// @param type settingyType from enum
|
/// @param type settingType from enum
|
||||||
/// @param config configuration object
|
/// @param config configuration object
|
||||||
///
|
///
|
||||||
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
|
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
|
||||||
@ -121,7 +122,7 @@ namespace hyperion
|
|||||||
///
|
///
|
||||||
bool updateBorder(const BlackBorder & newDetectedBorder);
|
bool updateBorder(const BlackBorder & newDetectedBorder);
|
||||||
|
|
||||||
/// flag for blackborder detector usage
|
/// flag for black-border detector usage
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
|
|
||||||
/// The number of unknown-borders detected before it becomes the current border
|
/// The number of unknown-borders detected before it becomes the current border
|
||||||
@ -133,13 +134,13 @@ namespace hyperion
|
|||||||
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
|
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
|
||||||
unsigned _maxInconsistentCnt;
|
unsigned _maxInconsistentCnt;
|
||||||
|
|
||||||
/// The number of pixels to increase a detected border for removing blury pixels
|
/// The number of pixels to increase a detected border for removing blurry pixels
|
||||||
unsigned _blurRemoveCnt;
|
unsigned _blurRemoveCnt;
|
||||||
|
|
||||||
/// The border detection mode
|
/// The border detection mode
|
||||||
QString _detectionMode;
|
QString _detectionMode;
|
||||||
|
|
||||||
/// The blackborder detector
|
/// The black-border detector
|
||||||
BlackBorderDetector* _detector;
|
BlackBorderDetector* _detector;
|
||||||
|
|
||||||
/// The current detected border
|
/// The current detected border
|
||||||
@ -148,9 +149,9 @@ namespace hyperion
|
|||||||
/// The border detected in the previous frame
|
/// The border detected in the previous frame
|
||||||
BlackBorder _previousDetectedBorder;
|
BlackBorder _previousDetectedBorder;
|
||||||
|
|
||||||
/// The number of frame the previous detected border matched the incomming border
|
/// The number of frame the previous detected border matched the incoming border
|
||||||
unsigned _consistentCnt;
|
unsigned _consistentCnt;
|
||||||
/// The number of frame the previous detected border NOT matched the incomming border
|
/// The number of frame the previous detected border NOT matched the incoming border
|
||||||
unsigned _inconsistentCnt;
|
unsigned _inconsistentCnt;
|
||||||
/// old threshold
|
/// old threshold
|
||||||
double _oldThreshold;
|
double _oldThreshold;
|
||||||
|
@ -19,7 +19,7 @@ private:
|
|||||||
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
|
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
|
||||||
/// Searching for hyperion http service by default
|
/// Searching for hyperion http service by default
|
||||||
///
|
///
|
||||||
BonjourBrowserWrapper(QObject * parent = 0);
|
BonjourBrowserWrapper(QObject * parent = nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -30,36 +30,36 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Get all available sessions
|
/// @brief Get all available sessions
|
||||||
///
|
///
|
||||||
QMap<QString,BonjourRecord> getAllServices() { return _hyperionSessions; };
|
QMap<QString, BonjourRecord> getAllServices() { return _hyperionSessions; }
|
||||||
|
|
||||||
static BonjourBrowserWrapper* instance;
|
static BonjourBrowserWrapper* instance;
|
||||||
static BonjourBrowserWrapper* getInstance(){ return instance; };
|
static BonjourBrowserWrapper *getInstance() { return instance; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
///
|
///
|
||||||
/// @brief Emits whenever a change happend
|
/// @brief Emits whenever a change happend
|
||||||
///
|
///
|
||||||
void browserChange(const QMap<QString,BonjourRecord>& bRegisters);
|
void browserChange( const QMap<QString, BonjourRecord> &bRegisters );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// map of service names and browsers
|
/// map of service names and browsers
|
||||||
QMap< QString, BonjourServiceBrowser* > _browsedServices;
|
QMap<QString, BonjourServiceBrowser *> _browsedServices;
|
||||||
/// Resolver
|
/// Resolver
|
||||||
BonjourServiceResolver* _bonjourResolver;
|
BonjourServiceResolver *_bonjourResolver;
|
||||||
|
|
||||||
// contains all current active service sessions
|
// contains all current active service sessions
|
||||||
QMap<QString,BonjourRecord> _hyperionSessions;
|
QMap<QString, BonjourRecord> _hyperionSessions;
|
||||||
|
|
||||||
QString _bonjourCurrentServiceToResolve;
|
QString _bonjourCurrentServiceToResolve;
|
||||||
/// timer to resolve changes
|
/// timer to resolve changes
|
||||||
QTimer* _timerBonjourResolver;
|
QTimer *_timerBonjourResolver;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
/// @brief is called whenever a BonjourServiceBrowser emits change
|
/// @brief is called whenever a BonjourServiceBrowser emits change
|
||||||
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
|
void currentBonjourRecordsChanged( const QList<BonjourRecord> &list );
|
||||||
/// @brief new record resolved
|
/// @brief new record resolved
|
||||||
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
|
void bonjourRecordResolved( const QHostInfo &hostInfo, int port );
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief timer slot which updates regularly entries
|
/// @brief timer slot which updates regularly entries
|
||||||
|
@ -33,6 +33,8 @@ public:
|
|||||||
QString value(Parser &parser) const;
|
QString value(Parser &parser) const;
|
||||||
const char* getCString(Parser &parser) const;
|
const char* getCString(Parser &parser) const;
|
||||||
|
|
||||||
|
virtual ~Option();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString _error;
|
QString _error;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QtGui>
|
|
||||||
#include "ColorOption.h"
|
#include "ColorOption.h"
|
||||||
#include "ColorsOption.h"
|
#include "ColorsOption.h"
|
||||||
#include "DoubleOption.h"
|
#include "DoubleOption.h"
|
||||||
@ -24,8 +23,8 @@ protected:
|
|||||||
/* No public inheritance because we need to modify a few methods */
|
/* No public inheritance because we need to modify a few methods */
|
||||||
QCommandLineParser _parser;
|
QCommandLineParser _parser;
|
||||||
|
|
||||||
QStringList _getNames(const char shortOption, const QString longOption);
|
QStringList _getNames(const char shortOption, const QString& longOption);
|
||||||
QString _getDescription(const QString description, const QString default_=QString());
|
QString _getDescription(const QString& description, const QString& default_=QString());
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~Parser() override;
|
~Parser() override;
|
||||||
@ -97,24 +96,24 @@ public:
|
|||||||
{
|
{
|
||||||
if(description.size())
|
if(description.size())
|
||||||
setApplicationDescription(description);
|
setApplicationDescription(description);
|
||||||
};
|
}
|
||||||
|
|
||||||
QCommandLineOption addHelpOption()
|
QCommandLineOption addHelpOption()
|
||||||
{
|
{
|
||||||
return _parser.addHelpOption();
|
return _parser.addHelpOption();
|
||||||
};
|
}
|
||||||
|
|
||||||
bool addOption(Option &option);
|
bool addOption(Option &option);
|
||||||
bool addOption(Option *option);
|
bool addOption(Option *option);
|
||||||
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString())
|
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString())
|
||||||
{
|
{
|
||||||
_parser.addPositionalArgument(name, description, syntax);
|
_parser.addPositionalArgument(name, description, syntax);
|
||||||
};
|
}
|
||||||
|
|
||||||
QCommandLineOption addVersionOption()
|
QCommandLineOption addVersionOption()
|
||||||
{
|
{
|
||||||
return _parser.addVersionOption();
|
return _parser.addVersionOption();
|
||||||
};
|
}
|
||||||
|
|
||||||
QString applicationDescription() const
|
QString applicationDescription() const
|
||||||
{
|
{
|
||||||
@ -166,7 +165,7 @@ public:
|
|||||||
_parser.setSingleDashWordOptionMode(singleDashWordOptionMode);
|
_parser.setSingleDashWordOptionMode(singleDashWordOptionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showHelp(int exitCode = 0)
|
[[ noreturn ]] void showHelp(int exitCode = 0)
|
||||||
{
|
{
|
||||||
_parser.showHelp(exitCode);
|
_parser.showHelp(exitCode);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Python includes
|
|
||||||
// collide of qt slots macro
|
|
||||||
#undef slots
|
|
||||||
#include "Python.h"
|
|
||||||
#define slots
|
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@ -44,13 +38,13 @@ public:
|
|||||||
int getPriority() const { return _priority; }
|
int getPriority() const { return _priority; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Set manual interuption to true,
|
/// @brief Set manual interruption to true,
|
||||||
/// Note: DO NOT USE QThread::interuption!
|
/// Note: DO NOT USE QThread::interruption!
|
||||||
///
|
///
|
||||||
void requestInterruption() { _interupt = true; }
|
void requestInterruption() { _interupt = true; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Check if the interuption flag has been set
|
/// @brief Check if the interruption flag has been set
|
||||||
/// @return The flag state
|
/// @return The flag state
|
||||||
///
|
///
|
||||||
bool isInterruptionRequested() { return _interupt; }
|
bool isInterruptionRequested() { return _interupt; }
|
||||||
@ -88,7 +82,7 @@ private:
|
|||||||
QVector<ColorRgb> _colors;
|
QVector<ColorRgb> _colors;
|
||||||
|
|
||||||
Logger *_log;
|
Logger *_log;
|
||||||
// Reflects whenever this effects should interupt (timeout or external request)
|
// Reflects whenever this effects should interrupt (timeout or external request)
|
||||||
std::atomic<bool> _interupt {};
|
std::atomic<bool> _interupt {};
|
||||||
|
|
||||||
QSize _imageSize;
|
QSize _imageSize;
|
||||||
|
@ -15,7 +15,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static EffectFileHandler* efhInstance;
|
static EffectFileHandler* efhInstance;
|
||||||
static EffectFileHandler* getInstance() { return efhInstance; };
|
static EffectFileHandler* getInstance() { return efhInstance; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get all available effects
|
/// @brief Get all available effects
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Apply new width/height values, overwrite Grabber.h implementation as qt doesn't use width/height, just pixelDecimation to calc dimensions
|
/// @brief Apply new width/height values, overwrite Grabber.h implementation as qt doesn't use width/height, just pixelDecimation to calc dimensions
|
||||||
///
|
///
|
||||||
bool setWidthHeight(int width, int height) override { return true; };
|
bool setWidthHeight(int width, int height) override { return true; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Apply new pixelDecimation
|
/// @brief Apply new pixelDecimation
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Apply new width/height values, overwrite Grabber.h implementation as X11 doesn't use width/height, just pixelDecimation to calc dimensions
|
/// @brief Apply new width/height values, overwrite Grabber.h implementation as X11 doesn't use width/height, just pixelDecimation to calc dimensions
|
||||||
///
|
///
|
||||||
bool setWidthHeight(int width, int height) override { return true; };
|
bool setWidthHeight(int width, int height) override { return true; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Apply new pixelDecimation
|
/// @brief Apply new pixelDecimation
|
||||||
|
@ -15,7 +15,7 @@ public:
|
|||||||
~XcbWrapper() override;
|
~XcbWrapper() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void action();
|
void action() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XcbGrabber _grabber;
|
XcbGrabber _grabber;
|
||||||
|
@ -21,7 +21,7 @@ class AuthManager : public QObject
|
|||||||
private:
|
private:
|
||||||
friend class HyperionDaemon;
|
friend class HyperionDaemon;
|
||||||
/// constructor is private, can be called from HyperionDaemon
|
/// constructor is private, can be called from HyperionDaemon
|
||||||
AuthManager(QObject *parent = 0, bool readonlyMode = false);
|
AuthManager(QObject *parent = nullptr, bool readonlyMode = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct AuthDefinition
|
struct AuthDefinition
|
||||||
|
@ -19,14 +19,14 @@ public:
|
|||||||
// listen for config changes
|
// listen for config changes
|
||||||
connect(_hyperion, &Hyperion::settingsChanged, this, &BGEffectHandler::handleSettingsUpdate);
|
connect(_hyperion, &Hyperion::settingsChanged, this, &BGEffectHandler::handleSettingsUpdate);
|
||||||
|
|
||||||
// init
|
// initialization
|
||||||
handleSettingsUpdate(settings::BGEFFECT, _hyperion->getSetting(settings::BGEFFECT));
|
handleSettingsUpdate(settings::BGEFFECT, _hyperion->getSetting(settings::BGEFFECT));
|
||||||
};
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
/// @param type settingyType from enum
|
/// @param type settingType from enum
|
||||||
/// @param config configuration object
|
/// @param config configuration object
|
||||||
///
|
///
|
||||||
void handleSettingsUpdate(settings::type type, const QJsonDocument& config)
|
void handleSettingsUpdate(settings::type type, const QJsonDocument& config)
|
||||||
@ -36,7 +36,7 @@ private slots:
|
|||||||
const QJsonObject& BGEffectConfig = config.object();
|
const QJsonObject& BGEffectConfig = config.object();
|
||||||
|
|
||||||
#define BGCONFIG_ARRAY bgColorConfig.toArray()
|
#define BGCONFIG_ARRAY bgColorConfig.toArray()
|
||||||
// clear bg prioritiy
|
// clear background priority
|
||||||
_hyperion->clear(254);
|
_hyperion->clear(254);
|
||||||
// initial background effect/color
|
// initial background effect/color
|
||||||
if (BGEffectConfig["enable"].toBool(true))
|
if (BGEffectConfig["enable"].toBool(true))
|
||||||
@ -48,24 +48,24 @@ private slots:
|
|||||||
{
|
{
|
||||||
std::vector<ColorRgb> bg_color = {
|
std::vector<ColorRgb> bg_color = {
|
||||||
ColorRgb {
|
ColorRgb {
|
||||||
(uint8_t)BGCONFIG_ARRAY.at(0).toInt(0),
|
static_cast<uint8_t>(BGCONFIG_ARRAY.at(0).toInt(0)),
|
||||||
(uint8_t)BGCONFIG_ARRAY.at(1).toInt(0),
|
static_cast<uint8_t>(BGCONFIG_ARRAY.at(1).toInt(0)),
|
||||||
(uint8_t)BGCONFIG_ARRAY.at(2).toInt(0)
|
static_cast<uint8_t>(BGCONFIG_ARRAY.at(2).toInt(0))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_hyperion->setColor(254, bg_color);
|
_hyperion->setColor(254, bg_color);
|
||||||
Info(Logger::getInstance("HYPERION"),"Inital background color set (%d %d %d)",bg_color.at(0).red, bg_color.at(0).green, bg_color.at(0).blue);
|
Info(Logger::getInstance("HYPERION"),"Initial background color set (%d %d %d)",bg_color.at(0).red, bg_color.at(0).green, bg_color.at(0).blue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int result = _hyperion->setEffect(bgEffectConfig, 254);
|
int result = _hyperion->setEffect(bgEffectConfig, 254);
|
||||||
Info(Logger::getInstance("HYPERION"),"Inital background effect '%s' %s", QSTRING_CSTR(bgEffectConfig), ((result == 0) ? "started" : "failed"));
|
Info(Logger::getInstance("HYPERION"),"Initial background effect '%s' %s", QSTRING_CSTR(bgEffectConfig), ((result == 0) ? "started" : "failed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BGCONFIG_ARRAY
|
#undef BGCONFIG_ARRAY
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Hyperion instance pointer
|
/// Hyperion instance pointer
|
||||||
|
@ -111,7 +111,7 @@ public slots:
|
|||||||
///
|
///
|
||||||
/// Returns the number of attached leds
|
/// Returns the number of attached leds
|
||||||
///
|
///
|
||||||
unsigned getLedCount() const;
|
int getLedCount() const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()
|
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()
|
||||||
@ -298,7 +298,7 @@ public slots:
|
|||||||
///
|
///
|
||||||
/// @return The information of the given, a not found priority will return lowest priority as fallback
|
/// @return The information of the given, a not found priority will return lowest priority as fallback
|
||||||
///
|
///
|
||||||
InputInfo getPriorityInfo(int priority) const;
|
PriorityMuxer::InputInfo getPriorityInfo(int priority) const;
|
||||||
|
|
||||||
/// #############
|
/// #############
|
||||||
/// SETTINGSMANAGER
|
/// SETTINGSMANAGER
|
||||||
@ -527,7 +527,7 @@ private:
|
|||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
/// count of hardware leds
|
/// count of hardware leds
|
||||||
unsigned _hwLedCount;
|
int _hwLedCount;
|
||||||
|
|
||||||
QSize _ledGridSize;
|
QSize _ledGridSize;
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
class Hyperion;
|
class Hyperion;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
/// The ImageProcessor translates an RGB-image to RGB-values for the LEDs. The processing is
|
||||||
/// performed in two steps. First the average color per led-region is computed. Second a
|
/// performed in two steps. First the average color per led-region is computed. Second a
|
||||||
/// color-tranform is applied based on a gamma-correction.
|
/// color-transform is applied based on a gamma-correction.
|
||||||
///
|
///
|
||||||
class ImageProcessor : public QObject
|
class ImageProcessor : public QObject
|
||||||
{
|
{
|
||||||
@ -39,7 +39,7 @@ public:
|
|||||||
~ImageProcessor() override;
|
~ImageProcessor() override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
/// Specifies the width and height of 'incoming' images. This will resize the buffer-image to
|
||||||
/// match the given size.
|
/// match the given size.
|
||||||
/// NB All earlier obtained references will be invalid.
|
/// NB All earlier obtained references will be invalid.
|
||||||
///
|
///
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
///
|
///
|
||||||
void setLedString(const LedString& ledString);
|
void setLedString(const LedString& ledString);
|
||||||
|
|
||||||
/// Returns starte of black border detector
|
/// Returns state of black border detector
|
||||||
bool blackBorderDetectorEnabled() const;
|
bool blackBorderDetectorEnabled() const;
|
||||||
|
|
||||||
/// Returns the current _userMappingType, this may not be the current applied type!
|
/// Returns the current _userMappingType, this may not be the current applied type!
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
static QString mappingTypeToStr(int mappingType);
|
static QString mappingTypeToStr(int mappingType);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Set the Hyperion::update() requestes led mapping type. This type is used in favour of type set with setLedMappingType.
|
/// @brief Set the Hyperion::update() request LED mapping type. This type is used in favour of type set with setLedMappingType.
|
||||||
/// If you don't want to force a mapType set this to -1 (user choice will be set)
|
/// If you don't want to force a mapType set this to -1 (user choice will be set)
|
||||||
/// @param mapType The new mapping type
|
/// @param mapType The new mapping type
|
||||||
///
|
///
|
||||||
@ -85,7 +85,7 @@ public slots:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
/// Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
/// Specifies the width and height of 'incoming' images. This will resize the buffer-image to
|
||||||
/// match the given size.
|
/// match the given size.
|
||||||
/// NB All earlier obtained references will be invalid.
|
/// NB All earlier obtained references will be invalid.
|
||||||
///
|
///
|
||||||
@ -117,7 +117,7 @@ public:
|
|||||||
// Check black border detection
|
// Check black border detection
|
||||||
verifyBorder(image);
|
verifyBorder(image);
|
||||||
|
|
||||||
// Create a result vector and call the 'in place' functionl
|
// Create a result vector and call the 'in place' function
|
||||||
switch (_mappingType)
|
switch (_mappingType)
|
||||||
{
|
{
|
||||||
case 1: colors = _imageToLeds->getUniLedColor(image); break;
|
case 1: colors = _imageToLeds->getUniLedColor(image); break;
|
||||||
@ -225,7 +225,7 @@ private:
|
|||||||
/// The processor for black border detection
|
/// The processor for black border detection
|
||||||
hyperion::BlackBorderProcessor * _borderProcessor;
|
hyperion::BlackBorderProcessor * _borderProcessor;
|
||||||
|
|
||||||
/// The mapping of image-pixels to leds
|
/// The mapping of image-pixels to LEDs
|
||||||
hyperion::ImageToLedsMap* _imageToLeds;
|
hyperion::ImageToLedsMap* _imageToLeds;
|
||||||
|
|
||||||
/// Type of image 2 led mapping
|
/// Type of image 2 led mapping
|
||||||
|
@ -175,7 +175,7 @@ namespace hyperion
|
|||||||
return ColorRgb::BLACK;
|
return ColorRgb::BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate the sum of each seperate color channel
|
// Accumulate the sum of each separate color channel
|
||||||
uint_fast32_t cummRed = 0;
|
uint_fast32_t cummRed = 0;
|
||||||
uint_fast32_t cummGreen = 0;
|
uint_fast32_t cummGreen = 0;
|
||||||
uint_fast32_t cummBlue = 0;
|
uint_fast32_t cummBlue = 0;
|
||||||
@ -209,7 +209,7 @@ namespace hyperion
|
|||||||
template <typename Pixel_T>
|
template <typename Pixel_T>
|
||||||
ColorRgb calcMeanColor(const Image<Pixel_T> & image) const
|
ColorRgb calcMeanColor(const Image<Pixel_T> & image) const
|
||||||
{
|
{
|
||||||
// Accumulate the sum of each seperate color channel
|
// Accumulate the sum of each separate color channel
|
||||||
uint_fast32_t cummRed = 0;
|
uint_fast32_t cummRed = 0;
|
||||||
uint_fast32_t cummGreen = 0;
|
uint_fast32_t cummGreen = 0;
|
||||||
uint_fast32_t cummBlue = 0;
|
uint_fast32_t cummBlue = 0;
|
||||||
|
@ -107,16 +107,6 @@ struct Led
|
|||||||
class LedString
|
class LedString
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///
|
|
||||||
/// Constructs the LedString with no leds
|
|
||||||
///
|
|
||||||
LedString();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Destructor of this LedString
|
|
||||||
///
|
|
||||||
~LedString();
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the led specifications
|
/// Returns the led specifications
|
||||||
///
|
///
|
||||||
|
@ -11,22 +11,22 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// The LedColorTransform is responsible for performing color transformation from 'raw' colors
|
/// The LedColorTransform is responsible for performing color transformation from 'raw' colors
|
||||||
/// received as input to colors mapped to match the color-properties of the leds.
|
/// received as input to colors mapped to match the color-properties of the LEDs.
|
||||||
///
|
///
|
||||||
class MultiColorAdjustment
|
class MultiColorAdjustment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MultiColorAdjustment(unsigned ledCnt);
|
MultiColorAdjustment(int ledCnt);
|
||||||
~MultiColorAdjustment();
|
~MultiColorAdjustment();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new ColorAdjustment to this MultiColorTransform
|
* Adds a new ColorAdjustment to this MultiColorTransform
|
||||||
*
|
*
|
||||||
* @param adjustment The new ColorAdjustment (ownership is transfered)
|
* @param adjustment The new ColorAdjustment (ownership is transferred)
|
||||||
*/
|
*/
|
||||||
void addAdjustment(ColorAdjustment * adjustment);
|
void addAdjustment(ColorAdjustment * adjustment);
|
||||||
|
|
||||||
void setAdjustmentForLed(const QString& id, unsigned startLed, unsigned endLed);
|
void setAdjustmentForLed(const QString& id, int startLed, int endLed);
|
||||||
|
|
||||||
bool verifyAdjustments() const;
|
bool verifyAdjustments() const;
|
||||||
|
|
||||||
|
@ -58,10 +58,10 @@ public:
|
|||||||
const static int LOWEST_PRIORITY;
|
const static int LOWEST_PRIORITY;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Constructs the PriorityMuxer for the given number of leds (used to switch to black when
|
/// Constructs the PriorityMuxer for the given number of LEDs (used to switch to black when
|
||||||
/// there are no priority channels
|
/// there are no priority channels
|
||||||
///
|
///
|
||||||
/// @param ledCount The number of leds
|
/// @param ledCount The number of LEDs
|
||||||
///
|
///
|
||||||
PriorityMuxer(int ledCount, QObject * parent);
|
PriorityMuxer(int ledCount, QObject * parent);
|
||||||
|
|
||||||
@ -87,18 +87,18 @@ public:
|
|||||||
/// @brief Get the state of source auto selection
|
/// @brief Get the state of source auto selection
|
||||||
/// @return True if enabled, else false
|
/// @return True if enabled, else false
|
||||||
///
|
///
|
||||||
bool isSourceAutoSelectEnabled() const { return _sourceAutoSelectEnabled; };
|
bool isSourceAutoSelectEnabled() const { return _sourceAutoSelectEnabled; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Overwrite current lowest piority with manual selection; On success disables aito selection
|
/// @brief Overwrite current lowest priority with manual selection; On success disables auto selection
|
||||||
/// @param priority The
|
/// @param priority The
|
||||||
/// @return True on success, false if priority not found
|
/// @return True on success, false if priority not found
|
||||||
///
|
///
|
||||||
bool setPriority(uint8_t priority);
|
bool setPriority(int priority);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Update all ledColos with min length of >= 1 to fit the new led length
|
/// @brief Update all LED-Colors with min length of >= 1 to fit the new led length
|
||||||
/// @param[in] ledCount The count of leds
|
/// @param[in] ledCount The count of LEDs
|
||||||
///
|
///
|
||||||
void updateLedColorsLength(int ledCount);
|
void updateLedColorsLength(int ledCount);
|
||||||
|
|
||||||
@ -146,13 +146,13 @@ public:
|
|||||||
/// @param[in] priority The priority of the channel
|
/// @param[in] priority The priority of the channel
|
||||||
/// @param[in] component The component of the channel
|
/// @param[in] component The component of the channel
|
||||||
/// @param[in] origin Who set the channel (CustomString@IP)
|
/// @param[in] origin Who set the channel (CustomString@IP)
|
||||||
/// @param[in] owner Speicifc owner string, might be empty
|
/// @param[in] owner Specific owner string, might be empty
|
||||||
/// @param[in] smooth_cfg The smooth id to use
|
/// @param[in] smooth_cfg The smooth id to use
|
||||||
///
|
///
|
||||||
void registerInput(int priority, hyperion::Components component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = SMOOTHING_MODE_DEFAULT);
|
void registerInput(int priority, hyperion::Components component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = SMOOTHING_MODE_DEFAULT);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Update the current color of a priority (prev registered with registerInput())
|
/// @brief Update the current color of a priority (previous registered with registerInput())
|
||||||
/// @param priority The priority to update
|
/// @param priority The priority to update
|
||||||
/// @param ledColors The colors
|
/// @param ledColors The colors
|
||||||
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
||||||
@ -174,7 +174,7 @@ public:
|
|||||||
/// @param priority The priority
|
/// @param priority The priority
|
||||||
/// @return True on success false if not found
|
/// @return True on success false if not found
|
||||||
///
|
///
|
||||||
bool setInputInactive(quint8 priority);
|
bool setInputInactive(int priority);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Clears the specified priority channel and update _currentPriority on success
|
/// Clears the specified priority channel and update _currentPriority on success
|
||||||
@ -182,7 +182,7 @@ public:
|
|||||||
/// @param[in] priority The priority of the channel to clear
|
/// @param[in] priority The priority of the channel to clear
|
||||||
/// @return True if priority has been cleared else false (not found)
|
/// @return True if priority has been cleared else false (not found)
|
||||||
///
|
///
|
||||||
bool clearInput(uint8_t priority);
|
bool clearInput(int priority);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Clears all priority channels
|
/// Clears all priority channels
|
||||||
@ -190,7 +190,7 @@ public:
|
|||||||
void clearAll(bool forceClearAll=false);
|
void clearAll(bool forceClearAll=false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Queue a manual push where muxer doesn't recognize them (e.g. continous single color pushes)
|
/// @brief Queue a manual push where muxer doesn't recognize them (e.g. continuous single color pushes)
|
||||||
///
|
///
|
||||||
void queuePush() { emit timeRunner(); }
|
void queuePush() { emit timeRunner(); }
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/settings.h>
|
#include <utils/settings.h>
|
||||||
|
|
||||||
// qt incl
|
// qt includes
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
class Hyperion;
|
class Hyperion;
|
||||||
class SettingsTable;
|
class SettingsTable;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Manage the settings read write from/to config file, on settings changed will emit a signal to update components accordingly
|
/// @brief Manage the settings read write from/to configuration file, on settings changed will emit a signal to update components accordingly
|
||||||
///
|
///
|
||||||
class SettingsManager : public QObject
|
class SettingsManager : public QObject
|
||||||
{
|
{
|
||||||
@ -24,7 +24,7 @@ public:
|
|||||||
SettingsManager(quint8 instance, QObject* parent = nullptr, bool readonlyMode = false);
|
SettingsManager(quint8 instance, QObject* parent = nullptr, bool readonlyMode = false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Save a complete json config
|
/// @brief Save a complete json configuration
|
||||||
/// @param config The entire config object
|
/// @param config The entire config object
|
||||||
/// @param correct If true will correct json against schema before save
|
/// @param correct If true will correct json against schema before save
|
||||||
/// @return True on success else false
|
/// @return True on success else false
|
||||||
@ -32,7 +32,7 @@ public:
|
|||||||
bool saveSettings(QJsonObject config, bool correct = false);
|
bool saveSettings(QJsonObject config, bool correct = false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief get a single setting json from config
|
/// @brief get a single setting json from configuration
|
||||||
/// @param type The settings::type from enum
|
/// @param type The settings::type from enum
|
||||||
/// @return The requested json data as QJsonDocument
|
/// @return The requested json data as QJsonDocument
|
||||||
///
|
///
|
||||||
@ -42,11 +42,11 @@ public:
|
|||||||
/// @brief get the full settings object of this instance (with global settings)
|
/// @brief get the full settings object of this instance (with global settings)
|
||||||
/// @return The requested json
|
/// @return The requested json
|
||||||
///
|
///
|
||||||
const QJsonObject & getSettings() const { return _qconfig; };
|
const QJsonObject & getSettings() const { return _qconfig; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
///
|
///
|
||||||
/// @brief Emits whenever a config part changed.
|
/// @brief Emits whenever a configuration part changed.
|
||||||
/// @param type The settings type from enum
|
/// @param type The settings type from enum
|
||||||
/// @param data The data as QJsonDocument
|
/// @param data The data as QJsonDocument
|
||||||
///
|
///
|
||||||
@ -54,7 +54,7 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
///
|
///
|
||||||
/// @brief Add possile migrations steps for config here
|
/// @brief Add possible migrations steps for configuration here
|
||||||
/// @param config The configuration object
|
/// @param config The configuration object
|
||||||
/// @return True when a migration has been triggered
|
/// @return True when a migration has been triggered
|
||||||
///
|
///
|
||||||
@ -73,7 +73,7 @@ private:
|
|||||||
/// the schema
|
/// the schema
|
||||||
static QJsonObject schemaJson;
|
static QJsonObject schemaJson;
|
||||||
|
|
||||||
/// the current config of this instance
|
/// the current configuration of this instance
|
||||||
QJsonObject _qconfig;
|
QJsonObject _qconfig;
|
||||||
|
|
||||||
bool _readonlyMode;
|
bool _readonlyMode;
|
||||||
|
@ -62,7 +62,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param[in] ledCount Number of device LEDs, 0 = unknown number
|
/// @param[in] ledCount Number of device LEDs, 0 = unknown number
|
||||||
///
|
///
|
||||||
void setLedCount(unsigned int ledCount);
|
void setLedCount(int ledCount);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Set a device's latch time.
|
/// @brief Set a device's latch time.
|
||||||
@ -87,9 +87,11 @@ public:
|
|||||||
/// @brief Discover devices of this type available (for configuration).
|
/// @brief Discover devices of this type available (for configuration).
|
||||||
/// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways.
|
/// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways.
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
virtual QJsonObject discover();
|
virtual QJsonObject discover(const QJsonObject& params);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Discover first device of this type available (for configuration).
|
/// @brief Discover first device of this type available (for configuration).
|
||||||
@ -116,7 +118,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param[in] params Parameters to address device
|
/// @param[in] params Parameters to address device
|
||||||
///
|
///
|
||||||
virtual void identify(const QJsonObject& params) {}
|
virtual void identify(const QJsonObject& /*params*/) {}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Check, if device is properly initialised
|
/// @brief Check, if device is properly initialised
|
||||||
@ -193,7 +195,7 @@ public slots:
|
|||||||
///
|
///
|
||||||
/// @return Number of device's LEDs, 0 = unknown number
|
/// @return Number of device's LEDs, 0 = unknown number
|
||||||
///
|
///
|
||||||
unsigned int getLedCount() const { return _ledCount; }
|
int getLedCount() const { return _ledCount; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get the current active LED-device type.
|
/// @brief Get the current active LED-device type.
|
||||||
@ -348,7 +350,7 @@ protected:
|
|||||||
/// @param size of the array
|
/// @param size of the array
|
||||||
/// @param number Number of array items to be converted.
|
/// @param number Number of array items to be converted.
|
||||||
/// @return array as string of hex values
|
/// @return array as string of hex values
|
||||||
QString uint8_t_to_hex_string(const uint8_t * data, const qint64 size, qint64 number = -1) const;
|
QString uint8_t_to_hex_string(const uint8_t * data, const int size, int number = -1) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Converts a ByteArray to hex string.
|
/// @brief Converts a ByteArray to hex string.
|
||||||
|
@ -66,64 +66,61 @@ public:
|
|||||||
/// @brief Overwrite description address
|
/// @brief Overwrite description address
|
||||||
/// @param addr new address
|
/// @param addr new address
|
||||||
///
|
///
|
||||||
void setDescriptionAddress(const QString& addr) { _descAddress = addr; };
|
void setDescriptionAddress( const QString &addr ) { _descAddress = addr; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Set uuid
|
/// @brief Set uuid
|
||||||
/// @param uuid The uuid
|
/// @param uuid The uuid
|
||||||
///
|
///
|
||||||
void setUuid(const QString& uuid) { _uuid = uuid; };
|
void setUuid( const QString &uuid ) { _uuid = uuid; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief set new flatbuffer server port
|
/// @brief set new flatbuffer server port
|
||||||
///
|
///
|
||||||
void setFlatBufPort(quint16 port) { _fbsPort = QString::number(port); };
|
void setFlatBufPort( quint16 port ){_fbsPort = QString::number( port ); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get current flatbuffer server port
|
/// @brief Get current flatbuffer server port
|
||||||
///
|
///
|
||||||
quint16 getFlatBufPort() const { return _fbsPort.toInt(); };
|
quint16 getFlatBufPort() const
|
||||||
|
{
|
||||||
|
return _fbsPort.toInt();
|
||||||
|
}
|
||||||
///
|
///
|
||||||
/// @brief set new protobuf server port
|
/// @brief set new protobuf server port
|
||||||
///
|
///
|
||||||
void setProtoBufPort(quint16 port) { _pbsPort = QString::number(port); };
|
void setProtoBufPort( quint16 port ) { _pbsPort = QString::number( port ); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get current protobuf server port
|
/// @brief Get current protobuf server port
|
||||||
///
|
///
|
||||||
quint16 getProtoBufPort() const { return _pbsPort.toInt(); };
|
quint16 getProtoBufPort() const { return _pbsPort.toInt(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief set new json server port
|
/// @brief set new json server port
|
||||||
///
|
///
|
||||||
void setJsonServerPort(quint16 port) { _jssPort = QString::number(port); };
|
void setJsonServerPort( quint16 port ) { _jssPort = QString::number( port ); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief get new json server port
|
/// @brief get new json server port
|
||||||
///
|
///
|
||||||
quint16 getJsonServerPort() const { return _jssPort.toInt(); };
|
quint16 getJsonServerPort() const { return _jssPort.toInt(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief set new ssl server port
|
/// @brief set new ssl server port
|
||||||
///
|
///
|
||||||
void setSSLServerPort(quint16 port) { _sslPort = QString::number(port); };
|
void setSSLServerPort( quint16 port ) { _sslPort = QString::number( port ); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief get new ssl server port
|
/// @brief get new ssl server port
|
||||||
///
|
///
|
||||||
quint16 getSSLServerPort() const { return _sslPort.toInt(); };
|
quint16 getSSLServerPort() const { return _sslPort.toInt(); }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief set new hyperion name
|
/// @brief set new hyperion name
|
||||||
///
|
///
|
||||||
void setHyperionName(const QString &name) { _name = name; };
|
void setHyperionName( const QString &name ) { _name = name; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief get hyperion name
|
/// @brief get hyperion name
|
||||||
///
|
///
|
||||||
QString getHyperionName() const { return _name; };
|
QString getHyperionName() const { return _name; }
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
///
|
///
|
||||||
@ -133,23 +130,18 @@ signals:
|
|||||||
/// @param address The ip of the caller
|
/// @param address The ip of the caller
|
||||||
/// @param port The port of the caller
|
/// @param port The port of the caller
|
||||||
///
|
///
|
||||||
void msearchRequestReceived(const QString& target, const QString& mx, const QString address, quint16 port);
|
void msearchRequestReceived( const QString &target,
|
||||||
|
const QString &mx,
|
||||||
|
const QString address,
|
||||||
|
quint16 port );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger* _log;
|
Logger *_log;
|
||||||
QUdpSocket* _udpSocket;
|
QUdpSocket *_udpSocket;
|
||||||
|
|
||||||
QString _serverHeader,
|
QString _serverHeader, _uuid, _fbsPort, _pbsPort, _jssPort, _sslPort, _name, _descAddress;
|
||||||
_uuid,
|
|
||||||
_fbsPort,
|
|
||||||
_pbsPort,
|
|
||||||
_jssPort,
|
|
||||||
_sslPort,
|
|
||||||
_name,
|
|
||||||
_descAddress;
|
|
||||||
bool _running;
|
bool _running;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
_height(other._height),
|
_height(other._height),
|
||||||
_pixels(new Pixel_T[other._width * other._height + 1])
|
_pixels(new Pixel_T[other._width * other._height + 1])
|
||||||
{
|
{
|
||||||
memcpy(_pixels, other._pixels, (long) other._width * other._height * sizeof(Pixel_T));
|
memcpy(_pixels, other._pixels, static_cast<ulong>(other._width) * static_cast<ulong>(other._height) * sizeof(Pixel_T));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageData& operator=(ImageData rhs)
|
ImageData& operator=(ImageData rhs)
|
||||||
@ -150,7 +150,7 @@ public:
|
|||||||
|
|
||||||
ssize_t size() const
|
ssize_t size() const
|
||||||
{
|
{
|
||||||
return (ssize_t) _width * _height * sizeof(Pixel_T);
|
return static_cast<ssize_t>(_width) * static_cast<ssize_t>(_height) * sizeof(Pixel_T);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
@ -163,7 +163,7 @@ public:
|
|||||||
_pixels = new Pixel_T[2];
|
_pixels = new Pixel_T[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(_pixels, 0, (unsigned long) _width * _height * sizeof(Pixel_T));
|
memset(_pixels, 0, static_cast<unsigned long>(_width) * static_cast<unsigned long>(_height) * sizeof(Pixel_T));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -16,7 +16,7 @@ class NetOrigin : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
friend class HyperionDaemon;
|
friend class HyperionDaemon;
|
||||||
NetOrigin(QObject* parent = 0, Logger* log = Logger::getInstance("NETWORK"));
|
NetOrigin(QObject* parent = nullptr, Logger* log = Logger::getInstance("NETWORK"));
|
||||||
|
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
@ -33,8 +33,8 @@ public:
|
|||||||
///
|
///
|
||||||
bool isLocalAddress(const QHostAddress& address, const QHostAddress& local) const;
|
bool isLocalAddress(const QHostAddress& address, const QHostAddress& local) const;
|
||||||
|
|
||||||
static NetOrigin* getInstance(){ return instance; };
|
static NetOrigin *getInstance() { return instance; }
|
||||||
static NetOrigin* instance;
|
static NetOrigin *instance;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
|
@ -19,9 +19,6 @@ public:
|
|||||||
/// @param adjustB
|
/// @param adjustB
|
||||||
RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName="");
|
RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName="");
|
||||||
|
|
||||||
/// Destructor
|
|
||||||
~RgbChannelAdjustment();
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Transform the given array value
|
/// Transform the given array value
|
||||||
///
|
///
|
||||||
|
@ -36,9 +36,9 @@ namespace hyperion {
|
|||||||
{
|
{
|
||||||
std::vector<ColorRgb> fg_color = {
|
std::vector<ColorRgb> fg_color = {
|
||||||
ColorRgb {
|
ColorRgb {
|
||||||
(uint8_t)FGCONFIG_ARRAY.at(0).toInt(0),
|
static_cast<uint8_t>(FGCONFIG_ARRAY.at(0).toInt(0)),
|
||||||
(uint8_t)FGCONFIG_ARRAY.at(1).toInt(0),
|
static_cast<uint8_t>(FGCONFIG_ARRAY.at(1).toInt(0)),
|
||||||
(uint8_t)FGCONFIG_ARRAY.at(2).toInt(0)
|
static_cast<uint8_t>(FGCONFIG_ARRAY.at(2).toInt(0))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
hyperion->setColor(FG_PRIORITY, fg_color, fg_duration_ms);
|
hyperion->setColor(FG_PRIORITY, fg_color, fg_duration_ms);
|
||||||
@ -62,22 +62,22 @@ namespace hyperion {
|
|||||||
{
|
{
|
||||||
const double backlightThreshold = colorConfig["backlightThreshold"].toDouble(0.0);
|
const double backlightThreshold = colorConfig["backlightThreshold"].toDouble(0.0);
|
||||||
const bool backlightColored = colorConfig["backlightColored"].toBool(false);
|
const bool backlightColored = colorConfig["backlightColored"].toBool(false);
|
||||||
const double brightness = colorConfig["brightness"].toInt(100);
|
const int brightness = colorConfig["brightness"].toInt(100);
|
||||||
const double brightnessComp = colorConfig["brightnessCompensation"].toInt(100);
|
const int brightnessComp = colorConfig["brightnessCompensation"].toInt(100);
|
||||||
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
|
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
|
||||||
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
|
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
|
||||||
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
|
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
|
||||||
|
|
||||||
return RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessComp);
|
return RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, static_cast<uint8_t>(brightness), static_cast<uint8_t>(brightnessComp));
|
||||||
}
|
}
|
||||||
|
|
||||||
RgbChannelAdjustment createRgbChannelAdjustment(const QJsonObject& colorConfig, const QString& channelName, int defaultR, int defaultG, int defaultB)
|
RgbChannelAdjustment createRgbChannelAdjustment(const QJsonObject& colorConfig, const QString& channelName, int defaultR, int defaultG, int defaultB)
|
||||||
{
|
{
|
||||||
const QJsonArray& channelConfig = colorConfig[channelName].toArray();
|
const QJsonArray& channelConfig = colorConfig[channelName].toArray();
|
||||||
return RgbChannelAdjustment(
|
return RgbChannelAdjustment(
|
||||||
channelConfig[0].toInt(defaultR),
|
static_cast<uint8_t>(channelConfig[0].toInt(defaultR)),
|
||||||
channelConfig[1].toInt(defaultG),
|
static_cast<uint8_t>(channelConfig[1].toInt(defaultG)),
|
||||||
channelConfig[2].toInt(defaultB),
|
static_cast<uint8_t>(channelConfig[2].toInt(defaultB)),
|
||||||
"ChannelAdjust_" + channelName.toUpper()
|
"ChannelAdjust_" + channelName.toUpper()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ namespace hyperion {
|
|||||||
return adjustment;
|
return adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiColorAdjustment * createLedColorsAdjustment(unsigned ledCnt, const QJsonObject & colorConfig)
|
MultiColorAdjustment * createLedColorsAdjustment(int ledCnt, const QJsonObject & colorConfig)
|
||||||
{
|
{
|
||||||
// Create the result, the transforms are added to this
|
// Create the result, the transforms are added to this
|
||||||
MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt);
|
MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt);
|
||||||
@ -233,7 +233,7 @@ namespace hyperion {
|
|||||||
std::sort(midPointsY.begin(), midPointsY.end());
|
std::sort(midPointsY.begin(), midPointsY.end());
|
||||||
midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
|
midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
|
||||||
|
|
||||||
QSize gridSize( midPointsX.size(), midPointsY.size() );
|
QSize gridSize( static_cast<int>(midPointsX.size()), static_cast<int>(midPointsY.size()) );
|
||||||
|
|
||||||
// Correct the grid in case it is malformed in width vs height
|
// Correct the grid in case it is malformed in width vs height
|
||||||
// Expected is at least 50% of width <-> height
|
// Expected is at least 50% of width <-> height
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
{
|
{
|
||||||
case QJsonValue::Array:
|
case QJsonValue::Array:
|
||||||
{
|
{
|
||||||
for (const QJsonValue &v : value.toArray())
|
for (const QJsonValueRef v : value.toArray())
|
||||||
{
|
{
|
||||||
ret = getDefaultValue(v);
|
ret = getDefaultValue(v);
|
||||||
if (!ret.isEmpty())
|
if (!ret.isEmpty())
|
||||||
|
@ -33,7 +33,7 @@ class WebServer : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebServer (const QJsonDocument& config, bool useSsl, QObject * parent = 0);
|
WebServer (const QJsonDocument& config, bool useSsl, QObject * parent = nullptr);
|
||||||
|
|
||||||
~WebServer () override;
|
~WebServer () override;
|
||||||
|
|
||||||
|
@ -473,6 +473,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
|
|||||||
{
|
{
|
||||||
grabbers["active"] = GrabberWrapper::getInstance()->getActive();
|
grabbers["active"] = GrabberWrapper::getInstance()->getActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
// get available grabbers
|
// get available grabbers
|
||||||
for (auto grabber : GrabberWrapper::availableGrabbers())
|
for (auto grabber : GrabberWrapper::availableGrabbers())
|
||||||
{
|
{
|
||||||
@ -688,12 +689,13 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
|
|||||||
if (subsArr.contains("all"))
|
if (subsArr.contains("all"))
|
||||||
{
|
{
|
||||||
subsArr = QJsonArray();
|
subsArr = QJsonArray();
|
||||||
for (const auto &entry : _jsonCB->getCommands())
|
for (const auto& entry : _jsonCB->getCommands())
|
||||||
{
|
{
|
||||||
subsArr.append(entry);
|
subsArr.append(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto &entry : subsArr)
|
|
||||||
|
for (const QJsonValueRef entry : subsArr)
|
||||||
{
|
{
|
||||||
// config callbacks just if auth is set
|
// config callbacks just if auth is set
|
||||||
if ((entry == "settings-update" || entry == "token-update") && !API::isAdminAuthorized())
|
if ((entry == "settings-update" || entry == "token-update") && !API::isAdminAuthorized())
|
||||||
@ -1416,7 +1418,8 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString &
|
|||||||
if (subc == "discover")
|
if (subc == "discover")
|
||||||
{
|
{
|
||||||
ledDevice = LedDeviceFactory::construct(config);
|
ledDevice = LedDeviceFactory::construct(config);
|
||||||
const QJsonObject devicesDiscovered = ledDevice->discover();
|
const QJsonObject ¶ms = message["params"].toObject();
|
||||||
|
const QJsonObject devicesDiscovered = ledDevice->discover(params);
|
||||||
|
|
||||||
Debug(_log, "response: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
Debug(_log, "response: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ void BoblightClientConnection::sendLightMessage()
|
|||||||
sendMessage(QByteArray(buffer, n));
|
sendMessage(QByteArray(buffer, n));
|
||||||
|
|
||||||
double h0, h1, v0, v1;
|
double h0, h1, v0, v1;
|
||||||
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
|
for (int i = 0; i < _hyperion->getLedCount(); ++i)
|
||||||
{
|
{
|
||||||
_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
|
_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
|
||||||
n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
|
n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
|
||||||
|
@ -17,7 +17,7 @@ class ImageProcessor;
|
|||||||
class Hyperion;
|
class Hyperion;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The Connection object created by \a BoblightServer when a new connection is establshed
|
/// The Connection object created by \a BoblightServer when a new connection is established
|
||||||
///
|
///
|
||||||
class BoblightClientConnection : public QObject
|
class BoblightClientConnection : public QObject
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,11 @@ Option::Option(const QCommandLineOption &other)
|
|||||||
: QCommandLineOption(other)
|
: QCommandLineOption(other)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Option::~Option()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QString Option::value(Parser &parser) const
|
QString Option::value(Parser &parser) const
|
||||||
{
|
{
|
||||||
return parser.value(*this);
|
return parser.value(*this);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include <QtDebug>
|
|
||||||
#include <QtGui>
|
|
||||||
#include "commandline/Parser.h"
|
#include "commandline/Parser.h"
|
||||||
|
|
||||||
using namespace commandline;
|
using namespace commandline;
|
||||||
@ -21,7 +19,7 @@ bool Parser::parse(const QStringList &arguments)
|
|||||||
QString value = this->value(*option);
|
QString value = this->value(*option);
|
||||||
if (!option->validate(*this, value)) {
|
if (!option->validate(*this, value)) {
|
||||||
const QString error = option->getError();
|
const QString error = option->getError();
|
||||||
if (error.size()) {
|
if (!error.isEmpty()) {
|
||||||
_errorText = tr("%1 is not a valid option for %2\n%3").arg(value, option->name(), error);
|
_errorText = tr("%1 is not a valid option for %2\n%3").arg(value, option->name(), error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -44,15 +42,14 @@ void Parser::process(const QStringList &arguments)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::process(const QCoreApplication &app)
|
void Parser::process(const QCoreApplication& /*app*/)
|
||||||
{
|
{
|
||||||
Q_UNUSED(app);
|
|
||||||
process(QCoreApplication::arguments());
|
process(QCoreApplication::arguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Parser::errorText() const
|
QString Parser::errorText() const
|
||||||
{
|
{
|
||||||
return (_errorText.size()) ? _errorText : _parser.errorText();
|
return (!_errorText.isEmpty()) ? _errorText : _parser.errorText();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::addOption(Option &option)
|
bool Parser::addOption(Option &option)
|
||||||
@ -66,27 +63,27 @@ bool Parser::addOption(Option * const option)
|
|||||||
return _parser.addOption(*option);
|
return _parser.addOption(*option);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList Parser::_getNames(const char shortOption, const QString longOption)
|
QStringList Parser::_getNames(const char shortOption, const QString& longOption)
|
||||||
{
|
{
|
||||||
QStringList names;
|
QStringList names;
|
||||||
if (shortOption != 0x0)
|
if (shortOption != 0x0)
|
||||||
{
|
{
|
||||||
names << QString(shortOption);
|
names << QString(shortOption);
|
||||||
}
|
}
|
||||||
if (longOption.size())
|
if (longOption.size() != 0)
|
||||||
{
|
{
|
||||||
names << longOption;
|
names << longOption;
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Parser::_getDescription(const QString description, const QString default_)
|
QString Parser::_getDescription(const QString& description, const QString& default_)
|
||||||
{
|
{
|
||||||
/* Add the translations if available */
|
/* Add the translations if available */
|
||||||
QString formattedDescription(tr(qPrintable(description)));
|
QString formattedDescription(tr(qPrintable(description)));
|
||||||
|
|
||||||
/* Fill in the default if needed */
|
/* Fill in the default if needed */
|
||||||
if (default_.size())
|
if (!default_.isEmpty())
|
||||||
{
|
{
|
||||||
if(!formattedDescription.contains("%1"))
|
if(!formattedDescription.contains("%1"))
|
||||||
{
|
{
|
||||||
|
@ -56,8 +56,8 @@ void Effect::setModuleParameters()
|
|||||||
PyModule_AddObject(module, "__effectObj", PyCapsule_New((void*)this, "hyperion.__effectObj", nullptr));
|
PyModule_AddObject(module, "__effectObj", PyCapsule_New((void*)this, "hyperion.__effectObj", nullptr));
|
||||||
|
|
||||||
// add ledCount variable to the interpreter
|
// add ledCount variable to the interpreter
|
||||||
unsigned ledCount = 0;
|
int ledCount = 0;
|
||||||
QMetaObject::invokeMethod(_hyperion, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned, ledCount));
|
QMetaObject::invokeMethod(_hyperion, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, ledCount));
|
||||||
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", ledCount));
|
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", ledCount));
|
||||||
|
|
||||||
// add minimumWriteTime variable to the interpreter
|
// add minimumWriteTime variable to the interpreter
|
||||||
|
@ -138,7 +138,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args)
|
|||||||
int argCount = PyTuple_Size(args);
|
int argCount = PyTuple_Size(args);
|
||||||
if (argCount == 3)
|
if (argCount == 3)
|
||||||
{
|
{
|
||||||
// three seperate arguments for red, green, and blue
|
// three separate arguments for red, green, and blue
|
||||||
ColorRgb color;
|
ColorRgb color;
|
||||||
if (PyArg_ParseTuple(args, "bbb", &color.red, &color.green, &color.blue))
|
if (PyArg_ParseTuple(args, "bbb", &color.red, &color.green, &color.blue))
|
||||||
{
|
{
|
||||||
@ -158,7 +158,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args)
|
|||||||
if (PyByteArray_Check(bytearray))
|
if (PyByteArray_Check(bytearray))
|
||||||
{
|
{
|
||||||
size_t length = PyByteArray_Size(bytearray);
|
size_t length = PyByteArray_Size(bytearray);
|
||||||
if (length == 3 * getEffect()->_hyperion->getLedCount())
|
if (length == 3 * static_cast<size_t>(getEffect()->_hyperion->getLedCount()))
|
||||||
{
|
{
|
||||||
char * data = PyByteArray_AS_STRING(bytearray);
|
char * data = PyByteArray_AS_STRING(bytearray);
|
||||||
memcpy(getEffect()->_colors.data(), data, length);
|
memcpy(getEffect()->_colors.data(), data, length);
|
||||||
|
@ -14,7 +14,7 @@ ComponentRegister::ComponentRegister(Hyperion* hyperion)
|
|||||||
vect << COMP_ALL << COMP_SMOOTHING << COMP_BLACKBORDER << COMP_FORWARDER << COMP_BOBLIGHTSERVER << COMP_GRABBER << COMP_V4L << COMP_LEDDEVICE;
|
vect << COMP_ALL << COMP_SMOOTHING << COMP_BLACKBORDER << COMP_FORWARDER << COMP_BOBLIGHTSERVER << COMP_GRABBER << COMP_V4L << COMP_LEDDEVICE;
|
||||||
for(auto e : vect)
|
for(auto e : vect)
|
||||||
{
|
{
|
||||||
_componentStates.emplace(e, ((e == COMP_ALL) ? true : false));
|
_componentStates.emplace(e, (e == COMP_ALL));
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &ComponentRegister::handleCompStateChangeRequest);
|
connect(_hyperion, &Hyperion::compStateChangeRequest, this, &ComponentRegister::handleCompStateChangeRequest);
|
||||||
@ -48,29 +48,35 @@ void ComponentRegister::handleCompStateChangeRequest(hyperion::Components comps,
|
|||||||
if(!activated && _prevComponentStates.empty())
|
if(!activated && _prevComponentStates.empty())
|
||||||
{
|
{
|
||||||
Debug(_log,"Disable Hyperion, store current component states");
|
Debug(_log,"Disable Hyperion, store current component states");
|
||||||
for(const auto comp : _componentStates)
|
for(const auto &comp : _componentStates)
|
||||||
{
|
{
|
||||||
// save state
|
// save state
|
||||||
_prevComponentStates.emplace(comp.first, comp.second);
|
_prevComponentStates.emplace(comp.first, comp.second);
|
||||||
// disable if enabled
|
// disable if enabled
|
||||||
if(comp.second)
|
if(comp.second)
|
||||||
|
{
|
||||||
emit _hyperion->compStateChangeRequest(comp.first, false);
|
emit _hyperion->compStateChangeRequest(comp.first, false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
setNewComponentState(COMP_ALL, false);
|
setNewComponentState(COMP_ALL, false);
|
||||||
}
|
}
|
||||||
else if(activated && !_prevComponentStates.empty())
|
else
|
||||||
|
{
|
||||||
|
if(activated && !_prevComponentStates.empty())
|
||||||
{
|
{
|
||||||
Debug(_log,"Enable Hyperion, recover previous component states");
|
Debug(_log,"Enable Hyperion, recover previous component states");
|
||||||
for(const auto comp : _prevComponentStates)
|
for(const auto &comp : _prevComponentStates)
|
||||||
{
|
{
|
||||||
// if comp was enabled, enable again
|
// if comp was enabled, enable again
|
||||||
if(comp.second)
|
if(comp.second)
|
||||||
|
{
|
||||||
emit _hyperion->compStateChangeRequest(comp.first, true);
|
emit _hyperion->compStateChangeRequest(comp.first, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_prevComponentStates.clear();
|
_prevComponentStates.clear();
|
||||||
setNewComponentState(COMP_ALL, true);
|
setNewComponentState(COMP_ALL, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_inProgress = false;
|
_inProgress = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include <utils/GlobalSignals.h>
|
#include <utils/GlobalSignals.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
// Leddevice includes
|
// LedDevice includes
|
||||||
#include <leddevice/LedDeviceWrapper.h>
|
#include <leddevice/LedDeviceWrapper.h>
|
||||||
|
|
||||||
#include <hyperion/MultiColorAdjustment.h>
|
#include <hyperion/MultiColorAdjustment.h>
|
||||||
@ -46,14 +46,19 @@ Hyperion::Hyperion(quint8 instance, bool readonlyMode)
|
|||||||
, _componentRegister(this)
|
, _componentRegister(this)
|
||||||
, _ledString(hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
|
, _ledString(hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
|
||||||
, _imageProcessor(new ImageProcessor(_ledString, this))
|
, _imageProcessor(new ImageProcessor(_ledString, this))
|
||||||
, _muxer(_ledString.leds().size(), this)
|
, _muxer(static_cast<int>(_ledString.leds().size()), this)
|
||||||
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(_ledString.leds().size(), getSetting(settings::COLOR).object()))
|
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), getSetting(settings::COLOR).object()))
|
||||||
|
, _ledDeviceWrapper(nullptr)
|
||||||
|
, _deviceSmooth(nullptr)
|
||||||
, _effectEngine(nullptr)
|
, _effectEngine(nullptr)
|
||||||
, _messageForwarder(nullptr)
|
, _messageForwarder(nullptr)
|
||||||
, _log(Logger::getInstance("HYPERION"))
|
, _log(Logger::getInstance("HYPERION"))
|
||||||
, _hwLedCount()
|
, _hwLedCount()
|
||||||
, _ledGridSize(hyperion::getLedLayoutGridSize(getSetting(settings::LEDS).array()))
|
, _ledGridSize(hyperion::getLedLayoutGridSize(getSetting(settings::LEDS).array()))
|
||||||
|
, _BGEffectHandler(nullptr)
|
||||||
|
,_captureCont(nullptr)
|
||||||
, _ledBuffer(_ledString.leds().size(), ColorRgb::BLACK)
|
, _ledBuffer(_ledString.leds().size(), ColorRgb::BLACK)
|
||||||
|
, _boblightServer(nullptr)
|
||||||
, _readOnlyMode(readonlyMode)
|
, _readOnlyMode(readonlyMode)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -78,9 +83,9 @@ void Hyperion::start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle hwLedCount
|
// handle hwLedCount
|
||||||
_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount());
|
_hwLedCount = qMax(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount()), getLedCount());
|
||||||
|
|
||||||
// init colororder vector
|
// Initialize colororder vector
|
||||||
for (const Led& led : _ledString.leds())
|
for (const Led& led : _ledString.leds())
|
||||||
{
|
{
|
||||||
_ledStringColorOrder.push_back(led.colorOrder);
|
_ledStringColorOrder.push_back(led.colorOrder);
|
||||||
@ -97,12 +102,14 @@ void Hyperion::start()
|
|||||||
// listen for settings updates of this instance (LEDS & COLOR)
|
// listen for settings updates of this instance (LEDS & COLOR)
|
||||||
connect(_settingsManager, &SettingsManager::settingsChanged, this, &Hyperion::handleSettingsUpdate);
|
connect(_settingsManager, &SettingsManager::settingsChanged, this, &Hyperion::handleSettingsUpdate);
|
||||||
|
|
||||||
|
#if 0
|
||||||
// set color correction activity state
|
// set color correction activity state
|
||||||
const QJsonObject color = getSetting(settings::COLOR).object();
|
const QJsonObject color = getSetting(settings::COLOR).object();
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialize leddevices
|
// initialize LED-devices
|
||||||
QJsonObject ledDevice = getSetting(settings::DEVICE).object();
|
QJsonObject ledDevice = getSetting(settings::DEVICE).object();
|
||||||
ledDevice["currentLedCount"] = int(_hwLedCount); // Inject led count info
|
ledDevice["currentLedCount"] = _hwLedCount; // Inject led count info
|
||||||
|
|
||||||
_ledDeviceWrapper = new LedDeviceWrapper(this);
|
_ledDeviceWrapper = new LedDeviceWrapper(this);
|
||||||
connect(this, &Hyperion::compStateChangeRequest, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
|
connect(this, &Hyperion::compStateChangeRequest, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
|
||||||
@ -115,7 +122,9 @@ void Hyperion::start()
|
|||||||
|
|
||||||
// create the message forwarder only on main instance
|
// create the message forwarder only on main instance
|
||||||
if (_instIndex == 0)
|
if (_instIndex == 0)
|
||||||
|
{
|
||||||
_messageForwarder = new MessageForwarder(this);
|
_messageForwarder = new MessageForwarder(this);
|
||||||
|
}
|
||||||
|
|
||||||
// create the effect engine; needs to be initialized after smoothing!
|
// create the effect engine; needs to be initialized after smoothing!
|
||||||
_effectEngine = new EffectEngine(this);
|
_effectEngine = new EffectEngine(this);
|
||||||
@ -136,14 +145,14 @@ void Hyperion::start()
|
|||||||
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor, this, &Hyperion::setColor);
|
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor, this, &Hyperion::setColor);
|
||||||
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage, this, &Hyperion::setInputImage);
|
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage, this, &Hyperion::setInputImage);
|
||||||
|
|
||||||
// if there is no startup / background eff and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a prioritiy change)
|
// if there is no startup / background effect and no sending capture interface we probably want to push once BLACK (as PrioMuxer won't emit a priority change)
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// boblight, can't live in global scope as it depends on layout
|
// boblight, can't live in global scope as it depends on layout
|
||||||
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
|
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
|
||||||
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
|
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
|
||||||
|
|
||||||
// instance inited, enter thread event loop
|
// instance initiated, enter thread event loop
|
||||||
emit started();
|
emit started();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +187,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
|
|||||||
const QJsonObject obj = config.object();
|
const QJsonObject obj = config.object();
|
||||||
// change in color recreate ledAdjustments
|
// change in color recreate ledAdjustments
|
||||||
delete _raw2ledAdjustment;
|
delete _raw2ledAdjustment;
|
||||||
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(_ledString.leds().size(), obj);
|
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), obj);
|
||||||
|
|
||||||
if (!_raw2ledAdjustment->verifyAdjustments())
|
if (!_raw2ledAdjustment->verifyAdjustments())
|
||||||
{
|
{
|
||||||
@ -189,13 +198,13 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
|
|||||||
{
|
{
|
||||||
const QJsonArray leds = config.array();
|
const QJsonArray leds = config.array();
|
||||||
|
|
||||||
// stop and cache all running effects, as effects depend heavily on ledlayout
|
// stop and cache all running effects, as effects depend heavily on LED-layout
|
||||||
_effectEngine->cacheRunningEffects();
|
_effectEngine->cacheRunningEffects();
|
||||||
|
|
||||||
// ledstring, img processor, muxer, ledGridSize (eff engine image based effects), _ledBuffer and ByteOrder of ledstring
|
// ledstring, img processor, muxer, ledGridSize (effect-engine image based effects), _ledBuffer and ByteOrder of ledstring
|
||||||
_ledString = hyperion::createLedString(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
|
_ledString = hyperion::createLedString(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
|
||||||
_imageProcessor->setLedString(_ledString);
|
_imageProcessor->setLedString(_ledString);
|
||||||
_muxer.updateLedColorsLength(_ledString.leds().size());
|
_muxer.updateLedColorsLength(static_cast<int>(_ledString.leds().size()));
|
||||||
_ledGridSize = hyperion::getLedLayoutGridSize(leds);
|
_ledGridSize = hyperion::getLedLayoutGridSize(leds);
|
||||||
|
|
||||||
std::vector<ColorRgb> color(_ledString.leds().size(), ColorRgb{0,0,0});
|
std::vector<ColorRgb> color(_ledString.leds().size(), ColorRgb{0,0,0});
|
||||||
@ -208,11 +217,11 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle hwLedCount update
|
// handle hwLedCount update
|
||||||
_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount());
|
_hwLedCount = qMax(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount()), getLedCount());
|
||||||
|
|
||||||
// change in leds are also reflected in adjustment
|
// change in leds are also reflected in adjustment
|
||||||
delete _raw2ledAdjustment;
|
delete _raw2ledAdjustment;
|
||||||
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(_ledString.leds().size(), getSetting(settings::COLOR).object());
|
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), getSetting(settings::COLOR).object());
|
||||||
|
|
||||||
// start cached effects
|
// start cached effects
|
||||||
_effectEngine->startCachedEffects();
|
_effectEngine->startCachedEffects();
|
||||||
@ -222,7 +231,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
|
|||||||
QJsonObject dev = config.object();
|
QJsonObject dev = config.object();
|
||||||
|
|
||||||
// handle hwLedCount update
|
// handle hwLedCount update
|
||||||
_hwLedCount = qMax(unsigned(dev["hardwareLedCount"].toInt(getLedCount())), getLedCount());
|
_hwLedCount = qMax(dev["hardwareLedCount"].toInt(getLedCount()), getLedCount());
|
||||||
|
|
||||||
// force ledString update, if device ByteOrder changed
|
// force ledString update, if device ByteOrder changed
|
||||||
if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb"))
|
if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb"))
|
||||||
@ -238,7 +247,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do always reinit until the led devices can handle dynamic changes
|
// do always reinit until the led devices can handle dynamic changes
|
||||||
dev["currentLedCount"] = int(_hwLedCount); // Inject led count info
|
dev["currentLedCount"] = _hwLedCount; // Inject led count info
|
||||||
_ledDeviceWrapper->createLedDevice(dev);
|
_ledDeviceWrapper->createLedDevice(dev);
|
||||||
|
|
||||||
// TODO: Check, if framegrabber frequency is lower than latchtime..., if yes, stop
|
// TODO: Check, if framegrabber frequency is lower than latchtime..., if yes, stop
|
||||||
@ -277,9 +286,9 @@ unsigned Hyperion::updateSmoothingConfig(unsigned id, int settlingTime_ms, doubl
|
|||||||
return _deviceSmooth->updateConfig(id, settlingTime_ms, ledUpdateFrequency_hz, updateDelay);
|
return _deviceSmooth->updateConfig(id, settlingTime_ms, ledUpdateFrequency_hz, updateDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Hyperion::getLedCount() const
|
int Hyperion::getLedCount() const
|
||||||
{
|
{
|
||||||
return _ledString.leds().size();
|
return static_cast<int>(_ledString.leds().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hyperion::setSourceAutoSelect(bool state)
|
void Hyperion::setSourceAutoSelect(bool state)
|
||||||
@ -323,7 +332,9 @@ bool Hyperion::setInput(int priority, const std::vector<ColorRgb>& ledColors, in
|
|||||||
{
|
{
|
||||||
// clear effect if this call does not come from an effect
|
// clear effect if this call does not come from an effect
|
||||||
if(clearEffect)
|
if(clearEffect)
|
||||||
|
{
|
||||||
_effectEngine->channelCleared(priority);
|
_effectEngine->channelCleared(priority);
|
||||||
|
}
|
||||||
|
|
||||||
// if this priority is visible, update immediately
|
// if this priority is visible, update immediately
|
||||||
if(priority == _muxer.getCurrentPriority())
|
if(priority == _muxer.getCurrentPriority())
|
||||||
@ -348,7 +359,9 @@ bool Hyperion::setInputImage(int priority, const Image<ColorRgb>& image, int64_t
|
|||||||
{
|
{
|
||||||
// clear effect if this call does not come from an effect
|
// clear effect if this call does not come from an effect
|
||||||
if(clearEffect)
|
if(clearEffect)
|
||||||
|
{
|
||||||
_effectEngine->channelCleared(priority);
|
_effectEngine->channelCleared(priority);
|
||||||
|
}
|
||||||
|
|
||||||
// if this priority is visible, update immediately
|
// if this priority is visible, update immediately
|
||||||
if(priority == _muxer.getCurrentPriority())
|
if(priority == _muxer.getCurrentPriority())
|
||||||
@ -370,7 +383,9 @@ void Hyperion::setColor(int priority, const std::vector<ColorRgb> &ledColors, in
|
|||||||
{
|
{
|
||||||
// clear effect if this call does not come from an effect
|
// clear effect if this call does not come from an effect
|
||||||
if (clearEffects)
|
if (clearEffects)
|
||||||
|
{
|
||||||
_effectEngine->channelCleared(priority);
|
_effectEngine->channelCleared(priority);
|
||||||
|
}
|
||||||
|
|
||||||
// create full led vector from single/multiple colors
|
// create full led vector from single/multiple colors
|
||||||
size_t size = _ledString.leds().size();
|
size_t size = _ledString.leds().size();
|
||||||
@ -381,13 +396,17 @@ void Hyperion::setColor(int priority, const std::vector<ColorRgb> &ledColors, in
|
|||||||
{
|
{
|
||||||
newLedColors.emplace_back(entry);
|
newLedColors.emplace_back(entry);
|
||||||
if (newLedColors.size() == size)
|
if (newLedColors.size() == size)
|
||||||
|
{
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
end:
|
end:
|
||||||
|
|
||||||
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
|
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
|
||||||
|
{
|
||||||
clear(priority);
|
clear(priority);
|
||||||
|
}
|
||||||
|
|
||||||
// register color
|
// register color
|
||||||
registerInput(priority, hyperion::COMP_COLOR, origin);
|
registerInput(priority, hyperion::COMP_COLOR, origin);
|
||||||
@ -414,13 +433,14 @@ void Hyperion::adjustmentsUpdated()
|
|||||||
|
|
||||||
bool Hyperion::clear(int priority, bool forceClearAll)
|
bool Hyperion::clear(int priority, bool forceClearAll)
|
||||||
{
|
{
|
||||||
|
bool isCleared = false;
|
||||||
if (priority < 0)
|
if (priority < 0)
|
||||||
{
|
{
|
||||||
_muxer.clearAll(forceClearAll);
|
_muxer.clearAll(forceClearAll);
|
||||||
|
|
||||||
// send clearall signal to the effect engine
|
// send clearall signal to the effect engine
|
||||||
_effectEngine->allChannelsCleared();
|
_effectEngine->allChannelsCleared();
|
||||||
return true;
|
isCleared = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -429,9 +449,11 @@ bool Hyperion::clear(int priority, bool forceClearAll)
|
|||||||
_effectEngine->channelCleared(priority);
|
_effectEngine->channelCleared(priority);
|
||||||
|
|
||||||
if (_muxer.clearInput(priority))
|
if (_muxer.clearInput(priority))
|
||||||
return true;
|
{
|
||||||
|
isCleared = true;
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
return isCleared;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Hyperion::getCurrentPriority() const
|
int Hyperion::getCurrentPriority() const
|
||||||
@ -532,9 +554,9 @@ void Hyperion::handleVisibleComponentChanged(hyperion::Components comp)
|
|||||||
|
|
||||||
void Hyperion::handlePriorityChangedLedDevice(const quint8& priority)
|
void Hyperion::handlePriorityChangedLedDevice(const quint8& priority)
|
||||||
{
|
{
|
||||||
quint8 previousPriority = _muxer.getPreviousPriority();
|
int previousPriority = _muxer.getPreviousPriority();
|
||||||
|
|
||||||
Debug(_log,"priority[%u], previousPriority[%u]", priority, previousPriority);
|
Debug(_log,"priority[%d], previousPriority[%d]", priority, previousPriority);
|
||||||
if ( priority == PriorityMuxer::LOWEST_PRIORITY)
|
if ( priority == PriorityMuxer::LOWEST_PRIORITY)
|
||||||
{
|
{
|
||||||
Debug(_log,"No source left -> switch LED-Device off");
|
Debug(_log,"No source left -> switch LED-Device off");
|
||||||
@ -604,8 +626,8 @@ void Hyperion::update()
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill additional hw leds with black
|
// fill additional hardware LEDs with black
|
||||||
if ( _hwLedCount > _ledBuffer.size() )
|
if ( _hwLedCount > static_cast<int>(_ledBuffer.size()) )
|
||||||
{
|
{
|
||||||
_ledBuffer.resize(_hwLedCount, ColorRgb::BLACK);
|
_ledBuffer.resize(_hwLedCount, ColorRgb::BLACK);
|
||||||
}
|
}
|
||||||
@ -623,16 +645,18 @@ void Hyperion::update()
|
|||||||
{
|
{
|
||||||
_deviceSmooth->selectConfig(priorityInfo.smooth_cfg);
|
_deviceSmooth->selectConfig(priorityInfo.smooth_cfg);
|
||||||
|
|
||||||
// feed smoothing in pause mode to maintain a smooth transistion back to smooth mode
|
// feed smoothing in pause mode to maintain a smooth transition back to smooth mode
|
||||||
if (_deviceSmooth->enabled() || _deviceSmooth->pause())
|
if (_deviceSmooth->enabled() || _deviceSmooth->pause())
|
||||||
{
|
{
|
||||||
_deviceSmooth->updateLedValues(_ledBuffer);
|
_deviceSmooth->updateLedValues(_ledBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else
|
#if 0
|
||||||
//{
|
else
|
||||||
// /LEDDevice is disabled
|
{
|
||||||
// Debug(_log, "LEDDevice is disabled - no update required");
|
//LEDDevice is disabled
|
||||||
//}
|
Debug(_log, "LEDDevice is disabled - no update required");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,6 @@
|
|||||||
// hyperion includes
|
// hyperion includes
|
||||||
#include <hyperion/LedString.h>
|
#include <hyperion/LedString.h>
|
||||||
|
|
||||||
LedString::LedString()
|
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
LedString::~LedString()
|
|
||||||
{
|
|
||||||
// empty
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Led>& LedString::leds()
|
std::vector<Led>& LedString::leds()
|
||||||
{
|
{
|
||||||
return mLeds;
|
return mLeds;
|
||||||
|
@ -22,7 +22,7 @@ const int64_t MS_PER_MICRO = 1000;
|
|||||||
|
|
||||||
/// Clamps the rounded values to the byte-interval of [0, 255].
|
/// Clamps the rounded values to the byte-interval of [0, 255].
|
||||||
ALWAYS_INLINE long clampRounded(const floatT x) {
|
ALWAYS_INLINE long clampRounded(const floatT x) {
|
||||||
return std::min(255l, std::max(0l, std::lroundf(x)));
|
return std::min(255L, std::max(0L, std::lroundf(x)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number of bits that are used for shifting the fixed point values
|
/// The number of bits that are used for shifting the fixed point values
|
||||||
@ -43,15 +43,16 @@ const char* SETTINGS_KEY_DECAY = "decay";
|
|||||||
using namespace hyperion;
|
using namespace hyperion;
|
||||||
|
|
||||||
const int64_t DEFAUL_SETTLINGTIME = 200; // settlingtime in ms
|
const int64_t DEFAUL_SETTLINGTIME = 200; // settlingtime in ms
|
||||||
const double DEFAUL_UPDATEFREQUENCY = 25; // updatefrequncy in hz
|
const int DEFAUL_UPDATEFREQUENCY = 25; // updatefrequncy in hz
|
||||||
const int64_t DEFAUL_UPDATEINTERVALL = static_cast<int64_t>(1000 / DEFAUL_UPDATEFREQUENCY); // updateintervall in ms
|
|
||||||
|
constexpr std::chrono::milliseconds DEFAUL_UPDATEINTERVALL{1000/ DEFAUL_UPDATEFREQUENCY};
|
||||||
const unsigned DEFAUL_OUTPUTDEPLAY = 0; // outputdelay in ms
|
const unsigned DEFAUL_OUTPUTDEPLAY = 0; // outputdelay in ms
|
||||||
|
|
||||||
LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion *hyperion)
|
LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion *hyperion)
|
||||||
: QObject(hyperion)
|
: QObject(hyperion)
|
||||||
, _log(Logger::getInstance("SMOOTHING"))
|
, _log(Logger::getInstance("SMOOTHING"))
|
||||||
, _hyperion(hyperion)
|
, _hyperion(hyperion)
|
||||||
, _updateInterval(DEFAUL_UPDATEINTERVALL)
|
, _updateInterval(DEFAUL_UPDATEINTERVALL.count())
|
||||||
, _settlingTime(DEFAUL_SETTLINGTIME)
|
, _settlingTime(DEFAUL_SETTLINGTIME)
|
||||||
, _timer(new QTimer(this))
|
, _timer(new QTimer(this))
|
||||||
, _outputDelay(DEFAUL_OUTPUTDEPLAY)
|
, _outputDelay(DEFAUL_OUTPUTDEPLAY)
|
||||||
@ -61,7 +62,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
|
|||||||
, _pause(false)
|
, _pause(false)
|
||||||
, _currentConfigId(0)
|
, _currentConfigId(0)
|
||||||
, _enabled(false)
|
, _enabled(false)
|
||||||
, tempValues(std::vector<uint64_t>(0, 0l))
|
, tempValues(std::vector<uint64_t>(0, 0L))
|
||||||
{
|
{
|
||||||
// init cfg 0 (default)
|
// init cfg 0 (default)
|
||||||
addConfig(DEFAUL_SETTLINGTIME, DEFAUL_UPDATEFREQUENCY, DEFAUL_OUTPUTDEPLAY);
|
addConfig(DEFAUL_SETTLINGTIME, DEFAUL_UPDATEFREQUENCY, DEFAUL_OUTPUTDEPLAY);
|
||||||
@ -69,7 +70,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
|
|||||||
selectConfig(0, true);
|
selectConfig(0, true);
|
||||||
|
|
||||||
// add pause on cfg 1
|
// add pause on cfg 1
|
||||||
SMOOTHING_CFG cfg = {SmoothingType::Linear, 0, 0, 0, 0, 0, false};
|
SMOOTHING_CFG cfg = {SmoothingType::Linear, false, 0, 0, 0, 0, 0, false, 1};
|
||||||
_cfgList.append(cfg);
|
_cfgList.append(cfg);
|
||||||
|
|
||||||
// listen for comp changes
|
// listen for comp changes
|
||||||
@ -77,7 +78,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
|
|||||||
// timer
|
// timer
|
||||||
connect(_timer, &QTimer::timeout, this, &LinearColorSmoothing::updateLeds);
|
connect(_timer, &QTimer::timeout, this, &LinearColorSmoothing::updateLeds);
|
||||||
|
|
||||||
Info(_log, "LinearColorSmoothing sizeof floatT == %d", (sizeof(floatT)));
|
//Debug(_log, "LinearColorSmoothing sizeof floatT == %d", (sizeof(floatT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJsonDocument &config)
|
void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJsonDocument &config)
|
||||||
@ -89,7 +90,9 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson
|
|||||||
|
|
||||||
QJsonObject obj = config.object();
|
QJsonObject obj = config.object();
|
||||||
if (enabled() != obj["enable"].toBool(true))
|
if (enabled() != obj["enable"].toBool(true))
|
||||||
|
{
|
||||||
setEnable(obj["enable"].toBool(true));
|
setEnable(obj["enable"].toBool(true));
|
||||||
|
}
|
||||||
|
|
||||||
_continuousOutput = obj["continuousOutput"].toBool(true);
|
_continuousOutput = obj["continuousOutput"].toBool(true);
|
||||||
|
|
||||||
@ -105,7 +108,7 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson
|
|||||||
|
|
||||||
cfg.pause = false;
|
cfg.pause = false;
|
||||||
cfg.settlingTime = static_cast<int64_t>(obj["time_ms"].toInt(DEFAUL_SETTLINGTIME));
|
cfg.settlingTime = static_cast<int64_t>(obj["time_ms"].toInt(DEFAUL_SETTLINGTIME));
|
||||||
cfg.updateInterval = static_cast<int64_t>(1000.0 / obj["updateFrequency"].toDouble(DEFAUL_UPDATEFREQUENCY));
|
cfg.updateInterval = static_cast<int>(1000.0 / obj["updateFrequency"].toDouble(DEFAUL_UPDATEFREQUENCY));
|
||||||
cfg.outputRate = obj[SETTINGS_KEY_OUTPUT_RATE].toDouble(DEFAUL_UPDATEFREQUENCY);
|
cfg.outputRate = obj[SETTINGS_KEY_OUTPUT_RATE].toDouble(DEFAUL_UPDATEFREQUENCY);
|
||||||
cfg.interpolationRate = obj[SETTINGS_KEY_INTERPOLATION_RATE].toDouble(DEFAUL_UPDATEFREQUENCY);
|
cfg.interpolationRate = obj[SETTINGS_KEY_INTERPOLATION_RATE].toDouble(DEFAUL_UPDATEFREQUENCY);
|
||||||
cfg.outputDelay = static_cast<unsigned>(obj["updateDelay"].toInt(DEFAUL_OUTPUTDEPLAY));
|
cfg.outputDelay = static_cast<unsigned>(obj["updateDelay"].toInt(DEFAUL_OUTPUTDEPLAY));
|
||||||
@ -155,7 +158,7 @@ int LinearColorSmoothing::updateLedValues(const std::vector<ColorRgb> &ledValues
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
{
|
{
|
||||||
return -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -173,13 +176,13 @@ void LinearColorSmoothing::intitializeComponentVectors(const size_t ledCount)
|
|||||||
|
|
||||||
const size_t len = 3 * ledCount;
|
const size_t len = 3 * ledCount;
|
||||||
|
|
||||||
meanValues = std::vector<floatT>(len, 0.0f);
|
meanValues = std::vector<floatT>(len, 0.0F);
|
||||||
residualErrors = std::vector<floatT>(len, 0.0f);
|
residualErrors = std::vector<floatT>(len, 0.0F);
|
||||||
tempValues = std::vector<uint64_t>(len, 0l);
|
tempValues = std::vector<uint64_t>(len, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zero the temp vector
|
// Zero the temp vector
|
||||||
std::fill(tempValues.begin(), tempValues.end(), 0l);
|
std::fill(tempValues.begin(), tempValues.end(), 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinearColorSmoothing::writeDirect()
|
void LinearColorSmoothing::writeDirect()
|
||||||
@ -232,9 +235,9 @@ void LinearColorSmoothing::assembleAndDitherFrame()
|
|||||||
|
|
||||||
// Update the colors
|
// Update the colors
|
||||||
ColorRgb &prev = _previousValues[i];
|
ColorRgb &prev = _previousValues[i];
|
||||||
prev.red = (uint8_t)ir;
|
prev.red = static_cast<uint8_t>(ir);
|
||||||
prev.green = (uint8_t)ig;
|
prev.green = static_cast<uint8_t>(ig);
|
||||||
prev.blue = (uint8_t)ib;
|
prev.blue = static_cast<uint8_t>(ib);
|
||||||
|
|
||||||
// Determine the component errors
|
// Determine the component errors
|
||||||
residualErrors[3 * i + 0] = fr - ir;
|
residualErrors[3 * i + 0] = fr - ir;
|
||||||
@ -262,15 +265,15 @@ void LinearColorSmoothing::assembleFrame()
|
|||||||
|
|
||||||
// Update the colors
|
// Update the colors
|
||||||
ColorRgb &prev = _previousValues[i];
|
ColorRgb &prev = _previousValues[i];
|
||||||
prev.red = (uint8_t)ir;
|
prev.red = static_cast<uint8_t>(ir);
|
||||||
prev.green = (uint8_t)ig;
|
prev.green = static_cast<uint8_t>(ig);
|
||||||
prev.blue = (uint8_t)ib;
|
prev.blue = static_cast<uint8_t>(ib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void LinearColorSmoothing::aggregateComponents(const std::vector<ColorRgb>& colors, std::vector<uint64_t>& weighted, const floatT weight) {
|
ALWAYS_INLINE void LinearColorSmoothing::aggregateComponents(const std::vector<ColorRgb>& colors, std::vector<uint64_t>& weighted, const floatT weight) {
|
||||||
// Determine the integer-scale by converting the weight to fixed point
|
// Determine the integer-scale by converting the weight to fixed point
|
||||||
const uint64_t scale = (1l<<FPShift) * static_cast<double>(weight);
|
const uint64_t scale = (static_cast<uint64_t>(1L)<<FPShift) * static_cast<double>(weight);
|
||||||
|
|
||||||
const size_t N = colors.size();
|
const size_t N = colors.size();
|
||||||
|
|
||||||
@ -309,7 +312,7 @@ void LinearColorSmoothing::interpolateFrame()
|
|||||||
const int64_t windowStart = now - (MS_PER_MICRO * _settlingTime);
|
const int64_t windowStart = now - (MS_PER_MICRO * _settlingTime);
|
||||||
|
|
||||||
/// The total weight of the frames that were included in our window; sum of the individual weights
|
/// The total weight of the frames that were included in our window; sum of the individual weights
|
||||||
floatT fs = 0.0f;
|
floatT fs = 0.0F;
|
||||||
|
|
||||||
// To calculate the mean component we iterate over all relevant frames;
|
// To calculate the mean component we iterate over all relevant frames;
|
||||||
// from the most recent to the oldest frame that still clips our moving-average window given by time (now)
|
// from the most recent to the oldest frame that still clips our moving-average window given by time (now)
|
||||||
@ -331,7 +334,7 @@ void LinearColorSmoothing::interpolateFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The inverse scaling factor for the color components, clamped to (0, 1.0]; 1.0 for fs < 1, 1 : fs otherwise
|
/// The inverse scaling factor for the color components, clamped to (0, 1.0]; 1.0 for fs < 1, 1 : fs otherwise
|
||||||
const floatT inv_fs = ((fs < 1.0f) ? 1.0f : 1.0f / fs) / (1 << SmallShiftBis);
|
const floatT inv_fs = ((fs < 1.0F) ? 1.0F : 1.0F / fs) / (1 << SmallShiftBis);
|
||||||
|
|
||||||
// Normalize the mean component values for the window (fs)
|
// Normalize the mean component values for the window (fs)
|
||||||
for (size_t i = 0; i < 3 * N; ++i)
|
for (size_t i = 0; i < 3 * N; ++i)
|
||||||
@ -385,8 +388,8 @@ void LinearColorSmoothing::performDecay(const int64_t now) {
|
|||||||
if(_updateInterval <= 0 && !(interpolatePending || writePending)) {
|
if(_updateInterval <= 0 && !(interpolatePending || writePending)) {
|
||||||
const int64_t nextActionExpected = std::min(interpolationTarget, writeTarget);
|
const int64_t nextActionExpected = std::min(interpolationTarget, writeTarget);
|
||||||
const int64_t microsTillNextAction = nextActionExpected - now;
|
const int64_t microsTillNextAction = nextActionExpected - now;
|
||||||
const int64_t SLEEP_MAX_MICROS = 1000l; // We want to use usleep for up to 1ms
|
const int64_t SLEEP_MAX_MICROS = 1000L; // We want to use usleep for up to 1ms
|
||||||
const int64_t SLEEP_RES_MICROS = 100l; // Expected resolution is >= 100µs on stock linux
|
const int64_t SLEEP_RES_MICROS = 100L; // Expected resolution is >= 100µs on stock linux
|
||||||
|
|
||||||
if(microsTillNextAction > SLEEP_RES_MICROS) {
|
if(microsTillNextAction > SLEEP_RES_MICROS) {
|
||||||
const int64_t wait = std::min(microsTillNextAction - SLEEP_RES_MICROS, SLEEP_MAX_MICROS);
|
const int64_t wait = std::min(microsTillNextAction - SLEEP_RES_MICROS, SLEEP_MAX_MICROS);
|
||||||
@ -398,12 +401,12 @@ void LinearColorSmoothing::performDecay(const int64_t now) {
|
|||||||
// Write stats every 30 sec
|
// Write stats every 30 sec
|
||||||
if ((now > (_renderedStatTime + 30 * 1000000)) && (_renderedCounter > _renderedStatCounter))
|
if ((now > (_renderedStatTime + 30 * 1000000)) && (_renderedCounter > _renderedStatCounter))
|
||||||
{
|
{
|
||||||
Info(_log, "decay - rendered frames [%d] (%f/s), interpolated frames [%d] (%f/s) in [%f ms]"
|
Debug(_log, "decay - rendered frames [%d] (%f/s), interpolated frames [%d] (%f/s) in [%f ms]"
|
||||||
, _renderedCounter - _renderedStatCounter
|
, _renderedCounter - _renderedStatCounter
|
||||||
, (1.0f * (_renderedCounter - _renderedStatCounter) / ((now - _renderedStatTime) / 1000000.0f))
|
, (1.0F * (_renderedCounter - _renderedStatCounter) / ((now - _renderedStatTime) / 1000000.0F))
|
||||||
, _interpolationCounter - _interpolationStatCounter
|
, _interpolationCounter - _interpolationStatCounter
|
||||||
, (1.0f * (_interpolationCounter - _interpolationStatCounter) / ((now - _renderedStatTime) / 1000000.0f))
|
, (1.0F * (_interpolationCounter - _interpolationStatCounter) / ((now - _renderedStatTime) / 1000000.0F))
|
||||||
, (now - _renderedStatTime) / 1000.0f
|
, (now - _renderedStatTime) / 1000.0F
|
||||||
);
|
);
|
||||||
_renderedStatTime = now;
|
_renderedStatTime = now;
|
||||||
_renderedStatCounter = _renderedCounter;
|
_renderedStatCounter = _renderedCounter;
|
||||||
@ -413,7 +416,7 @@ void LinearColorSmoothing::performDecay(const int64_t now) {
|
|||||||
|
|
||||||
void LinearColorSmoothing::performLinear(const int64_t now) {
|
void LinearColorSmoothing::performLinear(const int64_t now) {
|
||||||
const int64_t deltaTime = _targetTime - now;
|
const int64_t deltaTime = _targetTime - now;
|
||||||
const float k = 1.0f - 1.0f * deltaTime / (_targetTime - _previousWriteTime);
|
const float k = 1.0F - 1.0F * deltaTime / (_targetTime - _previousWriteTime);
|
||||||
const size_t N = _previousValues.size();
|
const size_t N = _previousValues.size();
|
||||||
|
|
||||||
for (size_t i = 0; i < N; ++i)
|
for (size_t i = 0; i < N; ++i)
|
||||||
@ -461,7 +464,7 @@ void LinearColorSmoothing::updateLeds()
|
|||||||
|
|
||||||
void LinearColorSmoothing::rememberFrame(const std::vector<ColorRgb> &ledColors)
|
void LinearColorSmoothing::rememberFrame(const std::vector<ColorRgb> &ledColors)
|
||||||
{
|
{
|
||||||
//Info(_log, "rememberFrame - before _frameQueue.size() [%d]", _frameQueue.size());
|
//Debug(_log, "rememberFrame - before _frameQueue.size() [%d]", _frameQueue.size());
|
||||||
|
|
||||||
const int64_t now = micros();
|
const int64_t now = micros();
|
||||||
|
|
||||||
@ -478,7 +481,7 @@ void LinearColorSmoothing::rememberFrame(const std::vector<ColorRgb> &ledColors)
|
|||||||
|
|
||||||
if (p > 0)
|
if (p > 0)
|
||||||
{
|
{
|
||||||
//Info(_log, "rememberFrame - erasing %d frames", p);
|
//Debug(_log, "rememberFrame - erasing %d frames", p);
|
||||||
_frameQueue.erase(_frameQueue.begin(), _frameQueue.begin() + p);
|
_frameQueue.erase(_frameQueue.begin(), _frameQueue.begin() + p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +489,7 @@ void LinearColorSmoothing::rememberFrame(const std::vector<ColorRgb> &ledColors)
|
|||||||
const REMEMBERED_FRAME frame = REMEMBERED_FRAME(now, ledColors);
|
const REMEMBERED_FRAME frame = REMEMBERED_FRAME(now, ledColors);
|
||||||
_frameQueue.push_back(frame);
|
_frameQueue.push_back(frame);
|
||||||
|
|
||||||
//Info(_log, "rememberFrame - after _frameQueue.size() [%d]", _frameQueue.size());
|
//Debug(_log, "rememberFrame - after _frameQueue.size() [%d]", _frameQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -518,10 +521,12 @@ void LinearColorSmoothing::queueColors(const std::vector<ColorRgb> &ledColors)
|
|||||||
{
|
{
|
||||||
// Push new colors in the delay-buffer
|
// Push new colors in the delay-buffer
|
||||||
if (_writeToLedsEnable)
|
if (_writeToLedsEnable)
|
||||||
|
{
|
||||||
_outputQueue.push_back(ledColors);
|
_outputQueue.push_back(ledColors);
|
||||||
|
}
|
||||||
|
|
||||||
// If the delay-buffer is filled pop the front and write to device
|
// If the delay-buffer is filled pop the front and write to device
|
||||||
if (_outputQueue.size() > 0)
|
if (!_outputQueue.empty())
|
||||||
{
|
{
|
||||||
if (_outputQueue.size() > _outputDelay || !_writeToLedsEnable)
|
if (_outputQueue.size() > _outputDelay || !_writeToLedsEnable)
|
||||||
{
|
{
|
||||||
@ -581,7 +586,7 @@ unsigned LinearColorSmoothing::addConfig(int settlingTime_ms, double ledUpdateFr
|
|||||||
SmoothingType::Linear,
|
SmoothingType::Linear,
|
||||||
false,
|
false,
|
||||||
settlingTime_ms,
|
settlingTime_ms,
|
||||||
int64_t(1000.0 / ledUpdateFrequency_hz),
|
static_cast<int>(1000.0 / ledUpdateFrequency_hz),
|
||||||
ledUpdateFrequency_hz,
|
ledUpdateFrequency_hz,
|
||||||
ledUpdateFrequency_hz,
|
ledUpdateFrequency_hz,
|
||||||
updateDelay,
|
updateDelay,
|
||||||
@ -603,7 +608,7 @@ unsigned LinearColorSmoothing::updateConfig(unsigned cfgID, int settlingTime_ms,
|
|||||||
SmoothingType::Linear,
|
SmoothingType::Linear,
|
||||||
false,
|
false,
|
||||||
settlingTime_ms,
|
settlingTime_ms,
|
||||||
int64_t(1000.0 / ledUpdateFrequency_hz),
|
static_cast<int>(1000.0 / ledUpdateFrequency_hz),
|
||||||
ledUpdateFrequency_hz,
|
ledUpdateFrequency_hz,
|
||||||
ledUpdateFrequency_hz,
|
ledUpdateFrequency_hz,
|
||||||
updateDelay,
|
updateDelay,
|
||||||
@ -630,7 +635,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Debug( _log, "selectConfig FORCED - _currentConfigId [%u], force [%d]", cfg, force);
|
//Debug( _log, "selectConfig FORCED - _currentConfigId [%u], force [%d]", cfg, force);
|
||||||
if (cfg < (unsigned)_cfgList.count())
|
if (cfg < static_cast<uint>(_cfgList.count()) )
|
||||||
{
|
{
|
||||||
_smoothingType = _cfgList[cfg].smoothingType;
|
_smoothingType = _cfgList[cfg].smoothingType;
|
||||||
_settlingTime = _cfgList[cfg].settlingTime;
|
_settlingTime = _cfgList[cfg].settlingTime;
|
||||||
@ -642,14 +647,14 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
|
|||||||
_interpolationIntervalMicros = int64_t(1000000.0 / _interpolationRate);
|
_interpolationIntervalMicros = int64_t(1000000.0 / _interpolationRate);
|
||||||
_dithering = _cfgList[cfg].dithering;
|
_dithering = _cfgList[cfg].dithering;
|
||||||
_decay = _cfgList[cfg].decay;
|
_decay = _cfgList[cfg].decay;
|
||||||
_invWindow = 1.0f / (MS_PER_MICRO * _settlingTime);
|
_invWindow = 1.0F / (MS_PER_MICRO * _settlingTime);
|
||||||
|
|
||||||
// Set _weightFrame based on the given decay
|
// Set _weightFrame based on the given decay
|
||||||
const float decay = _decay;
|
const float decay = _decay;
|
||||||
const floatT inv_window = _invWindow;
|
const floatT inv_window = _invWindow;
|
||||||
|
|
||||||
// For decay != 1 use power-based approach for calculating the moving average values
|
// For decay != 1 use power-based approach for calculating the moving average values
|
||||||
if(std::abs(decay - 1.0f) > std::numeric_limits<float>::epsilon()) {
|
if(std::abs(decay - 1.0F) > std::numeric_limits<float>::epsilon()) {
|
||||||
// Exponential Decay
|
// Exponential Decay
|
||||||
_weightFrame = [inv_window,decay](const int64_t fs, const int64_t fe, const int64_t ws) {
|
_weightFrame = [inv_window,decay](const int64_t fs, const int64_t fe, const int64_t ws) {
|
||||||
const floatT s = (fs - ws) * inv_window;
|
const floatT s = (fs - ws) * inv_window;
|
||||||
@ -660,7 +665,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
|
|||||||
} else {
|
} else {
|
||||||
// For decay == 1 use linear interpolation of the moving average values
|
// For decay == 1 use linear interpolation of the moving average values
|
||||||
// Linear Decay
|
// Linear Decay
|
||||||
_weightFrame = [inv_window](const int64_t fs, const int64_t fe, const int64_t ws) {
|
_weightFrame = [inv_window](const int64_t fs, const int64_t fe, const int64_t /*ws*/) {
|
||||||
// Linear weighting = (end - start) * scale
|
// Linear weighting = (end - start) * scale
|
||||||
return static_cast<floatT>((fe - fs) * inv_window);
|
return static_cast<floatT>((fe - fs) * inv_window);
|
||||||
};
|
};
|
||||||
@ -693,7 +698,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
|
|||||||
// DebugIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId );
|
// DebugIf( _pause, _log, "set smoothing cfg: %d, pause", _currentConfigId );
|
||||||
|
|
||||||
const float thalf = (1.0-std::pow(1.0/2, 1.0/_decay))*_settlingTime;
|
const float thalf = (1.0-std::pow(1.0/2, 1.0/_decay))*_settlingTime;
|
||||||
Info( _log, "%s - Time: %d ms, outputRate %f Hz, interpolationRate: %f Hz, timer: %d ms, Dithering: %d, Decay: %f -> HalfTime: %f ms", _smoothingType == SmoothingType::Decay ? "decay" : "linear", _settlingTime, _outputRate, _interpolationRate, _updateInterval, _dithering ? 1 : 0, _decay, thalf);
|
Debug( _log, "cfg [%d]: Type: %s - Time: %d ms, outputRate %f Hz, interpolationRate: %f Hz, timer: %d ms, Dithering: %d, Decay: %f -> HalfTime: %f ms", cfg, _smoothingType == SmoothingType::Decay ? "decay" : "linear", _settlingTime, _outputRate, _interpolationRate, _updateInterval, _dithering ? 1 : 0, _decay, thalf);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
// hyperion incluse
|
// hyperion includes
|
||||||
#include <leddevice/LedDevice.h>
|
#include <leddevice/LedDevice.h>
|
||||||
#include <utils/Components.h>
|
#include <utils/Components.h>
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ enum SmoothingType {
|
|||||||
Decay,
|
Decay,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Linear Smooting class
|
/// Linear Smoothing class
|
||||||
///
|
///
|
||||||
/// This class processes the requested led values and forwards them to the device after applying
|
/// This class processes the requested led values and forwards them to the device after applying
|
||||||
/// a smoothing effect to LED colors. This class can be handled as a generic LedDevice.
|
/// a smoothing effect to LED colors. This class can be handled as a generic LedDevice.
|
||||||
@ -94,12 +94,12 @@ public:
|
|||||||
bool enabled() const { return _enabled && !_pause; }
|
bool enabled() const { return _enabled && !_pause; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Add a new smoothing cfg which can be used with selectConfig()
|
/// @brief Add a new smoothing configuration which can be used with selectConfig()
|
||||||
/// @param settlingTime_ms The buffer time
|
/// @param settlingTime_ms The buffer time
|
||||||
/// @param ledUpdateFrequency_hz The frequency of update
|
/// @param ledUpdateFrequency_hz The frequency of update
|
||||||
/// @param updateDelay The delay
|
/// @param updateDelay The delay
|
||||||
///
|
///
|
||||||
/// @return The index of the cfg which can be passed to selectConfig()
|
/// @return The index of the configuration, which can be passed to selectConfig()
|
||||||
///
|
///
|
||||||
unsigned addConfig(int settlingTime_ms, double ledUpdateFrequency_hz = 25.0, unsigned updateDelay = 0);
|
unsigned addConfig(int settlingTime_ms, double ledUpdateFrequency_hz = 25.0, unsigned updateDelay = 0);
|
||||||
|
|
||||||
@ -112,12 +112,12 @@ public:
|
|||||||
/// @param ledUpdateFrequency_hz The frequency of update
|
/// @param ledUpdateFrequency_hz The frequency of update
|
||||||
/// @param updateDelay The delay
|
/// @param updateDelay The delay
|
||||||
///
|
///
|
||||||
/// @return The index of the cfg which can be passed to selectConfig()
|
/// @return The index of the configuration, which can be passed to selectConfig()
|
||||||
///
|
///
|
||||||
unsigned updateConfig(unsigned cfgID, int settlingTime_ms, double ledUpdateFrequency_hz = 25.0, unsigned updateDelay = 0);
|
unsigned updateConfig(unsigned cfgID, int settlingTime_ms, double ledUpdateFrequency_hz = 25.0, unsigned updateDelay = 0);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief select a smoothing cfg given by cfg index from addConfig()
|
/// @brief select a smoothing configuration given by cfg index from addConfig()
|
||||||
/// @param cfg The index to use
|
/// @param cfg The index to use
|
||||||
/// @param force Overwrite in any case the current values (used for cfg 0 settings update)
|
/// @param force Overwrite in any case the current values (used for cfg 0 settings update)
|
||||||
///
|
///
|
||||||
@ -128,7 +128,7 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
///
|
///
|
||||||
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
/// @param type settingyType from enum
|
/// @param type settingType from enum
|
||||||
/// @param config configuration object
|
/// @param config configuration object
|
||||||
///
|
///
|
||||||
void handleSettingsUpdate(settings::type type, const QJsonDocument &config);
|
void handleSettingsUpdate(settings::type type, const QJsonDocument &config);
|
||||||
@ -167,7 +167,7 @@ private:
|
|||||||
Hyperion *_hyperion;
|
Hyperion *_hyperion;
|
||||||
|
|
||||||
/// The interval at which to update the leds (msec)
|
/// The interval at which to update the leds (msec)
|
||||||
int64_t _updateInterval;
|
int _updateInterval;
|
||||||
|
|
||||||
/// The time after which the updated led values have been fully applied (msec)
|
/// The time after which the updated led values have been fully applied (msec)
|
||||||
int64_t _settlingTime;
|
int64_t _settlingTime;
|
||||||
@ -243,7 +243,7 @@ private:
|
|||||||
/// The interval time in microseconds for interpolation of LED Frames.
|
/// The interval time in microseconds for interpolation of LED Frames.
|
||||||
int64_t _interpolationIntervalMicros;
|
int64_t _interpolationIntervalMicros;
|
||||||
|
|
||||||
/// Whether to apply temproral dithering to diffuse rounding errors when downsampling to 8-bit RGB colors.
|
/// Whether to apply temporal dithering to diffuse rounding errors when downsampling to 8-bit RGB colors.
|
||||||
bool _dithering;
|
bool _dithering;
|
||||||
|
|
||||||
/// The decay power > 0. A value of exactly 1 is linear decay, higher numbers indicate a faster decay rate.
|
/// The decay power > 0. A value of exactly 1 is linear decay, higher numbers indicate a faster decay rate.
|
||||||
@ -263,8 +263,8 @@ private:
|
|||||||
/// The time of the smoothing window.
|
/// The time of the smoothing window.
|
||||||
int64_t settlingTime;
|
int64_t settlingTime;
|
||||||
|
|
||||||
/// The interval time in millisecons of the timer used for scheduling LED update operations. A value of 0 indicates sub-millisecond timing.
|
/// The interval time in milliseconds of the timer used for scheduling LED update operations. A value of 0 indicates sub-millisecond timing.
|
||||||
int64_t updateInterval;
|
int updateInterval;
|
||||||
|
|
||||||
// The rate at which color frames should be written to LED device.
|
// The rate at which color frames should be written to LED device.
|
||||||
double outputRate;
|
double outputRate;
|
||||||
@ -275,13 +275,13 @@ private:
|
|||||||
/// The number of frames the output is delayed
|
/// The number of frames the output is delayed
|
||||||
unsigned outputDelay;
|
unsigned outputDelay;
|
||||||
|
|
||||||
/// Whether to apply temproral dithering to diffuse rounding errors when downsampling to 8-bit RGB colors. Improves color accuracy.
|
/// Whether to apply temporal dithering to diffuse rounding errors when downsampling to 8-bit RGB colors. Improves color accuracy.
|
||||||
bool dithering;
|
bool dithering;
|
||||||
|
|
||||||
/// The decay power > 0. A value of exactly 1 is linear decay, higher numbers indicate a faster decay rate.
|
/// The decay power > 0. A value of exactly 1 is linear decay, higher numbers indicate a faster decay rate.
|
||||||
double decay;
|
double decay;
|
||||||
};
|
};
|
||||||
/// smooth config list
|
/// smooth configuration list
|
||||||
QVector<SMOOTHING_CFG> _cfgList;
|
QVector<SMOOTHING_CFG> _cfgList;
|
||||||
|
|
||||||
unsigned _currentConfigId;
|
unsigned _currentConfigId;
|
||||||
@ -329,7 +329,7 @@ private:
|
|||||||
/// Prepares a frame of LED colors by interpolating using the current smoothing window
|
/// Prepares a frame of LED colors by interpolating using the current smoothing window
|
||||||
void interpolateFrame();
|
void interpolateFrame();
|
||||||
|
|
||||||
/// Performes a decay-based smoothing effect. The frames are interpolated based on their age and a given decay-power.
|
/// Performs a decay-based smoothing effect. The frames are interpolated based on their age and a given decay-power.
|
||||||
///
|
///
|
||||||
/// The ingress frames that were received during the current smoothing window are reduced using a weighted moving average
|
/// The ingress frames that were received during the current smoothing window are reduced using a weighted moving average
|
||||||
/// by applying the weighting-function to the color components of each frame.
|
/// by applying the weighting-function to the color components of each frame.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
#include <hyperion/MultiColorAdjustment.h>
|
#include <hyperion/MultiColorAdjustment.h>
|
||||||
|
|
||||||
MultiColorAdjustment::MultiColorAdjustment(unsigned ledCnt)
|
MultiColorAdjustment::MultiColorAdjustment(int ledCnt)
|
||||||
: _ledAdjustments(ledCnt, nullptr)
|
: _ledAdjustments(ledCnt, nullptr)
|
||||||
, _log(Logger::getInstance("ADJUSTMENT"))
|
, _log(Logger::getInstance("ADJUSTMENT"))
|
||||||
{
|
{
|
||||||
@ -25,7 +25,7 @@ void MultiColorAdjustment::addAdjustment(ColorAdjustment * adjustment)
|
|||||||
_adjustment.push_back(adjustment);
|
_adjustment.push_back(adjustment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiColorAdjustment::setAdjustmentForLed(const QString& id, unsigned startLed, unsigned endLed)
|
void MultiColorAdjustment::setAdjustmentForLed(const QString& id, int startLed, int endLed)
|
||||||
{
|
{
|
||||||
// abort
|
// abort
|
||||||
if(startLed > endLed)
|
if(startLed > endLed)
|
||||||
@ -34,19 +34,19 @@ void MultiColorAdjustment::setAdjustmentForLed(const QString& id, unsigned start
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// catch wrong values
|
// catch wrong values
|
||||||
if(endLed > _ledAdjustments.size()-1)
|
if(endLed > static_cast<int>(_ledAdjustments.size()-1))
|
||||||
{
|
{
|
||||||
Warning(_log,"The color calibration 'LED index' field has leds specified which aren't part of your led layout");
|
Warning(_log,"The color calibration 'LED index' field has LEDs specified which aren't part of your led layout");
|
||||||
endLed = _ledAdjustments.size()-1;
|
endLed = static_cast<int>(_ledAdjustments.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the identified adjustment (don't care if is nullptr)
|
// Get the identified adjustment (don't care if is nullptr)
|
||||||
ColorAdjustment * adjustment = getAdjustment(id);
|
ColorAdjustment * adjustment = getAdjustment(id);
|
||||||
|
|
||||||
//Debug(_log,"ColorAdjustment Profile [%s], startLed[%u], endLed[%u]", QSTRING_CSTR(id), startLed, endLed);
|
//Debug(_log,"ColorAdjustment Profile [%s], startLed[%d], endLed[%d]", QSTRING_CSTR(id), startLed, endLed);
|
||||||
for (unsigned iLed=startLed; iLed<=endLed; ++iLed)
|
for (int iLed=startLed; iLed<=endLed; ++iLed)
|
||||||
{
|
{
|
||||||
//Debug(_log,"_ledAdjustments [%u] -> [%p]", iLed, adjustment);
|
//Debug(_log,"_ledAdjustments [%d] -> [%p]", iLed, adjustment);
|
||||||
_ledAdjustments[iLed] = adjustment;
|
_ledAdjustments[iLed] = adjustment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ bool PriorityMuxer::setSourceAutoSelectEnabled(bool enable, bool update)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PriorityMuxer::setPriority(uint8_t priority)
|
bool PriorityMuxer::setPriority(int priority)
|
||||||
{
|
{
|
||||||
if(_activeInputs.contains(priority))
|
if(_activeInputs.contains(priority))
|
||||||
{
|
{
|
||||||
@ -141,7 +141,8 @@ hyperion::Components PriorityMuxer::getComponentOfPriority(int priority) const
|
|||||||
void PriorityMuxer::registerInput(int priority, hyperion::Components component, const QString& origin, const QString& owner, unsigned smooth_cfg)
|
void PriorityMuxer::registerInput(int priority, hyperion::Components component, const QString& origin, const QString& owner, unsigned smooth_cfg)
|
||||||
{
|
{
|
||||||
// detect new registers
|
// detect new registers
|
||||||
bool newInput = false, reusedInput = false;
|
bool newInput = false;
|
||||||
|
bool reusedInput = false;
|
||||||
if (!_activeInputs.contains(priority))
|
if (!_activeInputs.contains(priority))
|
||||||
newInput = true;
|
newInput = true;
|
||||||
else if(_prevVisComp == component || _activeInputs[priority].componentId == component)
|
else if(_prevVisComp == component || _activeInputs[priority].componentId == component)
|
||||||
@ -165,7 +166,9 @@ void PriorityMuxer::registerInput(int priority, hyperion::Components component,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reusedInput)
|
if (reusedInput)
|
||||||
|
{
|
||||||
emit timeRunner();
|
emit timeRunner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PriorityMuxer::setInput(int priority, const std::vector<ColorRgb>& ledColors, int64_t timeout_ms)
|
bool PriorityMuxer::setInput(int priority, const std::vector<ColorRgb>& ledColors, int64_t timeout_ms)
|
||||||
@ -203,7 +206,9 @@ bool PriorityMuxer::setInput(int priority, const std::vector<ColorRgb>& ledColor
|
|||||||
{
|
{
|
||||||
Debug(_log, "Priority %d is now %s", priority, active ? "active" : "inactive");
|
Debug(_log, "Priority %d is now %s", priority, active ? "active" : "inactive");
|
||||||
if (_currentPriority < priority)
|
if (_currentPriority < priority)
|
||||||
|
{
|
||||||
emit prioritiesChanged();
|
emit prioritiesChanged();
|
||||||
|
}
|
||||||
setCurrentTime();
|
setCurrentTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +223,7 @@ bool PriorityMuxer::setInputImage(int priority, const Image<ColorRgb>& image, in
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calc final timeout
|
// calculate final timeout
|
||||||
if(timeout_ms > 0)
|
if(timeout_ms > 0)
|
||||||
timeout_ms = QDateTime::currentMSecsSinceEpoch() + timeout_ms;
|
timeout_ms = QDateTime::currentMSecsSinceEpoch() + timeout_ms;
|
||||||
|
|
||||||
@ -252,13 +257,13 @@ bool PriorityMuxer::setInputImage(int priority, const Image<ColorRgb>& image, in
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PriorityMuxer::setInputInactive(quint8 priority)
|
bool PriorityMuxer::setInputInactive(int priority)
|
||||||
{
|
{
|
||||||
Image<ColorRgb> image;
|
Image<ColorRgb> image;
|
||||||
return setInputImage(priority, image, -100);
|
return setInputImage(priority, image, -100);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PriorityMuxer::clearInput(uint8_t priority)
|
bool PriorityMuxer::clearInput(int priority)
|
||||||
{
|
{
|
||||||
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))
|
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))
|
||||||
{
|
{
|
||||||
@ -288,9 +293,11 @@ void PriorityMuxer::clearAll(bool forceClearAll)
|
|||||||
{
|
{
|
||||||
const InputInfo info = getInputInfo(key);
|
const InputInfo info = getInputInfo(key);
|
||||||
if ((info.componentId == hyperion::COMP_COLOR || info.componentId == hyperion::COMP_EFFECT || info.componentId == hyperion::COMP_IMAGE) && key < PriorityMuxer::LOWEST_PRIORITY-1)
|
if ((info.componentId == hyperion::COMP_COLOR || info.componentId == hyperion::COMP_EFFECT || info.componentId == hyperion::COMP_IMAGE) && key < PriorityMuxer::LOWEST_PRIORITY-1)
|
||||||
|
{
|
||||||
clearInput(key);
|
clearInput(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PriorityMuxer::setCurrentTime()
|
void PriorityMuxer::setCurrentTime()
|
||||||
@ -303,7 +310,7 @@ void PriorityMuxer::setCurrentTime()
|
|||||||
{
|
{
|
||||||
if (infoIt->timeoutTime_ms > 0 && infoIt->timeoutTime_ms <= now)
|
if (infoIt->timeoutTime_ms > 0 && infoIt->timeoutTime_ms <= now)
|
||||||
{
|
{
|
||||||
quint8 tPrio = infoIt->priority;
|
int tPrio = infoIt->priority;
|
||||||
infoIt = _activeInputs.erase(infoIt);
|
infoIt = _activeInputs.erase(infoIt);
|
||||||
Debug(_log,"Timeout clear for priority %d",tPrio);
|
Debug(_log,"Timeout clear for priority %d",tPrio);
|
||||||
emit prioritiesChanged();
|
emit prioritiesChanged();
|
||||||
@ -321,7 +328,7 @@ void PriorityMuxer::setCurrentTime()
|
|||||||
++infoIt;
|
++infoIt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eval if manual selected prio is still available
|
// evaluate, if manual selected priority is still available
|
||||||
if(!_sourceAutoSelectEnabled)
|
if(!_sourceAutoSelectEnabled)
|
||||||
{
|
{
|
||||||
if(_activeInputs.contains(_manualSelectedPriority))
|
if(_activeInputs.contains(_manualSelectedPriority))
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"options":
|
"options":
|
||||||
{
|
{
|
||||||
"enum_titles": ["edt_conf_enum_automatic","AMLogic","DispmanX","DirectX9","Framebuffer","OSX","QT","X11","XCB"]
|
"enum_titles": ["edt_conf_enum_automatic","AMLogic","DispmanX","DirectX9","Framebuffer","OSX","QT","X11","XCB"]
|
||||||
|
|
||||||
},
|
},
|
||||||
"default" : "auto",
|
"default" : "auto",
|
||||||
"propertyOrder" : 1
|
"propertyOrder" : 1
|
||||||
|
@ -8,22 +8,22 @@
|
|||||||
"top": {
|
"top": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"default": 8
|
"default": 1
|
||||||
},
|
},
|
||||||
"bottom": {
|
"bottom": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"default": 8
|
"default": 0
|
||||||
},
|
},
|
||||||
"left": {
|
"left": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"default": 5
|
"default": 0
|
||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"default": 5
|
"default": 0
|
||||||
},
|
},
|
||||||
"glength": {
|
"glength": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
"title" : "edt_conf_smooth_interpolationRate_title",
|
"title" : "edt_conf_smooth_interpolationRate_title",
|
||||||
"minimum" : 1.0,
|
"minimum" : 1.0,
|
||||||
"maximum": 1000.0,
|
"maximum": 1000.0,
|
||||||
"default" : 0,
|
"default" : 1.0,
|
||||||
"append" : "edt_append_hz",
|
"append" : "edt_append_hz",
|
||||||
"propertyOrder" : 5
|
"propertyOrder" : 5
|
||||||
},
|
},
|
||||||
@ -57,7 +57,7 @@
|
|||||||
"title" : "edt_conf_smooth_outputRate_title",
|
"title" : "edt_conf_smooth_outputRate_title",
|
||||||
"minimum" : 1.0,
|
"minimum" : 1.0,
|
||||||
"maximum": 1000.0,
|
"maximum": 1000.0,
|
||||||
"default" : 0,
|
"default" : 1.0,
|
||||||
"append" : "edt_append_hz",
|
"append" : "edt_append_hz",
|
||||||
"propertyOrder" : 6
|
"propertyOrder" : 6
|
||||||
},
|
},
|
||||||
|
@ -149,7 +149,7 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
|
|||||||
|
|
||||||
_colorOrder = deviceConfig["colorOrder"].toString("RGB");
|
_colorOrder = deviceConfig["colorOrder"].toString("RGB");
|
||||||
|
|
||||||
setLedCount( static_cast<unsigned int>( deviceConfig["currentLedCount"].toInt(1) ) ); // property injected to reflect real led count
|
setLedCount( deviceConfig["currentLedCount"].toInt(1) ); // property injected to reflect real led count
|
||||||
setLatchTime( deviceConfig["latchTime"].toInt( _latchTime_ms ) );
|
setLatchTime( deviceConfig["latchTime"].toInt( _latchTime_ms ) );
|
||||||
setRewriteTime ( deviceConfig["rewriteTime"].toInt( _refreshTimerInterval_ms) );
|
setRewriteTime ( deviceConfig["rewriteTime"].toInt( _refreshTimerInterval_ms) );
|
||||||
|
|
||||||
@ -178,11 +178,11 @@ int LedDevice::updateLeds(const std::vector<ColorRgb>& ledValues)
|
|||||||
if ( !_isEnabled || !_isOn || !_isDeviceReady || _isDeviceInError )
|
if ( !_isEnabled || !_isOn || !_isDeviceReady || _isDeviceInError )
|
||||||
{
|
{
|
||||||
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready! ";
|
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready! ";
|
||||||
return -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qint64 elapsedTimeMs = _lastWriteTime.msecsTo(QDateTime::currentDateTime());
|
qint64 elapsedTimeMs = _lastWriteTime.msecsTo( QDateTime::currentDateTime() );
|
||||||
if (_latchTime_ms == 0 || elapsedTimeMs >= _latchTime_ms)
|
if (_latchTime_ms == 0 || elapsedTimeMs >= _latchTime_ms)
|
||||||
{
|
{
|
||||||
//std::cout << "LedDevice::updateLeds(), Elapsed time since last write (" << elapsedTimeMs << ") ms > _latchTime_ms (" << _latchTime_ms << ") ms" << std::endl;
|
//std::cout << "LedDevice::updateLeds(), Elapsed time since last write (" << elapsedTimeMs << ") ms > _latchTime_ms (" << _latchTime_ms << ") ms" << std::endl;
|
||||||
@ -356,7 +356,7 @@ bool LedDevice::restoreState()
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDevice::discover()
|
QJsonObject LedDevice::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
|
|
||||||
@ -392,8 +392,9 @@ QJsonObject LedDevice::getProperties(const QJsonObject& params)
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDevice::setLedCount(unsigned int ledCount)
|
void LedDevice::setLedCount(int ledCount)
|
||||||
{
|
{
|
||||||
|
assert(ledCount >= 0);
|
||||||
_ledCount = ledCount;
|
_ledCount = ledCount;
|
||||||
_ledRGBCount = _ledCount * sizeof(ColorRgb);
|
_ledRGBCount = _ledCount * sizeof(ColorRgb);
|
||||||
_ledRGBWCount = _ledCount * sizeof(ColorRgbw);
|
_ledRGBWCount = _ledCount * sizeof(ColorRgbw);
|
||||||
@ -401,12 +402,14 @@ void LedDevice::setLedCount(unsigned int ledCount)
|
|||||||
|
|
||||||
void LedDevice::setLatchTime( int latchTime_ms )
|
void LedDevice::setLatchTime( int latchTime_ms )
|
||||||
{
|
{
|
||||||
|
assert(latchTime_ms >= 0);
|
||||||
_latchTime_ms = latchTime_ms;
|
_latchTime_ms = latchTime_ms;
|
||||||
Debug(_log, "LatchTime updated to %dms", _latchTime_ms);
|
Debug(_log, "LatchTime updated to %dms", _latchTime_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDevice::setRewriteTime( int rewriteTime_ms )
|
void LedDevice::setRewriteTime( int rewriteTime_ms )
|
||||||
{
|
{
|
||||||
|
assert(rewriteTime_ms >= 0);
|
||||||
_refreshTimerInterval_ms = rewriteTime_ms;
|
_refreshTimerInterval_ms = rewriteTime_ms;
|
||||||
|
|
||||||
if ( _refreshTimerInterval_ms > 0 )
|
if ( _refreshTimerInterval_ms > 0 )
|
||||||
@ -441,7 +444,7 @@ void LedDevice::printLedValues(const std::vector<ColorRgb>& ledValues)
|
|||||||
std::cout << "]" << std::endl;
|
std::cout << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LedDevice::uint8_t_to_hex_string(const uint8_t * data, const qint64 size, qint64 number) const
|
QString LedDevice::uint8_t_to_hex_string(const uint8_t * data, const int size, int number) const
|
||||||
{
|
{
|
||||||
if ( number <= 0 || number > size)
|
if ( number <= 0 || number > size)
|
||||||
{
|
{
|
||||||
|
@ -36,16 +36,17 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig)
|
|||||||
|
|
||||||
if (device == nullptr)
|
if (device == nullptr)
|
||||||
{
|
{
|
||||||
Error(log, "Dummy device used, because configured device '%s' is unknown", QSTRING_CSTR(type) );
|
|
||||||
throw std::runtime_error("unknown device");
|
throw std::runtime_error("unknown device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
|
QString dummyDeviceType = "file";
|
||||||
|
Error(log, "Dummy device type (%s) used, because configured device '%s' throws error '%s'", QSTRING_CSTR(dummyDeviceType), QSTRING_CSTR(type), e.what());
|
||||||
|
|
||||||
Error(log, "Dummy device used, because configured device '%s' throws error '%s'", QSTRING_CSTR(type), e.what());
|
QJsonObject dummyDeviceConfig;
|
||||||
const QJsonObject dummyDeviceConfig;
|
dummyDeviceConfig.insert("type",dummyDeviceType);
|
||||||
device = LedDeviceFile::construct(QJsonObject());
|
device = LedDeviceFile::construct(dummyDeviceConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "LedDeviceTemplate.h"
|
#include "LedDeviceTemplate.h"
|
||||||
|
|
||||||
LedDeviceTemplate::LedDeviceTemplate(const QJsonObject &deviceConfig)
|
LedDeviceTemplate::LedDeviceTemplate(const QJsonObject & /*deviceConfig*/)
|
||||||
: LedDevice()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ bool LedDeviceTemplate::init(const QJsonObject &deviceConfig)
|
|||||||
{
|
{
|
||||||
// Initialise LedDevice configuration and execution environment
|
// Initialise LedDevice configuration and execution environment
|
||||||
// ...
|
// ...
|
||||||
if ( 0 /*Error during init*/)
|
if ( false /*Error during init*/)
|
||||||
{
|
{
|
||||||
//Build an errortext, illustrative
|
//Build an errortext, illustrative
|
||||||
QString errortext = QString ("Error message: %1").arg("errno/text");
|
QString errortext = QString ("Error message: %1").arg("errno/text");
|
||||||
@ -56,7 +55,7 @@ int LedDeviceTemplate::open()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// On error/exceptions, set LedDevice in error
|
// On error/exceptions, set LedDevice in error
|
||||||
if ( retval < 0 )
|
if ( false /* retval < 0*/ )
|
||||||
{
|
{
|
||||||
this->setInError( errortext );
|
this->setInError( errortext );
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ QString LedDeviceWrapper::getColorOrder() const
|
|||||||
|
|
||||||
unsigned int LedDeviceWrapper::getLedCount() const
|
unsigned int LedDeviceWrapper::getLedCount() const
|
||||||
{
|
{
|
||||||
unsigned int value = 0;
|
int value = 0;
|
||||||
QMetaObject::invokeMethod(_ledDevice, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned int, value));
|
QMetaObject::invokeMethod(_ledDevice, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ void ProviderHID::unblockAfterDelay()
|
|||||||
_blockedForDelay = false;
|
_blockedForDelay = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ProviderHID::discover()
|
QJsonObject ProviderHID::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
@ -31,9 +31,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Discover HIB (USB) devices available (for configuration).
|
/// @brief Discover HIB (USB) devices available (for configuration).
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ bool LedDeviceAtmoOrb::init(const QJsonObject &deviceConfig)
|
|||||||
QStringList orbIds = QStringUtils::split(deviceConfig["orbIds"].toString().simplified().remove(" "),",", QStringUtils::SplitBehavior::SkipEmptyParts);
|
QStringList orbIds = QStringUtils::split(deviceConfig["orbIds"].toString().simplified().remove(" "),",", QStringUtils::SplitBehavior::SkipEmptyParts);
|
||||||
|
|
||||||
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
||||||
Debug(_log, "LedCount : %u", this->getLedCount());
|
Debug(_log, "LedCount : %d", this->getLedCount());
|
||||||
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
||||||
Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms);
|
Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms);
|
||||||
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
||||||
@ -89,8 +89,8 @@ bool LedDeviceAtmoOrb::init(const QJsonObject &deviceConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint numberOrbs = _orbIds.size();
|
int numberOrbs = _orbIds.size();
|
||||||
uint configuredLedCount = this->getLedCount();
|
int configuredLedCount = this->getLedCount();
|
||||||
|
|
||||||
if ( _orbIds.empty() )
|
if ( _orbIds.empty() )
|
||||||
{
|
{
|
||||||
@ -111,7 +111,7 @@ bool LedDeviceAtmoOrb::init(const QJsonObject &deviceConfig)
|
|||||||
{
|
{
|
||||||
if ( numberOrbs > configuredLedCount )
|
if ( numberOrbs > configuredLedCount )
|
||||||
{
|
{
|
||||||
Info(_log, "%s: More Orbs [%u] than configured LEDs [%u].", QSTRING_CSTR(this->getActiveDeviceType()), numberOrbs, configuredLedCount );
|
Info(_log, "%s: More Orbs [%d] than configured LEDs [%d].", QSTRING_CSTR(this->getActiveDeviceType()), numberOrbs, configuredLedCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
isInitOK = true;
|
isInitOK = true;
|
||||||
@ -276,16 +276,21 @@ void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes)
|
|||||||
_udpSocket->writeDatagram(bytes.data(), bytes.size(), _groupAddress, _multiCastGroupPort);
|
_udpSocket->writeDatagram(bytes.data(), bytes.size(), _groupAddress, _multiCastGroupPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceAtmoOrb::discover()
|
QJsonObject LedDeviceAtmoOrb::discover(const QJsonObject& params)
|
||||||
{
|
{
|
||||||
|
//Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
|
||||||
QJsonArray deviceList;
|
QJsonArray deviceList;
|
||||||
|
|
||||||
|
_multicastGroup = params["multiCastGroup"].toString(MULTICAST_GROUP_DEFAULT_ADDRESS);
|
||||||
|
_multiCastGroupPort = static_cast<quint16>(params["multiCastPort"].toInt(MULTICAST_GROUP_DEFAULT_PORT));
|
||||||
|
|
||||||
if ( open() == 0 )
|
if ( open() == 0 )
|
||||||
{
|
{
|
||||||
Debug ( _log, "Send discovery requests to all AtmoOrbs" );
|
Debug ( _log, "Send discovery requests to all AtmoOrbs listening to %s:%d", QSTRING_CSTR(_multicastGroup),_multiCastGroupPort );
|
||||||
setColor(0, ColorRgb::BLACK, 8);
|
setColor(0, ColorRgb::BLACK, 8);
|
||||||
|
|
||||||
if ( _udpSocket->waitForReadyRead(DEFAULT_DISCOVERY_TIMEOUT.count()) )
|
if ( _udpSocket->waitForReadyRead(DEFAULT_DISCOVERY_TIMEOUT.count()) )
|
||||||
|
@ -43,9 +43,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Discover AtmoOrb devices available (for configuration).
|
/// @brief Discover AtmoOrb devices available (for configuration).
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
virtual QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Send an update to the AtmoOrb device to identify it.
|
/// @brief Send an update to the AtmoOrb device to identify it.
|
||||||
|
@ -38,67 +38,6 @@ const char COLOLIGHT_MODEL_IDENTIFIER[] = "OD_WE_QUAN";
|
|||||||
const int COLOLIGHT_BEADS_PER_MODULE = 19;
|
const int COLOLIGHT_BEADS_PER_MODULE = 19;
|
||||||
const int COLOLIGHT_MIN_STRIP_SEGMENT_SIZE = 30;
|
const int COLOLIGHT_MIN_STRIP_SEGMENT_SIZE = 30;
|
||||||
|
|
||||||
enum verbs {
|
|
||||||
GET = 0x03,
|
|
||||||
SET = 0x04,
|
|
||||||
SETEEPROM = 0x07,
|
|
||||||
SETVAR = 0x0b
|
|
||||||
};
|
|
||||||
|
|
||||||
enum commandTypes {
|
|
||||||
STATE_OFF = 0x80,
|
|
||||||
STATE_ON = 0x81,
|
|
||||||
BRIGTHNESS = 0xCF,
|
|
||||||
SETCOLOR = 0xFF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum idxTypes {
|
|
||||||
BRIGTHNESS_CONTROL = 0x01,
|
|
||||||
COLOR_CONTROL = 0x02,
|
|
||||||
COLOR_DIRECT_CONTROL = 0x81,
|
|
||||||
READ_INFO_FROM_STORAGE = 0x86
|
|
||||||
};
|
|
||||||
|
|
||||||
enum bufferMode {
|
|
||||||
MONOCROME = 0x01,
|
|
||||||
LIGHTBEAD = 0x02,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ledLayout {
|
|
||||||
STRIP_LAYOUT,
|
|
||||||
MODLUE_LAYOUT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum modelType {
|
|
||||||
STRIP,
|
|
||||||
PLUS
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t PACKET_HEADER[] =
|
|
||||||
{
|
|
||||||
'S', 'Z', // Tag "SZ"
|
|
||||||
0x30, 0x30, // Version "00"
|
|
||||||
0x00, 0x00, // AppID, 0x0000 = TL1 command mode
|
|
||||||
0x00, 0x00, 0x00, 0x00 // Size
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t PACKET_SECU[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Dict
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Sum
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Salt
|
|
||||||
0x00, 0x00, 0x00, 0x00 // SN
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t TL1_CMD_FIXED_PART[] =
|
|
||||||
{
|
|
||||||
0x00, 0x00, 0x00, 0x00, // DISTID
|
|
||||||
0x00, 0x00, 0x00, 0x00, // SRCID
|
|
||||||
0x00, // SECU
|
|
||||||
0x00, // VERB
|
|
||||||
0x00, // CTAG
|
|
||||||
0x00 // LENGTH
|
|
||||||
};
|
|
||||||
} //End of constants
|
} //End of constants
|
||||||
|
|
||||||
LedDeviceCololight::LedDeviceCololight(const QJsonObject& deviceConfig)
|
LedDeviceCololight::LedDeviceCololight(const QJsonObject& deviceConfig)
|
||||||
@ -174,7 +113,7 @@ bool LedDeviceCololight::initLedsConfiguration()
|
|||||||
|
|
||||||
if (getLedCount() == 0)
|
if (getLedCount() == 0)
|
||||||
{
|
{
|
||||||
setLedCount(static_cast<uint>(_devConfig[CONFIG_HW_LED_COUNT].toInt(0)));
|
setLedCount(_devConfig[CONFIG_HW_LED_COUNT].toInt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_modelType == STRIP && (getLedCount() % COLOLIGHT_MIN_STRIP_SEGMENT_SIZE != 0))
|
if (_modelType == STRIP && (getLedCount() % COLOLIGHT_MIN_STRIP_SEGMENT_SIZE != 0))
|
||||||
@ -187,7 +126,7 @@ bool LedDeviceCololight::initLedsConfiguration()
|
|||||||
{
|
{
|
||||||
Debug(_log, "LedCount : %d", getLedCount());
|
Debug(_log, "LedCount : %d", getLedCount());
|
||||||
|
|
||||||
uint configuredLedCount = static_cast<uint>(_devConfig["currentLedCount"].toInt(1));
|
int configuredLedCount = _devConfig["currentLedCount"].toInt(1);
|
||||||
|
|
||||||
if (getLedCount() < configuredLedCount)
|
if (getLedCount() < configuredLedCount)
|
||||||
{
|
{
|
||||||
@ -200,7 +139,7 @@ bool LedDeviceCololight::initLedsConfiguration()
|
|||||||
{
|
{
|
||||||
if (getLedCount() > configuredLedCount)
|
if (getLedCount() > configuredLedCount)
|
||||||
{
|
{
|
||||||
Info(_log, "%s: More LEDs [%u] than configured LEDs in layout [%u].", QSTRING_CSTR(this->getActiveDeviceType()), getLedCount(), configuredLedCount);
|
Info(_log, "%s: More LEDs [%d] than configured LEDs in layout [%d].", QSTRING_CSTR(this->getActiveDeviceType()), getLedCount(), configuredLedCount);
|
||||||
}
|
}
|
||||||
isInitOK = true;
|
isInitOK = true;
|
||||||
}
|
}
|
||||||
@ -269,7 +208,7 @@ bool LedDeviceCololight::getInfo()
|
|||||||
{
|
{
|
||||||
_modelType = MODLUE_LAYOUT;
|
_modelType = MODLUE_LAYOUT;
|
||||||
_distance = ledNum / COLOLIGHT_BEADS_PER_MODULE;
|
_distance = ledNum / COLOLIGHT_BEADS_PER_MODULE;
|
||||||
setLedCount(static_cast<uint>(_distance));
|
setLedCount(_distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -455,7 +394,7 @@ bool LedDeviceCololight::sendRequest(const appID appID, const QByteArray& comman
|
|||||||
packet.append(static_cast<char>(_sequenceNumber));
|
packet.append(static_cast<char>(_sequenceNumber));
|
||||||
packet.append(command);
|
packet.append(command);
|
||||||
|
|
||||||
quint32 size = sizeof(PACKET_SECU) + 1 + command.size();
|
quint32 size = static_cast<quint32>(static_cast<int>(sizeof(PACKET_SECU)) + 1 + command.size());
|
||||||
|
|
||||||
qToBigEndian<quint16>(appID, packet.data() + 4);
|
qToBigEndian<quint16>(appID, packet.data() + 4);
|
||||||
|
|
||||||
@ -606,7 +545,7 @@ bool LedDeviceCololight::powerOff()
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceCololight::discover()
|
QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType);
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType);
|
||||||
|
@ -29,6 +29,68 @@ enum effect : uint32_t {
|
|||||||
CHRISTMAS = 0x068b0900
|
CHRISTMAS = 0x068b0900
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum verbs {
|
||||||
|
GET = 0x03,
|
||||||
|
SET = 0x04,
|
||||||
|
SETEEPROM = 0x07,
|
||||||
|
SETVAR = 0x0b
|
||||||
|
};
|
||||||
|
|
||||||
|
enum commandTypes {
|
||||||
|
STATE_OFF = 0x80,
|
||||||
|
STATE_ON = 0x81,
|
||||||
|
BRIGTHNESS = 0xCF,
|
||||||
|
SETCOLOR = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum idxTypes {
|
||||||
|
BRIGTHNESS_CONTROL = 0x01,
|
||||||
|
COLOR_CONTROL = 0x02,
|
||||||
|
COLOR_DIRECT_CONTROL = 0x81,
|
||||||
|
READ_INFO_FROM_STORAGE = 0x86
|
||||||
|
};
|
||||||
|
|
||||||
|
enum bufferMode {
|
||||||
|
MONOCROME = 0x01,
|
||||||
|
LIGHTBEAD = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ledLayout {
|
||||||
|
STRIP_LAYOUT,
|
||||||
|
MODLUE_LAYOUT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum modelType {
|
||||||
|
STRIP,
|
||||||
|
PLUS
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PACKET_HEADER[] =
|
||||||
|
{
|
||||||
|
'S', 'Z', // Tag "SZ"
|
||||||
|
0x30, 0x30, // Version "00"
|
||||||
|
0x00, 0x00, // AppID, 0x0000 = TL1 command mode
|
||||||
|
0x00, 0x00, 0x00, 0x00 // Size
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PACKET_SECU[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Dict
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Sum
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Salt
|
||||||
|
0x00, 0x00, 0x00, 0x00 // SN
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t TL1_CMD_FIXED_PART[] =
|
||||||
|
{
|
||||||
|
0x00, 0x00, 0x00, 0x00, // DISTID
|
||||||
|
0x00, 0x00, 0x00, 0x00, // SRCID
|
||||||
|
0x00, // SECU
|
||||||
|
0x00, // VERB
|
||||||
|
0x00, // CTAG
|
||||||
|
0x00 // LENGTH
|
||||||
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Implementation of a Cololight LedDevice
|
/// Implementation of a Cololight LedDevice
|
||||||
///
|
///
|
||||||
@ -54,9 +116,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Discover Cololight devices available (for configuration).
|
/// @brief Discover Cololight devices available (for configuration).
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a Cololight device's resource properties
|
/// @brief Get a Cololight device's resource properties
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include "LedDeviceFadeCandy.h"
|
#include "LedDeviceFadeCandy.h"
|
||||||
|
|
||||||
|
#include <QtEndian>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types#ssize-t
|
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types#ssize-t
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <BaseTsd.h>
|
#include <BaseTsd.h>
|
||||||
@ -8,22 +12,22 @@ typedef SSIZE_T ssize_t;
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr std::chrono::milliseconds CONNECT_TIMEOUT{1000};
|
||||||
|
|
||||||
const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 LEDs - in theory, fadecandy device should handle 10000 LEDs
|
const int MAX_NUM_LEDS = 10000; // OPC can handle 21845 LEDs - in theory, fadecandy device should handle 10000 LEDs
|
||||||
const unsigned OPC_SET_PIXELS = 0; // OPC command codes
|
const int OPC_SET_PIXELS = 0; // OPC command codes
|
||||||
const unsigned OPC_SYS_EX = 255; // OPC command codes
|
const int OPC_SYS_EX = 255; // OPC command codes
|
||||||
const unsigned OPC_HEADER_SIZE = 4; // OPC header size
|
const int OPC_HEADER_SIZE = 4; // OPC header size
|
||||||
|
|
||||||
} //End of constants
|
} //End of constants
|
||||||
|
|
||||||
// TCP elements
|
// TCP elements
|
||||||
const quint16 STREAM_DEFAULT_PORT = 7890;
|
const int STREAM_DEFAULT_PORT = 7890;
|
||||||
|
|
||||||
LedDeviceFadeCandy::LedDeviceFadeCandy(const QJsonObject &deviceConfig)
|
LedDeviceFadeCandy::LedDeviceFadeCandy(const QJsonObject& deviceConfig)
|
||||||
: LedDevice(deviceConfig)
|
: LedDevice(deviceConfig)
|
||||||
, _client(nullptr)
|
, _client(nullptr)
|
||||||
,_host()
|
, _host()
|
||||||
,_port(STREAM_DEFAULT_PORT)
|
, _port(STREAM_DEFAULT_PORT)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,20 +36,20 @@ LedDeviceFadeCandy::~LedDeviceFadeCandy()
|
|||||||
delete _client;
|
delete _client;
|
||||||
}
|
}
|
||||||
|
|
||||||
LedDevice* LedDeviceFadeCandy::construct(const QJsonObject &deviceConfig)
|
LedDevice* LedDeviceFadeCandy::construct(const QJsonObject& deviceConfig)
|
||||||
{
|
{
|
||||||
return new LedDeviceFadeCandy(deviceConfig);
|
return new LedDeviceFadeCandy(deviceConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
|
bool LedDeviceFadeCandy::init(const QJsonObject& deviceConfig)
|
||||||
{
|
{
|
||||||
bool isInitOK = false;
|
bool isInitOK = false;
|
||||||
|
|
||||||
if ( LedDevice::init(deviceConfig) )
|
if (LedDevice::init(deviceConfig))
|
||||||
{
|
{
|
||||||
if (getLedCount() > MAX_NUM_LEDS)
|
if (getLedCount() > MAX_NUM_LEDS)
|
||||||
{
|
{
|
||||||
QString errortext = QString ("More LED configured than allowed (%1)").arg(MAX_NUM_LEDS);
|
QString errortext = QString("More LED configured than allowed (%1)").arg(MAX_NUM_LEDS);
|
||||||
this->setInError(errortext);
|
this->setInError(errortext);
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
@ -55,7 +59,7 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
|
|||||||
_port = deviceConfig["port"].toInt(STREAM_DEFAULT_PORT);
|
_port = deviceConfig["port"].toInt(STREAM_DEFAULT_PORT);
|
||||||
|
|
||||||
//If host not configured the init fails
|
//If host not configured the init fails
|
||||||
if ( _host.isEmpty() )
|
if (_host.isEmpty())
|
||||||
{
|
{
|
||||||
this->setInError("No target hostname nor IP defined");
|
this->setInError("No target hostname nor IP defined");
|
||||||
}
|
}
|
||||||
@ -63,8 +67,8 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
|
|||||||
{
|
{
|
||||||
_channel = deviceConfig["channel"].toInt(0);
|
_channel = deviceConfig["channel"].toInt(0);
|
||||||
_gamma = deviceConfig["gamma"].toDouble(1.0);
|
_gamma = deviceConfig["gamma"].toDouble(1.0);
|
||||||
_noDither = ! deviceConfig["dither"].toBool(false);
|
_noDither = !deviceConfig["dither"].toBool(false);
|
||||||
_noInterp = ! deviceConfig["interpolation"].toBool(false);
|
_noInterp = !deviceConfig["interpolation"].toBool(false);
|
||||||
_manualLED = deviceConfig["manualLed"].toBool(false);
|
_manualLED = deviceConfig["manualLed"].toBool(false);
|
||||||
_ledOnOff = deviceConfig["ledOn"].toBool(false);
|
_ledOnOff = deviceConfig["ledOn"].toBool(false);
|
||||||
_setFcConfig = deviceConfig["setFcConfig"].toBool(false);
|
_setFcConfig = deviceConfig["setFcConfig"].toBool(false);
|
||||||
@ -74,20 +78,19 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
|
|||||||
_whitePoint_b = 1.0;
|
_whitePoint_b = 1.0;
|
||||||
|
|
||||||
const QJsonArray whitePointConfig = deviceConfig["whitePoint"].toArray();
|
const QJsonArray whitePointConfig = deviceConfig["whitePoint"].toArray();
|
||||||
if ( !whitePointConfig.isEmpty() && whitePointConfig.size() == 3 )
|
if (!whitePointConfig.isEmpty() && whitePointConfig.size() == 3)
|
||||||
{
|
{
|
||||||
_whitePoint_r = whitePointConfig[0].toDouble() / 255.0;
|
_whitePoint_r = whitePointConfig[0].toDouble() / 255.0;
|
||||||
_whitePoint_g = whitePointConfig[1].toDouble() / 255.0;
|
_whitePoint_g = whitePointConfig[1].toDouble() / 255.0;
|
||||||
_whitePoint_b = whitePointConfig[2].toDouble() / 255.0;
|
_whitePoint_b = whitePointConfig[2].toDouble() / 255.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_opc_data.resize( _ledRGBCount + OPC_HEADER_SIZE );
|
_opc_data.resize(static_cast<int>(_ledRGBCount) + OPC_HEADER_SIZE);
|
||||||
_opc_data[0] = _channel;
|
_opc_data[0] = static_cast<char>(_channel);
|
||||||
_opc_data[1] = OPC_SET_PIXELS;
|
_opc_data[1] = OPC_SET_PIXELS;
|
||||||
_opc_data[2] = _ledRGBCount >> 8;
|
qToBigEndian<quint16>(static_cast<quint16>(_ledRGBCount), _opc_data.data() + 2);
|
||||||
_opc_data[3] = _ledRGBCount & 0xff;
|
|
||||||
|
|
||||||
if ( initNetwork() )
|
if (initNetwork())
|
||||||
{
|
{
|
||||||
isInitOK = true;
|
isInitOK = true;
|
||||||
}
|
}
|
||||||
@ -101,7 +104,7 @@ bool LedDeviceFadeCandy::initNetwork()
|
|||||||
{
|
{
|
||||||
bool isInitOK = false;
|
bool isInitOK = false;
|
||||||
|
|
||||||
if ( _client == nullptr )
|
if (_client == nullptr)
|
||||||
{
|
{
|
||||||
_client = new QTcpSocket(this);
|
_client = new QTcpSocket(this);
|
||||||
isInitOK = true;
|
isInitOK = true;
|
||||||
@ -116,10 +119,10 @@ int LedDeviceFadeCandy::open()
|
|||||||
_isDeviceReady = false;
|
_isDeviceReady = false;
|
||||||
|
|
||||||
// Try to open the LedDevice
|
// Try to open the LedDevice
|
||||||
if ( !tryConnect() )
|
if (!tryConnect())
|
||||||
{
|
{
|
||||||
errortext = QString ("Failed to open device.");
|
errortext = QString("Failed to open device.");
|
||||||
this->setInError( errortext );
|
this->setInError(errortext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -136,7 +139,7 @@ int LedDeviceFadeCandy::close()
|
|||||||
_isDeviceReady = false;
|
_isDeviceReady = false;
|
||||||
|
|
||||||
// LedDevice specific closing activities
|
// LedDevice specific closing activities
|
||||||
if ( _client != nullptr )
|
if (_client != nullptr)
|
||||||
{
|
{
|
||||||
_client->close();
|
_client->close();
|
||||||
// Everything is OK -> device is closed
|
// Everything is OK -> device is closed
|
||||||
@ -147,7 +150,7 @@ int LedDeviceFadeCandy::close()
|
|||||||
bool LedDeviceFadeCandy::isConnected() const
|
bool LedDeviceFadeCandy::isConnected() const
|
||||||
{
|
{
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
if ( _client != nullptr )
|
if (_client != nullptr)
|
||||||
{
|
{
|
||||||
connected = _client->state() == QAbstractSocket::ConnectedState;
|
connected = _client->state() == QAbstractSocket::ConnectedState;
|
||||||
}
|
}
|
||||||
@ -156,13 +159,13 @@ bool LedDeviceFadeCandy::isConnected() const
|
|||||||
|
|
||||||
bool LedDeviceFadeCandy::tryConnect()
|
bool LedDeviceFadeCandy::tryConnect()
|
||||||
{
|
{
|
||||||
if ( _client != nullptr )
|
if (_client != nullptr)
|
||||||
{
|
{
|
||||||
if ( _client->state() == QAbstractSocket::UnconnectedState ) {
|
if (_client->state() == QAbstractSocket::UnconnectedState) {
|
||||||
_client->connectToHost( _host, _port);
|
_client->connectToHost(_host, static_cast<quint16>(_port));
|
||||||
if ( _client->waitForConnected(1000) )
|
if (_client->waitForConnected(CONNECT_TIMEOUT.count()))
|
||||||
{
|
{
|
||||||
Info(_log,"fadecandy/opc: connected to %s:%i on channel %i", QSTRING_CSTR(_host), _port, _channel);
|
Info(_log, "fadecandy/opc: connected to %s:%d on channel %d", QSTRING_CSTR(_host), _port, _channel);
|
||||||
if (_setFcConfig)
|
if (_setFcConfig)
|
||||||
{
|
{
|
||||||
sendFadeCandyConfiguration();
|
sendFadeCandyConfiguration();
|
||||||
@ -173,50 +176,48 @@ bool LedDeviceFadeCandy::tryConnect()
|
|||||||
return isConnected();
|
return isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
|
int LedDeviceFadeCandy::write(const std::vector<ColorRgb>& ledValues)
|
||||||
{
|
{
|
||||||
uint idx = OPC_HEADER_SIZE;
|
uint idx = OPC_HEADER_SIZE;
|
||||||
for (const ColorRgb& color : ledValues)
|
for (const ColorRgb& color : ledValues)
|
||||||
{
|
{
|
||||||
_opc_data[idx ] = unsigned( color.red );
|
_opc_data[idx] = static_cast<char>(color.red);
|
||||||
_opc_data[idx+1] = unsigned( color.green );
|
_opc_data[idx + 1] = static_cast<char>(color.green);
|
||||||
_opc_data[idx+2] = unsigned( color.blue );
|
_opc_data[idx + 2] = static_cast<char>(color.blue);
|
||||||
idx += 3;
|
idx += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int retval = transferData()<0 ? -1 : 0;
|
int retval = transferData() < 0 ? -1 : 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceFadeCandy::transferData()
|
qint64 LedDeviceFadeCandy::transferData()
|
||||||
{
|
{
|
||||||
if ( isConnected() || tryConnect() )
|
if (isConnected() || tryConnect())
|
||||||
{
|
{
|
||||||
return _client->write( _opc_data, _opc_data.size() );
|
return _client->write(_opc_data);
|
||||||
}
|
}
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, const QByteArray& msg)
|
qint64 LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, const QByteArray& msg)
|
||||||
{
|
{
|
||||||
if ( isConnected() )
|
if (isConnected())
|
||||||
{
|
{
|
||||||
QByteArray sysExData;
|
QByteArray sysExData;
|
||||||
uint data_size = msg.size() + 4;
|
int data_size = msg.size() + 4;
|
||||||
sysExData.resize( 4 + OPC_HEADER_SIZE );
|
sysExData.resize(4 + OPC_HEADER_SIZE);
|
||||||
|
|
||||||
sysExData[0] = 0;
|
sysExData[0] = 0;
|
||||||
sysExData[1] = OPC_SYS_EX;
|
sysExData[1] = static_cast<char>(OPC_SYS_EX);
|
||||||
sysExData[2] = data_size >>8;
|
|
||||||
sysExData[3] = data_size &0xff;
|
qToBigEndian<quint16>(static_cast<quint16>(data_size), sysExData.data() + 2);
|
||||||
sysExData[4] = systemId >>8;
|
qToBigEndian<quint16>(static_cast<quint16>(systemId), sysExData.data() + 4);
|
||||||
sysExData[5] = systemId &0xff;
|
qToBigEndian<quint16>(static_cast<quint16>(commandId), sysExData.data() + 6);
|
||||||
sysExData[6] = commandId >>8;
|
|
||||||
sysExData[7] = commandId &0xff;
|
|
||||||
|
|
||||||
sysExData += msg;
|
sysExData += msg;
|
||||||
|
|
||||||
return _client->write( sysExData, sysExData.size() );
|
return _client->write(sysExData, sysExData.size());
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -224,9 +225,9 @@ int LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, const QBy
|
|||||||
void LedDeviceFadeCandy::sendFadeCandyConfiguration()
|
void LedDeviceFadeCandy::sendFadeCandyConfiguration()
|
||||||
{
|
{
|
||||||
Debug(_log, "send configuration to fadecandy");
|
Debug(_log, "send configuration to fadecandy");
|
||||||
QString data = "{\"gamma\": "+QString::number(_gamma,'g',4)+", \"whitepoint\": ["+QString::number(_whitePoint_r,'g',4)+", "+QString::number(_whitePoint_g,'g',4)+", "+QString::number(_whitePoint_b,'g',4)+"]}";
|
QString data = "{\"gamma\": " + QString::number(_gamma, 'g', 4) + ", \"whitepoint\": [" + QString::number(_whitePoint_r, 'g', 4) + ", " + QString::number(_whitePoint_g, 'g', 4) + ", " + QString::number(_whitePoint_b, 'g', 4) + "]}";
|
||||||
sendSysEx(1, 1, data.toLocal8Bit() );
|
sendSysEx(1, 1, data.toLocal8Bit());
|
||||||
|
|
||||||
char firmware_data = ((uint8_t)_noDither | ((uint8_t)_noInterp << 1) | ((uint8_t)_manualLED << 2) | ((uint8_t)_ledOnOff << 3) );
|
char firmware_data = static_cast<char>(static_cast<uint8_t>(_noDither) | (static_cast<uint8_t>(_noInterp) << 1) | (static_cast<uint8_t>(_manualLED) << 2) | (static_cast<uint8_t>(_ledOnOff) << 3));
|
||||||
sendSysEx(1, 2, QByteArray(1,firmware_data) );
|
sendSysEx(1, 2, QByteArray(1, firmware_data));
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param deviceConfig Device's configuration as JSON-Object
|
/// @param deviceConfig Device's configuration as JSON-Object
|
||||||
///
|
///
|
||||||
explicit LedDeviceFadeCandy(const QJsonObject &deviceConfig);
|
explicit LedDeviceFadeCandy(const QJsonObject& deviceConfig);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Destructor of the LedDevice
|
/// @brief Destructor of the LedDevice
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param[in] deviceConfig Device's configuration as JSON-Object
|
/// @param[in] deviceConfig Device's configuration as JSON-Object
|
||||||
/// @return LedDevice constructed
|
/// @return LedDevice constructed
|
||||||
static LedDevice* construct(const QJsonObject &deviceConfig);
|
static LedDevice* construct(const QJsonObject& deviceConfig);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ protected:
|
|||||||
/// @param[in] deviceConfig the JSON device configuration
|
/// @param[in] deviceConfig the JSON device configuration
|
||||||
/// @return True, if success
|
/// @return True, if success
|
||||||
///
|
///
|
||||||
bool init(const QJsonObject &deviceConfig) override;
|
bool init(const QJsonObject& deviceConfig) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Opens the output device.
|
/// @brief Opens the output device.
|
||||||
@ -84,7 +84,7 @@ protected:
|
|||||||
/// @param[in] ledValues The RGB-color per LED
|
/// @param[in] ledValues The RGB-color per LED
|
||||||
/// @return Zero on success, else negative
|
/// @return Zero on success, else negative
|
||||||
///
|
///
|
||||||
int write(const std::vector<ColorRgb> & ledValues) override;
|
int write(const std::vector<ColorRgb>& ledValues) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ private:
|
|||||||
///
|
///
|
||||||
/// @return amount of transferred bytes. -1 error while transferring, -2 error while connecting
|
/// @return amount of transferred bytes. -1 error while transferring, -2 error while connecting
|
||||||
///
|
///
|
||||||
int transferData();
|
qint64 transferData();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Send system exclusive commands
|
/// @brief Send system exclusive commands
|
||||||
@ -122,7 +122,7 @@ private:
|
|||||||
/// @param[in] commandId id of command
|
/// @param[in] commandId id of command
|
||||||
/// @param[in] msg the sysEx message
|
/// @param[in] msg the sysEx message
|
||||||
/// @return amount bytes written, -1 if failed
|
/// @return amount bytes written, -1 if failed
|
||||||
int sendSysEx(uint8_t systemId, uint8_t commandId, const QByteArray& msg);
|
qint64 sendSysEx(uint8_t systemId, uint8_t commandId, const QByteArray& msg);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Sends the configuration to fadecandy cserver
|
/// @brief Sends the configuration to fadecandy cserver
|
||||||
@ -131,8 +131,8 @@ private:
|
|||||||
|
|
||||||
QTcpSocket* _client;
|
QTcpSocket* _client;
|
||||||
QString _host;
|
QString _host;
|
||||||
uint16_t _port;
|
int _port;
|
||||||
unsigned _channel;
|
int _channel;
|
||||||
QByteArray _opc_data;
|
QByteArray _opc_data;
|
||||||
|
|
||||||
// fadecandy sysEx
|
// fadecandy sysEx
|
||||||
@ -145,7 +145,6 @@ private:
|
|||||||
bool _noInterp;
|
bool _noInterp;
|
||||||
bool _manualLED;
|
bool _manualLED;
|
||||||
bool _ledOnOff;
|
bool _ledOnOff;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LEDEVICEFADECANDY_H
|
#endif // LEDEVICEFADECANDY_H
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QtEndian>
|
||||||
|
|
||||||
//std includes
|
//std includes
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -14,18 +15,17 @@
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const bool verbose = false;
|
const bool verbose = false;
|
||||||
const bool verbose3 = false;
|
const bool verbose3 = false;
|
||||||
|
|
||||||
// Configuration settings
|
// Configuration settings
|
||||||
const char CONFIG_ADDRESS[] = "host";
|
const char CONFIG_ADDRESS[] = "host";
|
||||||
//const char CONFIG_PORT[] = "port";
|
//const char CONFIG_PORT[] = "port";
|
||||||
const char CONFIG_AUTH_TOKEN[] ="token";
|
const char CONFIG_AUTH_TOKEN[] = "token";
|
||||||
|
|
||||||
const char CONFIG_PANEL_ORDER_TOP_DOWN[] ="panelOrderTopDown";
|
const char CONFIG_PANEL_ORDER_TOP_DOWN[] = "panelOrderTopDown";
|
||||||
const char CONFIG_PANEL_ORDER_LEFT_RIGHT[] ="panelOrderLeftRight";
|
const char CONFIG_PANEL_ORDER_LEFT_RIGHT[] = "panelOrderLeftRight";
|
||||||
const char CONFIG_PANEL_START_POS[] ="panelStartPos";
|
const char CONFIG_PANEL_START_POS[] = "panelStartPos";
|
||||||
|
|
||||||
// Panel configuration settings
|
// Panel configuration settings
|
||||||
const char PANEL_LAYOUT[] = "layout";
|
const char PANEL_LAYOUT[] = "layout";
|
||||||
@ -61,16 +61,19 @@ const char API_BASE_PATH[] = "/api/v1/%1/";
|
|||||||
const char API_ROOT[] = "";
|
const char API_ROOT[] = "";
|
||||||
//const char API_EXT_MODE_STRING_V1[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\"}}";
|
//const char API_EXT_MODE_STRING_V1[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\"}}";
|
||||||
const char API_EXT_MODE_STRING_V2[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\", \"extControlVersion\" : \"v2\"}}";
|
const char API_EXT_MODE_STRING_V2[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\", \"extControlVersion\" : \"v2\"}}";
|
||||||
const char API_STATE[] ="state";
|
const char API_STATE[] = "state";
|
||||||
const char API_PANELLAYOUT[] = "panelLayout";
|
const char API_PANELLAYOUT[] = "panelLayout";
|
||||||
const char API_EFFECT[] = "effects";
|
const char API_EFFECT[] = "effects";
|
||||||
|
|
||||||
|
//Nanoleaf Control data stream
|
||||||
|
const int STREAM_FRAME_PANEL_NUM_SIZE = 2;
|
||||||
|
const int STREAM_FRAME_PANEL_INFO_SIZE = 8;
|
||||||
|
|
||||||
// Nanoleaf ssdp services
|
// Nanoleaf ssdp services
|
||||||
const char SSDP_ID[] = "ssdp:all";
|
const char SSDP_ID[] = "ssdp:all";
|
||||||
const char SSDP_FILTER_HEADER[] = "ST";
|
const char SSDP_FILTER_HEADER[] = "ST";
|
||||||
const char SSDP_CANVAS[] = "nanoleaf:nl29";
|
const char SSDP_CANVAS[] = "nanoleaf:nl29";
|
||||||
const char SSDP_LIGHTPANELS[] = "nanoleaf_aurora:light";
|
const char SSDP_LIGHTPANELS[] = "nanoleaf_aurora:light";
|
||||||
|
|
||||||
} //End of constants
|
} //End of constants
|
||||||
|
|
||||||
// Nanoleaf Panel Shapetypes
|
// Nanoleaf Panel Shapetypes
|
||||||
@ -81,7 +84,7 @@ enum SHAPETYPES {
|
|||||||
CONTROL_SQUARE_PRIMARY,
|
CONTROL_SQUARE_PRIMARY,
|
||||||
CONTROL_SQUARE_PASSIVE,
|
CONTROL_SQUARE_PASSIVE,
|
||||||
POWER_SUPPLY,
|
POWER_SUPPLY,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Nanoleaf external control versions
|
// Nanoleaf external control versions
|
||||||
enum EXTCONTROLVERSIONS {
|
enum EXTCONTROLVERSIONS {
|
||||||
@ -89,20 +92,20 @@ enum EXTCONTROLVERSIONS {
|
|||||||
EXTCTRLVER_V2
|
EXTCTRLVER_V2
|
||||||
};
|
};
|
||||||
|
|
||||||
LedDeviceNanoleaf::LedDeviceNanoleaf(const QJsonObject &deviceConfig)
|
LedDeviceNanoleaf::LedDeviceNanoleaf(const QJsonObject& deviceConfig)
|
||||||
: ProviderUdp(deviceConfig)
|
: ProviderUdp(deviceConfig)
|
||||||
,_restApi(nullptr)
|
, _restApi(nullptr)
|
||||||
,_apiPort(API_DEFAULT_PORT)
|
, _apiPort(API_DEFAULT_PORT)
|
||||||
,_topDown(true)
|
, _topDown(true)
|
||||||
,_leftRight(true)
|
, _leftRight(true)
|
||||||
,_startPos(0)
|
, _startPos(0)
|
||||||
,_endPos(0)
|
, _endPos(0)
|
||||||
,_extControlVersion (EXTCTRLVER_V2),
|
, _extControlVersion(EXTCTRLVER_V2),
|
||||||
_panelLedCount(0)
|
_panelLedCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LedDevice* LedDeviceNanoleaf::construct(const QJsonObject &deviceConfig)
|
LedDevice* LedDeviceNanoleaf::construct(const QJsonObject& deviceConfig)
|
||||||
{
|
{
|
||||||
return new LedDeviceNanoleaf(deviceConfig);
|
return new LedDeviceNanoleaf(deviceConfig);
|
||||||
}
|
}
|
||||||
@ -113,7 +116,7 @@ LedDeviceNanoleaf::~LedDeviceNanoleaf()
|
|||||||
_restApi = nullptr;
|
_restApi = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
|
bool LedDeviceNanoleaf::init(const QJsonObject& deviceConfig)
|
||||||
{
|
{
|
||||||
// Overwrite non supported/required features
|
// Overwrite non supported/required features
|
||||||
setLatchTime(0);
|
setLatchTime(0);
|
||||||
@ -121,69 +124,69 @@ bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
|
|||||||
|
|
||||||
if (deviceConfig["rewriteTime"].toInt(0) > 0)
|
if (deviceConfig["rewriteTime"].toInt(0) > 0)
|
||||||
{
|
{
|
||||||
Info (_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored.");
|
Info(_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
bool isInitOK = false;
|
bool isInitOK = false;
|
||||||
|
|
||||||
if ( LedDevice::init(deviceConfig) )
|
if (LedDevice::init(deviceConfig))
|
||||||
{
|
{
|
||||||
uint configuredLedCount = this->getLedCount();
|
int configuredLedCount = this->getLedCount();
|
||||||
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
Debug(_log, "DeviceType : %s", QSTRING_CSTR(this->getActiveDeviceType()));
|
||||||
Debug(_log, "LedCount : %u", configuredLedCount);
|
Debug(_log, "LedCount : %d", configuredLedCount);
|
||||||
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
Debug(_log, "ColorOrder : %s", QSTRING_CSTR(this->getColorOrder()));
|
||||||
Debug(_log, "RewriteTime : %d", this->getRewriteTime());
|
Debug(_log, "RewriteTime : %d", this->getRewriteTime());
|
||||||
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
||||||
|
|
||||||
// Read panel organisation configuration
|
// Read panel organisation configuration
|
||||||
if ( deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].isString() )
|
if (deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].isString())
|
||||||
{
|
{
|
||||||
_topDown = deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].toString().toInt() == 0;
|
_topDown = deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].toString().toInt() == 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_topDown = deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].toInt() == 0;
|
_topDown = deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].toInt() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( deviceConfig[ CONFIG_PANEL_ORDER_LEFT_RIGHT ].isString() )
|
if (deviceConfig[CONFIG_PANEL_ORDER_LEFT_RIGHT].isString())
|
||||||
{
|
{
|
||||||
_leftRight = deviceConfig[ CONFIG_PANEL_ORDER_LEFT_RIGHT ].toString().toInt() == 0;
|
_leftRight = deviceConfig[CONFIG_PANEL_ORDER_LEFT_RIGHT].toString().toInt() == 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_leftRight = deviceConfig[ CONFIG_PANEL_ORDER_LEFT_RIGHT ].toInt() == 0;
|
_leftRight = deviceConfig[CONFIG_PANEL_ORDER_LEFT_RIGHT].toInt() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_startPos = static_cast<uint>( deviceConfig[ CONFIG_PANEL_START_POS ].toInt(0) );
|
_startPos = deviceConfig[CONFIG_PANEL_START_POS].toInt(0);
|
||||||
|
|
||||||
// TODO: Allow to handle port dynamically
|
// TODO: Allow to handle port dynamically
|
||||||
|
|
||||||
//Set hostname as per configuration and_defaultHost default port
|
//Set hostname as per configuration and_defaultHost default port
|
||||||
_hostname = deviceConfig[ CONFIG_ADDRESS ].toString();
|
_hostname = deviceConfig[CONFIG_ADDRESS].toString();
|
||||||
_apiPort = API_DEFAULT_PORT;
|
_apiPort = API_DEFAULT_PORT;
|
||||||
_authToken = deviceConfig[ CONFIG_AUTH_TOKEN ].toString();
|
_authToken = deviceConfig[CONFIG_AUTH_TOKEN].toString();
|
||||||
|
|
||||||
//If host not configured the init failed
|
//If host not configured the init failed
|
||||||
if ( _hostname.isEmpty() )
|
if (_hostname.isEmpty())
|
||||||
{
|
{
|
||||||
this->setInError("No target hostname nor IP defined");
|
this->setInError("No target hostname nor IP defined");
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( initRestAPI( _hostname, _apiPort, _authToken ) )
|
if (initRestAPI(_hostname, _apiPort, _authToken))
|
||||||
{
|
{
|
||||||
// Read LedDevice configuration and validate against device configuration
|
// Read LedDevice configuration and validate against device configuration
|
||||||
if ( initLedsConfiguration() )
|
if (initLedsConfiguration())
|
||||||
{
|
{
|
||||||
// Set UDP streaming host and port
|
// Set UDP streaming host and port
|
||||||
_devConfig["host"] = _hostname;
|
_devConfig["host"] = _hostname;
|
||||||
_devConfig["port"] = STREAM_CONTROL_DEFAULT_PORT;
|
_devConfig["port"] = STREAM_CONTROL_DEFAULT_PORT;
|
||||||
|
|
||||||
isInitOK = ProviderUdp::init(_devConfig);
|
isInitOK = ProviderUdp::init(_devConfig);
|
||||||
Debug(_log, "Hostname/IP : %s", QSTRING_CSTR( _hostname ));
|
Debug(_log, "Hostname/IP : %s", QSTRING_CSTR(_hostname));
|
||||||
Debug(_log, "Port : %d", _port);
|
Debug(_log, "Port : %d", _port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,9 +204,9 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
// Read Panel count and panel Ids
|
// Read Panel count and panel Ids
|
||||||
_restApi->setPath(API_ROOT);
|
_restApi->setPath(API_ROOT);
|
||||||
httpResponse response = _restApi->get();
|
httpResponse response = _restApi->get();
|
||||||
if ( response.error() )
|
if (response.error())
|
||||||
{
|
{
|
||||||
this->setInError ( response.getErrorReason() );
|
this->setInError(response.getErrorReason());
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -215,35 +218,35 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
QString deviceManufacturer = jsonAllPanelInfo[DEV_DATA_MANUFACTURER].toString();
|
QString deviceManufacturer = jsonAllPanelInfo[DEV_DATA_MANUFACTURER].toString();
|
||||||
_deviceFirmwareVersion = jsonAllPanelInfo[DEV_DATA_FIRMWAREVERSION].toString();
|
_deviceFirmwareVersion = jsonAllPanelInfo[DEV_DATA_FIRMWAREVERSION].toString();
|
||||||
|
|
||||||
Debug(_log, "Name : %s", QSTRING_CSTR( deviceName ));
|
Debug(_log, "Name : %s", QSTRING_CSTR(deviceName));
|
||||||
Debug(_log, "Model : %s", QSTRING_CSTR( _deviceModel ));
|
Debug(_log, "Model : %s", QSTRING_CSTR(_deviceModel));
|
||||||
Debug(_log, "Manufacturer : %s", QSTRING_CSTR( deviceManufacturer ));
|
Debug(_log, "Manufacturer : %s", QSTRING_CSTR(deviceManufacturer));
|
||||||
Debug(_log, "FirmwareVersion: %s", QSTRING_CSTR( _deviceFirmwareVersion));
|
Debug(_log, "FirmwareVersion: %s", QSTRING_CSTR(_deviceFirmwareVersion));
|
||||||
|
|
||||||
// Get panel details from /panelLayout/layout
|
// Get panel details from /panelLayout/layout
|
||||||
QJsonObject jsonPanelLayout = jsonAllPanelInfo[API_PANELLAYOUT].toObject();
|
QJsonObject jsonPanelLayout = jsonAllPanelInfo[API_PANELLAYOUT].toObject();
|
||||||
QJsonObject jsonLayout = jsonPanelLayout[PANEL_LAYOUT].toObject();
|
QJsonObject jsonLayout = jsonPanelLayout[PANEL_LAYOUT].toObject();
|
||||||
|
|
||||||
uint panelNum = static_cast<uint>(jsonLayout[PANEL_NUM].toInt());
|
int panelNum = jsonLayout[PANEL_NUM].toInt();
|
||||||
QJsonArray positionData = jsonLayout[PANEL_POSITIONDATA].toArray();
|
QJsonArray positionData = jsonLayout[PANEL_POSITIONDATA].toArray();
|
||||||
|
|
||||||
std::map<uint, std::map<uint, uint>> panelMap;
|
std::map<int, std::map<int, int>> panelMap;
|
||||||
|
|
||||||
// Loop over all children.
|
// Loop over all children.
|
||||||
for (const QJsonValue value : positionData)
|
foreach(const QJsonValue & value, positionData)
|
||||||
{
|
{
|
||||||
QJsonObject panelObj = value.toObject();
|
QJsonObject panelObj = value.toObject();
|
||||||
|
|
||||||
uint panelId = static_cast<uint>(panelObj[PANEL_ID].toInt());
|
int panelId = panelObj[PANEL_ID].toInt();
|
||||||
uint panelX = static_cast<uint>(panelObj[PANEL_POS_X].toInt());
|
int panelX = panelObj[PANEL_POS_X].toInt();
|
||||||
uint panelY = static_cast<uint>(panelObj[PANEL_POS_Y].toInt());
|
int panelY = panelObj[PANEL_POS_Y].toInt();
|
||||||
uint panelshapeType = static_cast<uint>(panelObj[PANEL_SHAPE_TYPE].toInt());
|
int panelshapeType = panelObj[PANEL_SHAPE_TYPE].toInt();
|
||||||
//uint panelOrientation = static_cast<uint>(panelObj[PANEL_ORIENTATION].toInt());
|
//int panelOrientation = panelObj[PANEL_ORIENTATION].toInt();
|
||||||
|
|
||||||
DebugIf(verbose, _log, "Panel [%u] (%u,%u) - Type: [%u]", panelId, panelX, panelY, panelshapeType );
|
DebugIf(verbose, _log, "Panel [%d] (%d,%d) - Type: [%d]", panelId, panelX, panelY, panelshapeType);
|
||||||
|
|
||||||
// Skip Rhythm panels
|
// Skip Rhythm panels
|
||||||
if ( panelshapeType != RHYTM )
|
if (panelshapeType != RHYTM)
|
||||||
{
|
{
|
||||||
panelMap[panelY][panelX] = panelId;
|
panelMap[panelY][panelX] = panelId;
|
||||||
}
|
}
|
||||||
@ -254,16 +257,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Travers panels top down
|
// Travers panels top down
|
||||||
for(auto posY = panelMap.crbegin(); posY != panelMap.crend(); ++posY)
|
for (auto posY = panelMap.crbegin(); posY != panelMap.crend(); ++posY)
|
||||||
{
|
{
|
||||||
// Sort panels left to right
|
// Sort panels left to right
|
||||||
if ( _leftRight )
|
if (_leftRight)
|
||||||
{
|
{
|
||||||
for( auto posX = posY->second.cbegin(); posX != posY->second.cend(); ++posX)
|
for (auto posX = posY->second.cbegin(); posX != posY->second.cend(); ++posX)
|
||||||
{
|
{
|
||||||
DebugIf(verbose3, _log, "panelMap[%u][%u]=%u", posY->first, posX->first, posX->second );
|
DebugIf(verbose3, _log, "panelMap[%d][%d]=%d", posY->first, posX->first, posX->second);
|
||||||
|
|
||||||
if ( _topDown )
|
if (_topDown)
|
||||||
{
|
{
|
||||||
_panelIds.push_back(posX->second);
|
_panelIds.push_back(posX->second);
|
||||||
}
|
}
|
||||||
@ -276,11 +279,11 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Sort panels right to left
|
// Sort panels right to left
|
||||||
for( auto posX = posY->second.crbegin(); posX != posY->second.crend(); ++posX)
|
for (auto posX = posY->second.crbegin(); posX != posY->second.crend(); ++posX)
|
||||||
{
|
{
|
||||||
DebugIf(verbose3, _log, "panelMap[%u][%u]=%u", posY->first, posX->first, posX->second );
|
DebugIf(verbose3, _log, "panelMap[%d][%d]=%d", posY->first, posX->first, posX->second);
|
||||||
|
|
||||||
if ( _topDown )
|
if (_topDown)
|
||||||
{
|
{
|
||||||
_panelIds.push_back(posX->second);
|
_panelIds.push_back(posX->second);
|
||||||
}
|
}
|
||||||
@ -292,22 +295,22 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_panelLedCount = static_cast<uint>(_panelIds.size());
|
this->_panelLedCount = _panelIds.size();
|
||||||
_devConfig["hardwareLedCount"] = static_cast<int>(_panelLedCount);
|
_devConfig["hardwareLedCount"] = _panelLedCount;
|
||||||
|
|
||||||
Debug(_log, "PanelsNum : %u", panelNum);
|
Debug(_log, "PanelsNum : %d", panelNum);
|
||||||
Debug(_log, "PanelLedCount : %u", _panelLedCount);
|
Debug(_log, "PanelLedCount : %d", _panelLedCount);
|
||||||
|
|
||||||
// Check. if enough panels were found.
|
// Check. if enough panels were found.
|
||||||
uint configuredLedCount = this->getLedCount();
|
int configuredLedCount = this->getLedCount();
|
||||||
_endPos = _startPos + configuredLedCount - 1;
|
_endPos = _startPos + configuredLedCount - 1;
|
||||||
|
|
||||||
Debug(_log, "Sort Top>Down : %d", _topDown);
|
Debug(_log, "Sort Top>Down : %d", _topDown);
|
||||||
Debug(_log, "Sort Left>Right: %d", _leftRight);
|
Debug(_log, "Sort Left>Right: %d", _leftRight);
|
||||||
Debug(_log, "Start Panel Pos: %u", _startPos);
|
Debug(_log, "Start Panel Pos: %d", _startPos);
|
||||||
Debug(_log, "End Panel Pos : %u", _endPos);
|
Debug(_log, "End Panel Pos : %d", _endPos);
|
||||||
|
|
||||||
if (_panelLedCount < configuredLedCount )
|
if (_panelLedCount < configuredLedCount)
|
||||||
{
|
{
|
||||||
QString errorReason = QString("Not enough panels [%1] for configured LEDs [%2] found!")
|
QString errorReason = QString("Not enough panels [%1] for configured LEDs [%2] found!")
|
||||||
.arg(_panelLedCount)
|
.arg(_panelLedCount)
|
||||||
@ -317,16 +320,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( _panelLedCount > this->getLedCount() )
|
if (_panelLedCount > this->getLedCount())
|
||||||
{
|
{
|
||||||
Info(_log, "%s: More panels [%u] than configured LEDs [%u].", QSTRING_CSTR(this->getActiveDeviceType()), _panelLedCount, configuredLedCount );
|
Info(_log, "%s: More panels [%d] than configured LEDs [%d].", QSTRING_CSTR(this->getActiveDeviceType()), _panelLedCount, configuredLedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check, if start position + number of configured LEDs is greater than number of panels available
|
// Check, if start position + number of configured LEDs is greater than number of panels available
|
||||||
if ( _endPos >= _panelLedCount )
|
if (_endPos >= _panelLedCount)
|
||||||
{
|
{
|
||||||
QString errorReason = QString("Start panel [%1] out of range. Start panel position can be max [%2] given [%3] panel available!")
|
QString errorReason = QString("Start panel [%1] out of range. Start panel position can be max [%2] given [%3] panel available!")
|
||||||
.arg(_startPos).arg(_panelLedCount-configuredLedCount).arg(_panelLedCount);
|
.arg(_startPos).arg(_panelLedCount - configuredLedCount).arg(_panelLedCount);
|
||||||
|
|
||||||
this->setInError(errorReason);
|
this->setInError(errorReason);
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
@ -336,16 +339,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
|
|||||||
return isInitOK;
|
return isInitOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDeviceNanoleaf::initRestAPI(const QString &hostname, int port, const QString &token )
|
bool LedDeviceNanoleaf::initRestAPI(const QString& hostname, int port, const QString& token)
|
||||||
{
|
{
|
||||||
bool isInitOK = false;
|
bool isInitOK = false;
|
||||||
|
|
||||||
if ( _restApi == nullptr )
|
if (_restApi == nullptr)
|
||||||
{
|
{
|
||||||
_restApi = new ProviderRestApi(hostname, port );
|
_restApi = new ProviderRestApi(hostname, port);
|
||||||
|
|
||||||
//Base-path is api-path + authentication token
|
//Base-path is api-path + authentication token
|
||||||
_restApi->setBasePath( QString(API_BASE_PATH).arg(token) );
|
_restApi->setBasePath(QString(API_BASE_PATH).arg(token));
|
||||||
|
|
||||||
isInitOK = true;
|
isInitOK = true;
|
||||||
}
|
}
|
||||||
@ -360,13 +363,13 @@ int LedDeviceNanoleaf::open()
|
|||||||
QJsonDocument responseDoc = changeToExternalControlMode();
|
QJsonDocument responseDoc = changeToExternalControlMode();
|
||||||
// Resolve port for Light Panels
|
// Resolve port for Light Panels
|
||||||
QJsonObject jsonStreamControllInfo = responseDoc.object();
|
QJsonObject jsonStreamControllInfo = responseDoc.object();
|
||||||
if ( ! jsonStreamControllInfo.isEmpty() )
|
if (!jsonStreamControllInfo.isEmpty())
|
||||||
{
|
{
|
||||||
//Set default streaming port
|
//Set default streaming port
|
||||||
_port = static_cast<uchar>(jsonStreamControllInfo[STREAM_CONTROL_PORT].toInt());
|
_port = static_cast<uchar>(jsonStreamControllInfo[STREAM_CONTROL_PORT].toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ProviderUdp::open() == 0 )
|
if (ProviderUdp::open() == 0)
|
||||||
{
|
{
|
||||||
// Everything is OK, device is ready
|
// Everything is OK, device is ready
|
||||||
_isDeviceReady = true;
|
_isDeviceReady = true;
|
||||||
@ -375,10 +378,10 @@ int LedDeviceNanoleaf::open()
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceNanoleaf::discover()
|
QJsonObject LedDeviceNanoleaf::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType);
|
||||||
|
|
||||||
QJsonArray deviceList;
|
QJsonArray deviceList;
|
||||||
|
|
||||||
@ -391,35 +394,35 @@ QJsonObject LedDeviceNanoleaf::discover()
|
|||||||
discover.setSearchFilter(searchTargetFilter, SSDP_FILTER_HEADER);
|
discover.setSearchFilter(searchTargetFilter, SSDP_FILTER_HEADER);
|
||||||
QString searchTarget = SSDP_ID;
|
QString searchTarget = SSDP_ID;
|
||||||
|
|
||||||
if ( discover.discoverServices(searchTarget) > 0 )
|
if (discover.discoverServices(searchTarget) > 0)
|
||||||
{
|
{
|
||||||
deviceList = discover.getServicesDiscoveredJson();
|
deviceList = discover.getServicesDiscoveredJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
devicesDiscovered.insert("devices", deviceList);
|
devicesDiscovered.insert("devices", deviceList);
|
||||||
Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
return devicesDiscovered;
|
return devicesDiscovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
|
QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
|
||||||
{
|
{
|
||||||
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
QJsonObject properties;
|
QJsonObject properties;
|
||||||
|
|
||||||
// Get Nanoleaf device properties
|
// Get Nanoleaf device properties
|
||||||
QString host = params["host"].toString("");
|
QString host = params["host"].toString("");
|
||||||
if ( !host.isEmpty() )
|
if (!host.isEmpty())
|
||||||
{
|
{
|
||||||
QString authToken = params["token"].toString("");
|
QString authToken = params["token"].toString("");
|
||||||
QString filter = params["filter"].toString("");
|
QString filter = params["filter"].toString("");
|
||||||
|
|
||||||
// Resolve hostname and port (or use default API port)
|
// Resolve hostname and port (or use default API port)
|
||||||
QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts);
|
QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts);
|
||||||
QString apiHost = addressparts[0];
|
QString apiHost = addressparts[0];
|
||||||
int apiPort;
|
int apiPort;
|
||||||
|
|
||||||
if ( addressparts.size() > 1)
|
if (addressparts.size() > 1)
|
||||||
{
|
{
|
||||||
apiPort = addressparts[1].toInt();
|
apiPort = addressparts[1].toInt();
|
||||||
}
|
}
|
||||||
@ -433,34 +436,33 @@ QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
|
|||||||
|
|
||||||
// Perform request
|
// Perform request
|
||||||
httpResponse response = _restApi->get();
|
httpResponse response = _restApi->get();
|
||||||
if ( response.error() )
|
if (response.error())
|
||||||
{
|
{
|
||||||
Warning (_log, "%s get properties failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
|
Warning(_log, "%s get properties failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.insert("properties", response.getBody().object());
|
properties.insert("properties", response.getBody().object());
|
||||||
|
|
||||||
Debug(_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
Debug(_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDeviceNanoleaf::identify(const QJsonObject& params)
|
void LedDeviceNanoleaf::identify(const QJsonObject& params)
|
||||||
{
|
{
|
||||||
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() );
|
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
|
||||||
|
|
||||||
QString host = params["host"].toString("");
|
QString host = params["host"].toString("");
|
||||||
if ( !host.isEmpty() )
|
if (!host.isEmpty())
|
||||||
{
|
{
|
||||||
QString authToken = params["token"].toString("");
|
QString authToken = params["token"].toString("");
|
||||||
|
|
||||||
// Resolve hostname and port (or use default API port)
|
// Resolve hostname and port (or use default API port)
|
||||||
QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts);
|
QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts);
|
||||||
QString apiHost = addressparts[0];
|
QString apiHost = addressparts[0];
|
||||||
int apiPort;
|
int apiPort;
|
||||||
|
|
||||||
if ( addressparts.size() > 1)
|
if (addressparts.size() > 1)
|
||||||
{
|
{
|
||||||
apiPort = addressparts[1].toInt();
|
apiPort = addressparts[1].toInt();
|
||||||
}
|
}
|
||||||
@ -474,33 +476,33 @@ void LedDeviceNanoleaf::identify(const QJsonObject& params)
|
|||||||
|
|
||||||
// Perform request
|
// Perform request
|
||||||
httpResponse response = _restApi->put();
|
httpResponse response = _restApi->put();
|
||||||
if ( response.error() )
|
if (response.error())
|
||||||
{
|
{
|
||||||
Warning (_log, "%s identification failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
|
Warning(_log, "%s identification failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDeviceNanoleaf::powerOn()
|
bool LedDeviceNanoleaf::powerOn()
|
||||||
{
|
{
|
||||||
if ( _isDeviceReady)
|
if (_isDeviceReady)
|
||||||
{
|
{
|
||||||
changeToExternalControlMode();
|
changeToExternalControlMode();
|
||||||
|
|
||||||
//Power-on Nanoleaf device
|
//Power-on Nanoleaf device
|
||||||
_restApi->setPath(API_STATE);
|
_restApi->setPath(API_STATE);
|
||||||
_restApi->put( getOnOffRequest(true) );
|
_restApi->put(getOnOffRequest(true));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedDeviceNanoleaf::powerOff()
|
bool LedDeviceNanoleaf::powerOff()
|
||||||
{
|
{
|
||||||
if ( _isDeviceReady)
|
if (_isDeviceReady)
|
||||||
{
|
{
|
||||||
//Power-off the Nanoleaf device physically
|
//Power-off the Nanoleaf device physically
|
||||||
_restApi->setPath(API_STATE);
|
_restApi->setPath(API_STATE);
|
||||||
_restApi->put( getOnOffRequest(false) );
|
_restApi->put(getOnOffRequest(false));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -508,7 +510,7 @@ bool LedDeviceNanoleaf::powerOff()
|
|||||||
QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const
|
QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const
|
||||||
{
|
{
|
||||||
QString state = isOn ? STATE_VALUE_TRUE : STATE_VALUE_FALSE;
|
QString state = isOn ? STATE_VALUE_TRUE : STATE_VALUE_FALSE;
|
||||||
return QString( "{\"%1\":{\"%2\":%3}}" ).arg(STATE_ON, STATE_ONOFF_VALUE, state);
|
return QString("{\"%1\":{\"%2\":%3}}").arg(STATE_ON, STATE_ONOFF_VALUE, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
|
QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
|
||||||
@ -518,15 +520,14 @@ QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
|
|||||||
//Enable UDP Mode v2
|
//Enable UDP Mode v2
|
||||||
|
|
||||||
_restApi->setPath(API_EFFECT);
|
_restApi->setPath(API_EFFECT);
|
||||||
httpResponse response =_restApi->put(API_EXT_MODE_STRING_V2);
|
httpResponse response = _restApi->put(API_EXT_MODE_STRING_V2);
|
||||||
|
|
||||||
return response.getBody();
|
return response.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
|
int LedDeviceNanoleaf::write(const std::vector<ColorRgb>& ledValues)
|
||||||
{
|
{
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
uint udpBufferSize;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// nPanels 2B
|
// nPanels 2B
|
||||||
@ -537,35 +538,27 @@ int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
|
|||||||
//
|
//
|
||||||
// Note: Nanoleaf Light Panels (Aurora) now support External Control V2 (tested with FW 3.2.0)
|
// Note: Nanoleaf Light Panels (Aurora) now support External Control V2 (tested with FW 3.2.0)
|
||||||
|
|
||||||
udpBufferSize = _panelLedCount * 8 + 2;
|
int udpBufferSize = STREAM_FRAME_PANEL_NUM_SIZE + _panelLedCount * STREAM_FRAME_PANEL_INFO_SIZE;
|
||||||
std::vector<uint8_t> udpbuffer;
|
|
||||||
|
QByteArray udpbuffer;
|
||||||
udpbuffer.resize(udpBufferSize);
|
udpbuffer.resize(udpBufferSize);
|
||||||
|
|
||||||
uchar lowByte; // lower byte
|
int i = 0;
|
||||||
uchar highByte; // upper byte
|
|
||||||
|
|
||||||
uint i=0;
|
|
||||||
|
|
||||||
// Set number of panels
|
// Set number of panels
|
||||||
highByte = static_cast<uchar>(_panelLedCount >>8 );
|
qToBigEndian<quint16>(static_cast<quint16>(_panelLedCount), udpbuffer.data() + i);
|
||||||
lowByte = static_cast<uchar>(_panelLedCount & 0xFF);
|
i += 2;
|
||||||
|
|
||||||
udpbuffer[i++] = highByte;
|
|
||||||
udpbuffer[i++] = lowByte;
|
|
||||||
|
|
||||||
ColorRgb color;
|
ColorRgb color;
|
||||||
|
|
||||||
//Maintain LED counter independent from PanelCounter
|
//Maintain LED counter independent from PanelCounter
|
||||||
uint ledCounter = 0;
|
int ledCounter = 0;
|
||||||
for ( uint panelCounter=0; panelCounter < _panelLedCount; panelCounter++ )
|
for (int panelCounter = 0; panelCounter < _panelLedCount; panelCounter++)
|
||||||
{
|
{
|
||||||
uint panelID = _panelIds[panelCounter];
|
int panelID = _panelIds[panelCounter];
|
||||||
|
|
||||||
highByte = static_cast<uchar>(panelID >>8 );
|
|
||||||
lowByte = static_cast<uchar>(panelID & 0xFF);
|
|
||||||
|
|
||||||
// Set panels configured
|
// Set panels configured
|
||||||
if( panelCounter >= _startPos && panelCounter <= _endPos ) {
|
if (panelCounter >= _startPos && panelCounter <= _endPos) {
|
||||||
color = static_cast<ColorRgb>(ledValues.at(ledCounter));
|
color = static_cast<ColorRgb>(ledValues.at(ledCounter));
|
||||||
++ledCounter;
|
++ledCounter;
|
||||||
}
|
}
|
||||||
@ -573,49 +566,35 @@ int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
|
|||||||
{
|
{
|
||||||
// Set panels not configured to black;
|
// Set panels not configured to black;
|
||||||
color = ColorRgb::BLACK;
|
color = ColorRgb::BLACK;
|
||||||
DebugIf(verbose3, _log, "[%u] >= panelLedCount [%u] => Set to BLACK", panelCounter, _panelLedCount );
|
DebugIf(verbose3, _log, "[%d] >= panelLedCount [%d] => Set to BLACK", panelCounter, _panelLedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set panelID
|
// Set panelID
|
||||||
udpbuffer[i++] = highByte;
|
qToBigEndian<quint16>(static_cast<quint16>(panelID), udpbuffer.data() + i);
|
||||||
udpbuffer[i++] = lowByte;
|
i += 2;
|
||||||
|
|
||||||
// Set panel's color LEDs
|
// Set panel's color LEDs
|
||||||
udpbuffer[i++] = color.red;
|
udpbuffer[i++] = static_cast<char>(color.red);
|
||||||
udpbuffer[i++] = color.green;
|
udpbuffer[i++] = static_cast<char>(color.green);
|
||||||
udpbuffer[i++] = color.blue;
|
udpbuffer[i++] = static_cast<char>(color.blue);
|
||||||
|
|
||||||
// Set white LED
|
// Set white LED
|
||||||
udpbuffer[i++] = 0; // W not set manually
|
udpbuffer[i++] = 0; // W not set manually
|
||||||
|
|
||||||
// Set transition time
|
// Set transition time
|
||||||
unsigned char tranitionTime = 1; // currently fixed at value 1 which corresponds to 100ms
|
unsigned char tranitionTime = 1; // currently fixed at value 1 which corresponds to 100ms
|
||||||
|
qToBigEndian<quint16>(static_cast<quint16>(tranitionTime), udpbuffer.data() + i);
|
||||||
|
i += 2;
|
||||||
|
|
||||||
highByte = static_cast<uchar>(tranitionTime >>8 );
|
DebugIf(verbose3, _log, "[%u] Color: {%u,%u,%u}", panelCounter, color.red, color.green, color.blue);
|
||||||
lowByte = static_cast<uchar>(tranitionTime & 0xFF);
|
|
||||||
|
|
||||||
udpbuffer[i++] = highByte;
|
|
||||||
udpbuffer[i++] = lowByte;
|
|
||||||
DebugIf(verbose3, _log, "[%u] Color: {%u,%u,%u}", panelCounter, color.red, color.green, color.blue );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
DebugIf(verbose3, _log, "UDP-Address [%s], UDP-Port [%u], udpBufferSize[%u], Bytes to send [%u]", QSTRING_CSTR(_address.toString()), _port, udpBufferSize, i);
|
|
||||||
DebugIf(verbose3, _log, "[%s]", uint8_vector_to_hex_string(udpbuffer).c_str() );
|
|
||||||
|
|
||||||
retVal &= writeBytes( i , udpbuffer.data());
|
if (verbose3)
|
||||||
DebugIf(verbose3, _log, "writeBytes(): [%d]",retVal);
|
{
|
||||||
|
Debug(_log, "UDP-Address [%s], UDP-Port [%u], udpBufferSize[%d], Bytes to send [%d]", QSTRING_CSTR(_address.toString()), _port, udpBufferSize, i);
|
||||||
|
Debug( _log, "packet: [%s]", QSTRING_CSTR(toHex(udpbuffer, 64)));
|
||||||
|
}
|
||||||
|
|
||||||
|
retVal = writeBytes(udpbuffer);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LedDeviceNanoleaf::uint8_vector_to_hex_string(const std::vector<uint8_t>& buffer) const
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::hex << std::setfill('0');
|
|
||||||
std::vector<uint8_t>::const_iterator it;
|
|
||||||
|
|
||||||
for (it = buffer.begin(); it != buffer.end(); ++it)
|
|
||||||
{
|
|
||||||
ss << " " << std::setw(2) << static_cast<unsigned>(*it);
|
|
||||||
}
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param deviceConfig Device's configuration as JSON-Object
|
/// @param deviceConfig Device's configuration as JSON-Object
|
||||||
///
|
///
|
||||||
explicit LedDeviceNanoleaf(const QJsonObject &deviceConfig);
|
explicit LedDeviceNanoleaf(const QJsonObject& deviceConfig);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Destructor of the LED-device
|
/// @brief Destructor of the LED-device
|
||||||
@ -44,14 +44,16 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param[in] deviceConfig Device's configuration as JSON-Object
|
/// @param[in] deviceConfig Device's configuration as JSON-Object
|
||||||
/// @return LedDevice constructed
|
/// @return LedDevice constructed
|
||||||
static LedDevice* construct(const QJsonObject &deviceConfig);
|
static LedDevice* construct(const QJsonObject& deviceConfig);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Discover Nanoleaf devices available (for configuration).
|
/// @brief Discover Nanoleaf devices available (for configuration).
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get the Nanoleaf device's resource properties
|
/// @brief Get the Nanoleaf device's resource properties
|
||||||
@ -93,7 +95,7 @@ protected:
|
|||||||
/// @param[in] deviceConfig the JSON device configuration
|
/// @param[in] deviceConfig the JSON device configuration
|
||||||
/// @return True, if success
|
/// @return True, if success
|
||||||
///
|
///
|
||||||
bool init(const QJsonObject &deviceConfig) override;
|
bool init(const QJsonObject& deviceConfig) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Opens the output device.
|
/// @brief Opens the output device.
|
||||||
@ -108,7 +110,7 @@ protected:
|
|||||||
/// @param[in] ledValues The RGB-color per LED
|
/// @param[in] ledValues The RGB-color per LED
|
||||||
/// @return Zero on success, else negative
|
/// @return Zero on success, else negative
|
||||||
//////
|
//////
|
||||||
int write(const std::vector<ColorRgb> & ledValues) override;
|
int write(const std::vector<ColorRgb>& ledValues) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Power-/turn on the Nanoleaf device.
|
/// @brief Power-/turn on the Nanoleaf device.
|
||||||
@ -135,7 +137,7 @@ private:
|
|||||||
///
|
///
|
||||||
/// @return True, if success
|
/// @return True, if success
|
||||||
///
|
///
|
||||||
bool initRestAPI(const QString &hostname, int port, const QString &token );
|
bool initRestAPI(const QString& hostname, int port, const QString& token);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get Nanoleaf device details and configuration
|
/// @brief Get Nanoleaf device details and configuration
|
||||||
@ -157,14 +159,7 @@ private:
|
|||||||
/// @param isOn True, if to switch on device
|
/// @param isOn True, if to switch on device
|
||||||
/// @return Command to switch device on/off
|
/// @return Command to switch device on/off
|
||||||
///
|
///
|
||||||
QString getOnOffRequest (bool isOn ) const;
|
QString getOnOffRequest(bool isOn) const;
|
||||||
|
|
||||||
///
|
|
||||||
/// @brief Convert vector to hex string
|
|
||||||
///
|
|
||||||
/// @param uint8_t vector
|
|
||||||
/// @return vector as string of hex values
|
|
||||||
std::string uint8_vector_to_hex_string( const std::vector<uint8_t>& buffer ) const;
|
|
||||||
|
|
||||||
///REST-API wrapper
|
///REST-API wrapper
|
||||||
ProviderRestApi* _restApi;
|
ProviderRestApi* _restApi;
|
||||||
@ -175,8 +170,8 @@ private:
|
|||||||
|
|
||||||
bool _topDown;
|
bool _topDown;
|
||||||
bool _leftRight;
|
bool _leftRight;
|
||||||
uint _startPos;
|
int _startPos;
|
||||||
uint _endPos;
|
int _endPos;
|
||||||
|
|
||||||
//Nanoleaf device details
|
//Nanoleaf device details
|
||||||
QString _deviceModel;
|
QString _deviceModel;
|
||||||
@ -184,11 +179,10 @@ private:
|
|||||||
ushort _extControlVersion;
|
ushort _extControlVersion;
|
||||||
|
|
||||||
/// The number of panels with LEDs
|
/// The number of panels with LEDs
|
||||||
uint _panelLedCount;
|
int _panelLedCount;
|
||||||
|
|
||||||
/// Array of the panel ids.
|
/// Array of the panel ids.
|
||||||
QVector<uint> _panelIds;
|
QVector<int> _panelIds;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LEDEVICENANOLEAF_H
|
#endif // LEDEVICENANOLEAF_H
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
bool verbose = false;
|
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
// Configuration settings
|
// Configuration settings
|
||||||
const char CONFIG_ADDRESS[] = "output";
|
const char CONFIG_ADDRESS[] = "output";
|
||||||
//const char CONFIG_PORT[] = "port";
|
//const char CONFIG_PORT[] = "port";
|
||||||
@ -97,31 +97,6 @@ const int STREAM_SSL_HANDSHAKE_ATTEMPTS = 5;
|
|||||||
constexpr std::chrono::milliseconds STREAM_REWRITE_TIME{20};
|
constexpr std::chrono::milliseconds STREAM_REWRITE_TIME{20};
|
||||||
const int SSL_CIPHERSUITES[2] = { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, 0 };
|
const int SSL_CIPHERSUITES[2] = { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, 0 };
|
||||||
|
|
||||||
//Streaming message header and payload definition
|
|
||||||
const uint8_t HEADER[] =
|
|
||||||
{
|
|
||||||
'H', 'u', 'e', 'S', 't', 'r', 'e', 'a', 'm', //protocol
|
|
||||||
0x01, 0x00, //version 1.0
|
|
||||||
0x01, //sequence number 1
|
|
||||||
0x00, 0x00, //Reserved write 0’s
|
|
||||||
0x01, //xy Brightness
|
|
||||||
0x00, // Reserved, write 0’s
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t PAYLOAD_PER_LIGHT[] =
|
|
||||||
{
|
|
||||||
0x01, 0x00, 0x06, //light ID
|
|
||||||
//color: 16 bpc
|
|
||||||
0xff, 0xff,
|
|
||||||
0xff, 0xff,
|
|
||||||
0xff, 0xff,
|
|
||||||
/*
|
|
||||||
(message.R >> 8) & 0xff, message.R & 0xff,
|
|
||||||
(message.G >> 8) & 0xff, message.G & 0xff,
|
|
||||||
(message.B >> 8) & 0xff, message.B & 0xff
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
} //End of constants
|
} //End of constants
|
||||||
|
|
||||||
bool operator ==(const CiColor& p1, const CiColor& p2)
|
bool operator ==(const CiColor& p1, const CiColor& p2)
|
||||||
@ -301,7 +276,7 @@ bool LedDevicePhilipsHueBridge::init(const QJsonObject &deviceConfig)
|
|||||||
{
|
{
|
||||||
|
|
||||||
log( "DeviceType", "%s", QSTRING_CSTR( this->getActiveDeviceType() ) );
|
log( "DeviceType", "%s", QSTRING_CSTR( this->getActiveDeviceType() ) );
|
||||||
log( "LedCount", "%u", this->getLedCount() );
|
log( "LedCount", "%d", this->getLedCount() );
|
||||||
log( "ColorOrder", "%s", QSTRING_CSTR( this->getColorOrder() ) );
|
log( "ColorOrder", "%s", QSTRING_CSTR( this->getColorOrder() ) );
|
||||||
log( "RefreshTime", "%d", _refreshTimerInterval_ms );
|
log( "RefreshTime", "%d", _refreshTimerInterval_ms );
|
||||||
log( "LatchTime", "%d", this->getLatchTime() );
|
log( "LatchTime", "%d", this->getLatchTime() );
|
||||||
@ -313,7 +288,7 @@ bool LedDevicePhilipsHueBridge::init(const QJsonObject &deviceConfig)
|
|||||||
if ( address.isEmpty() )
|
if ( address.isEmpty() )
|
||||||
{
|
{
|
||||||
this->setInError("No target hostname nor IP defined");
|
this->setInError("No target hostname nor IP defined");
|
||||||
return false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -485,7 +460,7 @@ void LedDevicePhilipsHueBridge::setBridgeConfig(const QJsonDocument &doc)
|
|||||||
log( "Bridge-ID", "%s", QSTRING_CSTR( deviceBridgeID ));
|
log( "Bridge-ID", "%s", QSTRING_CSTR( deviceBridgeID ));
|
||||||
log( "SoftwareVersion", "%s", QSTRING_CSTR( _deviceFirmwareVersion ));
|
log( "SoftwareVersion", "%s", QSTRING_CSTR( _deviceFirmwareVersion ));
|
||||||
log( "API-Version", "%u.%u.%u", _api_major, _api_minor, _api_patch );
|
log( "API-Version", "%u.%u.%u", _api_major, _api_minor, _api_patch );
|
||||||
log( "EntertainmentReady", "%d", _isHueEntertainmentReady );
|
log( "EntertainmentReady", "%d", static_cast<int>(_isHueEntertainmentReady) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedDevicePhilipsHueBridge::setLightsMap(const QJsonDocument &doc)
|
void LedDevicePhilipsHueBridge::setLightsMap(const QJsonDocument &doc)
|
||||||
@ -511,7 +486,7 @@ void LedDevicePhilipsHueBridge::setLightsMap(const QJsonDocument &doc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log( "Lights in Bridge found", "%u", getLedCount() );
|
log( "Lights in Bridge found", "%d", getLedCount() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,7 +897,7 @@ bool LedDevicePhilipsHue::setLights()
|
|||||||
|
|
||||||
if( !lArray.empty() )
|
if( !lArray.empty() )
|
||||||
{
|
{
|
||||||
for (const auto id : lArray)
|
for (const QJsonValueRef id : lArray)
|
||||||
{
|
{
|
||||||
unsigned int lightId = id.toString().toUInt();
|
unsigned int lightId = id.toString().toUInt();
|
||||||
if( lightId > 0 )
|
if( lightId > 0 )
|
||||||
@ -1253,7 +1228,7 @@ QByteArray LedDevicePhilipsHue::prepareStreamData() const
|
|||||||
{
|
{
|
||||||
QByteArray msg;
|
QByteArray msg;
|
||||||
msg.reserve(static_cast<int>(sizeof(HEADER) + sizeof(PAYLOAD_PER_LIGHT) * _lights.size()));
|
msg.reserve(static_cast<int>(sizeof(HEADER) + sizeof(PAYLOAD_PER_LIGHT) * _lights.size()));
|
||||||
msg.append((const char*)HEADER, sizeof(HEADER));
|
msg.append(reinterpret_cast<const char*>(HEADER), sizeof(HEADER));
|
||||||
|
|
||||||
for (const PhilipsHueLight& light : _lights)
|
for (const PhilipsHueLight& light : _lights)
|
||||||
{
|
{
|
||||||
@ -1268,7 +1243,7 @@ QByteArray LedDevicePhilipsHue::prepareStreamData() const
|
|||||||
static_cast<uint8_t>((G >> 8) & 0xff), static_cast<uint8_t>(G & 0xff),
|
static_cast<uint8_t>((G >> 8) & 0xff), static_cast<uint8_t>(G & 0xff),
|
||||||
static_cast<uint8_t>((B >> 8) & 0xff), static_cast<uint8_t>(B & 0xff)
|
static_cast<uint8_t>((B >> 8) & 0xff), static_cast<uint8_t>(B & 0xff)
|
||||||
};
|
};
|
||||||
msg.append((char*)payload, sizeof(payload));
|
msg.append(reinterpret_cast<const char *>(payload), sizeof(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
@ -1298,7 +1273,7 @@ int LedDevicePhilipsHue::close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LedDevicePhilipsHue::switchOn()
|
bool LedDevicePhilipsHue::switchOn()
|
||||||
{
|
{
|
||||||
Debug(_log, "");
|
Debug(_log, "");
|
||||||
|
|
||||||
bool rc = false;
|
bool rc = false;
|
||||||
@ -1327,7 +1302,7 @@ bool LedDevicePhilipsHue::switchOn()
|
|||||||
rc = true;
|
rc = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1388,7 +1363,7 @@ void LedDevicePhilipsHue::stopBlackTimeoutTimer()
|
|||||||
|
|
||||||
bool LedDevicePhilipsHue::noSignalDetection()
|
bool LedDevicePhilipsHue::noSignalDetection()
|
||||||
{
|
{
|
||||||
if( _allLightsBlack )
|
if( _allLightsBlack && _switchOffOnBlack)
|
||||||
{
|
{
|
||||||
if( !_stopConnection && _isInitLeds )
|
if( !_stopConnection && _isInitLeds )
|
||||||
{
|
{
|
||||||
@ -1614,7 +1589,7 @@ bool LedDevicePhilipsHue::restoreState()
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDevicePhilipsHue::discover()
|
QJsonObject LedDevicePhilipsHue::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
@ -17,6 +17,31 @@
|
|||||||
#include "ProviderRestApi.h"
|
#include "ProviderRestApi.h"
|
||||||
#include "ProviderUdpSSL.h"
|
#include "ProviderUdpSSL.h"
|
||||||
|
|
||||||
|
//Streaming message header and payload definition
|
||||||
|
const uint8_t HEADER[] =
|
||||||
|
{
|
||||||
|
'H', 'u', 'e', 'S', 't', 'r', 'e', 'a', 'm', //protocol
|
||||||
|
0x01, 0x00, //version 1.0
|
||||||
|
0x01, //sequence number 1
|
||||||
|
0x00, 0x00, //Reserved write 0’s
|
||||||
|
0x01, //xy Brightness
|
||||||
|
0x00, // Reserved, write 0’s
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t PAYLOAD_PER_LIGHT[] =
|
||||||
|
{
|
||||||
|
0x01, 0x00, 0x06, //light ID
|
||||||
|
//color: 16 bpc
|
||||||
|
0xff, 0xff,
|
||||||
|
0xff, 0xff,
|
||||||
|
0xff, 0xff,
|
||||||
|
/*
|
||||||
|
(message.R >> 8) & 0xff, message.R & 0xff,
|
||||||
|
(message.G >> 8) & 0xff, message.G & 0xff,
|
||||||
|
(message.B >> 8) & 0xff, message.B & 0xff
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A XY color point in the color space of the hue system without brightness.
|
* A XY color point in the color space of the hue system without brightness.
|
||||||
*/
|
*/
|
||||||
@ -326,7 +351,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Destructor of the LED-device
|
/// @brief Destructor of the LED-device
|
||||||
///
|
///
|
||||||
~LedDevicePhilipsHue();
|
~LedDevicePhilipsHue() override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Constructs the LED-device
|
/// @brief Constructs the LED-device
|
||||||
@ -339,9 +364,11 @@ public:
|
|||||||
/// @brief Discover devices of this type available (for configuration).
|
/// @brief Discover devices of this type available (for configuration).
|
||||||
/// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways.
|
/// @note Mainly used for network devices. Allows to find devices, e.g. via ssdp, mDNS or cloud ways.
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get the Hue Bridge device's resource properties
|
/// @brief Get the Hue Bridge device's resource properties
|
||||||
|
@ -17,7 +17,7 @@ const quint16 STREAM_DEFAULT_PORT = 19446;
|
|||||||
const int API_DEFAULT_PORT = -1; //Use default port per communication scheme
|
const int API_DEFAULT_PORT = -1; //Use default port per communication scheme
|
||||||
|
|
||||||
const char API_BASE_PATH[] = "/json/";
|
const char API_BASE_PATH[] = "/json/";
|
||||||
const char API_PATH_INFO[] = "info";
|
//const char API_PATH_INFO[] = "info";
|
||||||
const char API_PATH_STATE[] = "state";
|
const char API_PATH_STATE[] = "state";
|
||||||
|
|
||||||
// List of State Information
|
// List of State Information
|
||||||
@ -60,9 +60,9 @@ bool LedDeviceWled::init(const QJsonObject &deviceConfig)
|
|||||||
if ( LedDevice::init(deviceConfig) )
|
if ( LedDevice::init(deviceConfig) )
|
||||||
{
|
{
|
||||||
// Initialise LedDevice configuration and execution environment
|
// Initialise LedDevice configuration and execution environment
|
||||||
uint configuredLedCount = this->getLedCount();
|
int configuredLedCount = this->getLedCount();
|
||||||
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
||||||
Debug(_log, "LedCount : %u", configuredLedCount);
|
Debug(_log, "LedCount : %d", configuredLedCount);
|
||||||
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
||||||
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ bool LedDeviceWled::powerOff()
|
|||||||
return off;
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceWled::discover()
|
QJsonObject LedDeviceWled::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
@ -37,9 +37,11 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Discover WLED devices available (for configuration).
|
/// @brief Discover WLED devices available (for configuration).
|
||||||
///
|
///
|
||||||
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get the WLED device's resource properties
|
/// @brief Get the WLED device's resource properties
|
||||||
|
@ -247,7 +247,7 @@ int YeelightLight::writeCommand( const QJsonDocument &command, QJsonArray &resul
|
|||||||
if ( elapsedTime < _waitTimeQuota )
|
if ( elapsedTime < _waitTimeQuota )
|
||||||
{
|
{
|
||||||
int waitTime = _waitTimeQuota;
|
int waitTime = _waitTimeQuota;
|
||||||
log ( 1, "writeCommand():", "Wait %dms, elapsedTime: %dms < quotaTime: %dms", waitTime, elapsedTime, _waitTimeQuota);
|
log ( 1, "writeCommand():", "Wait %dms, elapsedTime: %dms < quotaTime: %dms", waitTime, static_cast<int>(elapsedTime), _waitTimeQuota);
|
||||||
|
|
||||||
// Wait time (in ms) before doing next write to not overrun Yeelight command quota
|
// Wait time (in ms) before doing next write to not overrun Yeelight command quota
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(_waitTimeQuota));
|
std::this_thread::sleep_for(std::chrono::milliseconds(_waitTimeQuota));
|
||||||
@ -452,7 +452,7 @@ YeelightResponse YeelightLight::handleResponse(int correlationID, QByteArray con
|
|||||||
// Debug output
|
// Debug output
|
||||||
if(!yeeResponse.getResult().empty())
|
if(!yeeResponse.getResult().empty())
|
||||||
{
|
{
|
||||||
for(const auto item : yeeResponse.getResult())
|
for(const QJsonValueRef item : yeeResponse.getResult())
|
||||||
{
|
{
|
||||||
log ( 3, "Result:", "%s", QSTRING_CSTR( item.toString() ));
|
log ( 3, "Result:", "%s", QSTRING_CSTR( item.toString() ));
|
||||||
}
|
}
|
||||||
@ -524,7 +524,7 @@ QJsonObject YeelightLight::getProperties()
|
|||||||
if( !result.empty())
|
if( !result.empty())
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(const auto item : result)
|
for(const QJsonValueRef item : result)
|
||||||
{
|
{
|
||||||
log (1,"Property:", "%s = %s", QSTRING_CSTR( propertyList.at(i).toString() ), QSTRING_CSTR( item.toString() ));
|
log (1,"Property:", "%s = %s", QSTRING_CSTR( propertyList.at(i).toString() ), QSTRING_CSTR( item.toString() ));
|
||||||
properties.insert( propertyList.at(i).toString(), item );
|
properties.insert( propertyList.at(i).toString(), item );
|
||||||
@ -1008,7 +1008,7 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
|
|||||||
if ( LedDevice::init(deviceConfig) )
|
if ( LedDevice::init(deviceConfig) )
|
||||||
{
|
{
|
||||||
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
||||||
Debug(_log, "LedCount : %u", this->getLedCount());
|
Debug(_log, "LedCount : %d", this->getLedCount());
|
||||||
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
||||||
Debug(_log, "RewriteTime : %d", this->getRewriteTime());
|
Debug(_log, "RewriteTime : %d", this->getRewriteTime());
|
||||||
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
||||||
@ -1073,8 +1073,8 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
|
|||||||
Debug(_log, "Debuglevel : %d", _debuglevel);
|
Debug(_log, "Debuglevel : %d", _debuglevel);
|
||||||
|
|
||||||
QJsonArray configuredYeelightLights = _devConfig[CONFIG_LIGHTS].toArray();
|
QJsonArray configuredYeelightLights = _devConfig[CONFIG_LIGHTS].toArray();
|
||||||
uint configuredYeelightsCount = 0;
|
int configuredYeelightsCount = 0;
|
||||||
for (const QJsonValue light : configuredYeelightLights)
|
for (const QJsonValueRef light : configuredYeelightLights)
|
||||||
{
|
{
|
||||||
QString host = light.toObject().value("host").toString();
|
QString host = light.toObject().value("host").toString();
|
||||||
int port = light.toObject().value("port").toInt(API_DEFAULT_PORT);
|
int port = light.toObject().value("port").toInt(API_DEFAULT_PORT);
|
||||||
@ -1085,9 +1085,9 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
|
|||||||
++configuredYeelightsCount;
|
++configuredYeelightsCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug(_log, "Light configured : %u", configuredYeelightsCount );
|
Debug(_log, "Light configured : %d", configuredYeelightsCount );
|
||||||
|
|
||||||
uint configuredLedCount = this->getLedCount();
|
int configuredLedCount = this->getLedCount();
|
||||||
if (configuredYeelightsCount < configuredLedCount )
|
if (configuredYeelightsCount < configuredLedCount )
|
||||||
{
|
{
|
||||||
QString errorReason = QString("Not enough Yeelights [%1] for configured LEDs [%2] found!")
|
QString errorReason = QString("Not enough Yeelights [%1] for configured LEDs [%2] found!")
|
||||||
@ -1101,7 +1101,7 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
|
|||||||
|
|
||||||
if ( configuredYeelightsCount > configuredLedCount )
|
if ( configuredYeelightsCount > configuredLedCount )
|
||||||
{
|
{
|
||||||
Warning(_log, "More Yeelights defined [%u] than configured LEDs [%u].", configuredYeelightsCount, configuredLedCount );
|
Warning(_log, "More Yeelights defined [%d] than configured LEDs [%d].", configuredYeelightsCount, configuredLedCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
_lightsAddressList.clear();
|
_lightsAddressList.clear();
|
||||||
@ -1347,7 +1347,7 @@ bool LedDeviceYeelight::restoreState()
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject LedDeviceYeelight::discover()
|
QJsonObject LedDeviceYeelight::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
@ -435,12 +435,11 @@ public:
|
|||||||
///
|
///
|
||||||
static LedDevice* construct(const QJsonObject &deviceConfig);
|
static LedDevice* construct(const QJsonObject &deviceConfig);
|
||||||
|
|
||||||
///
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
/// @brief Discover Yeelight devices available (for configuration).
|
|
||||||
///
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a Yeelight device's resource properties
|
/// @brief Get a Yeelight device's resource properties
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// STL includes
|
// STL includes
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -16,9 +15,9 @@
|
|||||||
|
|
||||||
const ushort MAX_PORT = 65535;
|
const ushort MAX_PORT = 65535;
|
||||||
|
|
||||||
ProviderUdp::ProviderUdp(const QJsonObject &deviceConfig)
|
ProviderUdp::ProviderUdp(const QJsonObject& deviceConfig)
|
||||||
: LedDevice(deviceConfig)
|
: LedDevice(deviceConfig)
|
||||||
, _udpSocket (nullptr)
|
, _udpSocket(nullptr)
|
||||||
, _port(1)
|
, _port(1)
|
||||||
, _defaultHost("127.0.0.1")
|
, _defaultHost("127.0.0.1")
|
||||||
{
|
{
|
||||||
@ -30,48 +29,48 @@ ProviderUdp::~ProviderUdp()
|
|||||||
delete _udpSocket;
|
delete _udpSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProviderUdp::init(const QJsonObject &deviceConfig)
|
bool ProviderUdp::init(const QJsonObject& deviceConfig)
|
||||||
{
|
{
|
||||||
bool isInitOK = false;
|
bool isInitOK = false;
|
||||||
|
|
||||||
// Initialise sub-class
|
// Initialise sub-class
|
||||||
if ( LedDevice::init(deviceConfig) )
|
if (LedDevice::init(deviceConfig))
|
||||||
{
|
{
|
||||||
QString host = deviceConfig["host"].toString(_defaultHost);
|
QString host = deviceConfig["host"].toString(_defaultHost);
|
||||||
|
|
||||||
if (_address.setAddress(host) )
|
if (_address.setAddress(host))
|
||||||
{
|
{
|
||||||
Debug( _log, "Successfully parsed %s as an IP-address.", QSTRING_CSTR(_address.toString()));
|
Debug(_log, "Successfully parsed %s as an IP-address.", QSTRING_CSTR(_address.toString()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QHostInfo hostInfo = QHostInfo::fromName(host);
|
QHostInfo hostInfo = QHostInfo::fromName(host);
|
||||||
if ( hostInfo.error() == QHostInfo::NoError )
|
if (hostInfo.error() == QHostInfo::NoError)
|
||||||
{
|
{
|
||||||
_address = hostInfo.addresses().first();
|
_address = hostInfo.addresses().first();
|
||||||
Debug( _log, "Successfully resolved IP-address (%s) for hostname (%s).", QSTRING_CSTR(_address.toString()), QSTRING_CSTR(host));
|
Debug(_log, "Successfully resolved IP-address (%s) for hostname (%s).", QSTRING_CSTR(_address.toString()), QSTRING_CSTR(host));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString errortext = QString ("Failed resolving IP-address for [%1], (%2) %3").arg(host).arg(hostInfo.error()).arg(hostInfo.errorString());
|
QString errortext = QString("Failed resolving IP-address for [%1], (%2) %3").arg(host).arg(hostInfo.error()).arg(hostInfo.errorString());
|
||||||
this->setInError ( errortext );
|
this->setInError(errortext);
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !_isDeviceInError )
|
if (!_isDeviceInError)
|
||||||
{
|
{
|
||||||
int config_port = deviceConfig["port"].toInt(_port);
|
int config_port = deviceConfig["port"].toInt(_port);
|
||||||
if ( config_port <= 0 || config_port > MAX_PORT )
|
if (config_port <= 0 || config_port > MAX_PORT)
|
||||||
{
|
{
|
||||||
QString errortext = QString ("Invalid target port [%1]!").arg(config_port);
|
QString errortext = QString("Invalid target port [%1]!").arg(config_port);
|
||||||
this->setInError ( errortext );
|
this->setInError(errortext);
|
||||||
isInitOK = false;
|
isInitOK = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_port = static_cast<int>(config_port);
|
_port = static_cast<quint16>(config_port);
|
||||||
Debug( _log, "UDP socket will write to %s:%u", QSTRING_CSTR(_address.toString()) , _port );
|
Debug(_log, "UDP socket will write to %s:%u", QSTRING_CSTR(_address.toString()), _port);
|
||||||
|
|
||||||
_udpSocket = new QUdpSocket(this);
|
_udpSocket = new QUdpSocket(this);
|
||||||
|
|
||||||
@ -88,16 +87,16 @@ int ProviderUdp::open()
|
|||||||
_isDeviceReady = false;
|
_isDeviceReady = false;
|
||||||
|
|
||||||
// Try to bind the UDP-Socket
|
// Try to bind the UDP-Socket
|
||||||
if ( _udpSocket != nullptr )
|
if (_udpSocket != nullptr)
|
||||||
{
|
{
|
||||||
if ( _udpSocket->state() != QAbstractSocket::BoundState )
|
if (_udpSocket->state() != QAbstractSocket::BoundState)
|
||||||
{
|
{
|
||||||
QHostAddress localAddress = QHostAddress::Any;
|
QHostAddress localAddress = QHostAddress::Any;
|
||||||
quint16 localPort = 0;
|
quint16 localPort = 0;
|
||||||
if ( !_udpSocket->bind(localAddress, localPort) )
|
if (!_udpSocket->bind(localAddress, localPort))
|
||||||
{
|
{
|
||||||
QString warntext = QString ("Could not bind local address: %1, (%2) %3").arg(localAddress.toString()).arg(_udpSocket->error()).arg(_udpSocket->errorString());
|
QString warntext = QString("Could not bind local address: %1, (%2) %3").arg(localAddress.toString()).arg(_udpSocket->error()).arg(_udpSocket->errorString());
|
||||||
Warning ( _log, "%s", QSTRING_CSTR(warntext));
|
Warning(_log, "%s", QSTRING_CSTR(warntext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Everything is OK, device is ready
|
// Everything is OK, device is ready
|
||||||
@ -106,7 +105,7 @@ int ProviderUdp::open()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->setInError( " Open error. UDP Socket not initialised!" );
|
this->setInError(" Open error. UDP Socket not initialised!");
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -116,12 +115,12 @@ int ProviderUdp::close()
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
_isDeviceReady = false;
|
_isDeviceReady = false;
|
||||||
|
|
||||||
if ( _udpSocket != nullptr )
|
if (_udpSocket != nullptr)
|
||||||
{
|
{
|
||||||
// Test, if device requires closing
|
// Test, if device requires closing
|
||||||
if ( _udpSocket->isOpen() )
|
if (_udpSocket->isOpen())
|
||||||
{
|
{
|
||||||
Debug(_log,"Close UDP-device: %s", QSTRING_CSTR( this->getActiveDeviceType() ) );
|
Debug(_log, "Close UDP-device: %s", QSTRING_CSTR(this->getActiveDeviceType()));
|
||||||
_udpSocket->close();
|
_udpSocket->close();
|
||||||
// Everything is OK -> device is closed
|
// Everything is OK -> device is closed
|
||||||
}
|
}
|
||||||
@ -129,22 +128,28 @@ int ProviderUdp::close()
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProviderUdp::writeBytes(const unsigned size, const uint8_t * data)
|
int ProviderUdp::writeBytes(const unsigned size, const uint8_t* data)
|
||||||
{
|
{
|
||||||
qint64 retVal = _udpSocket->writeDatagram((const char *)data,size,_address,_port);
|
int rc = 0;
|
||||||
|
qint64 bytesWritten = _udpSocket->writeDatagram(reinterpret_cast<const char*>(data), size, _address, _port);
|
||||||
|
|
||||||
WarningIf((retVal<0), _log, "&s", QSTRING_CSTR(QString
|
if (bytesWritten == -1 || bytesWritten != size)
|
||||||
("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
|
{
|
||||||
|
Warning(_log, "%s", QSTRING_CSTR(QString("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
|
||||||
return retVal;
|
rc = -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProviderUdp::writeBytes(const QByteArray &bytes)
|
int ProviderUdp::writeBytes(const QByteArray& bytes)
|
||||||
{
|
{
|
||||||
qint64 retVal = _udpSocket->writeDatagram(bytes,_address,_port);
|
int rc = 0;
|
||||||
|
qint64 bytesWritten = _udpSocket->writeDatagram(bytes, _address, _port);
|
||||||
|
|
||||||
WarningIf((retVal<0), _log, "&s", QSTRING_CSTR(QString
|
if (bytesWritten == -1 || bytesWritten != bytes.size())
|
||||||
("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
|
{
|
||||||
|
Warning(_log, "%s", QSTRING_CSTR(QString("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
|
||||||
return retVal;
|
rc = -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @brief Constructs an UDP LED-device
|
/// @brief Constructs an UDP LED-device
|
||||||
///
|
///
|
||||||
ProviderUdp(const QJsonObject &deviceConfig);
|
ProviderUdp(const QJsonObject& deviceConfig);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Destructor of the UDP LED-device
|
/// @brief Destructor of the UDP LED-device
|
||||||
@ -38,7 +38,7 @@ protected:
|
|||||||
/// @param[in] deviceConfig the JSON device configuration
|
/// @param[in] deviceConfig the JSON device configuration
|
||||||
/// @return True, if success
|
/// @return True, if success
|
||||||
///
|
///
|
||||||
bool init(const QJsonObject &deviceConfig) override;
|
bool init(const QJsonObject& deviceConfig) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Opens the output device.
|
/// @brief Opens the output device.
|
||||||
@ -62,7 +62,7 @@ protected:
|
|||||||
///
|
///
|
||||||
/// @return Zero on success, else negative
|
/// @return Zero on success, else negative
|
||||||
///
|
///
|
||||||
int writeBytes(const unsigned size, const uint8_t *data);
|
int writeBytes(const unsigned size, const uint8_t* data);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Writes the given bytes to the UDP-device
|
/// @brief Writes the given bytes to the UDP-device
|
||||||
@ -71,10 +71,10 @@ protected:
|
|||||||
///
|
///
|
||||||
/// @return Zero on success, else negative
|
/// @return Zero on success, else negative
|
||||||
///
|
///
|
||||||
int writeBytes(const QByteArray &bytes);
|
int writeBytes(const QByteArray& bytes);
|
||||||
|
|
||||||
///
|
///
|
||||||
QUdpSocket * _udpSocket;
|
QUdpSocket* _udpSocket;
|
||||||
QHostAddress _address;
|
QHostAddress _address;
|
||||||
quint16 _port;
|
quint16 _port;
|
||||||
QString _defaultHost;
|
QString _defaultHost;
|
||||||
|
@ -26,6 +26,14 @@ bool LedDeviceFile::init(const QJsonObject &deviceConfig)
|
|||||||
bool initOK = LedDevice::init(deviceConfig);
|
bool initOK = LedDevice::init(deviceConfig);
|
||||||
|
|
||||||
_fileName = deviceConfig["output"].toString("/dev/null");
|
_fileName = deviceConfig["output"].toString("/dev/null");
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
if (_fileName == "/dev/null" )
|
||||||
|
{
|
||||||
|
_fileName = "NULL";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_printTimeStamp = deviceConfig["printTimeStamp"].toBool(false);
|
_printTimeStamp = deviceConfig["printTimeStamp"].toBool(false);
|
||||||
|
|
||||||
initFile(_fileName);
|
initFile(_fileName);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "LedDeviceAdalight.h"
|
#include "LedDeviceAdalight.h"
|
||||||
|
|
||||||
|
#include <QtEndian>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig)
|
LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig)
|
||||||
@ -50,8 +52,7 @@ bool LedDeviceAdalight::init(const QJsonObject &deviceConfig)
|
|||||||
_ledBuffer[0] = 'A';
|
_ledBuffer[0] = 'A';
|
||||||
_ledBuffer[1] = 'd';
|
_ledBuffer[1] = 'd';
|
||||||
_ledBuffer[2] = 'a';
|
_ledBuffer[2] = 'a';
|
||||||
_ledBuffer[3] = (totalLedCount >> 8) & 0xFF; // LED count high byte
|
qToBigEndian<quint16>(static_cast<quint16>(totalLedCount), &_ledBuffer[3]);
|
||||||
_ledBuffer[4] = totalLedCount & 0xFF; // LED count low byte
|
|
||||||
_ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum
|
_ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum
|
||||||
|
|
||||||
Debug( _log, "Adalight header for %d leds: %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount,
|
Debug( _log, "Adalight header for %d leds: %c%c%c 0x%02x 0x%02x 0x%02x", _ledCount,
|
||||||
|
@ -34,7 +34,7 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig)
|
|||||||
{
|
{
|
||||||
|
|
||||||
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
|
||||||
Debug(_log, "LedCount : %u", this->getLedCount());
|
Debug(_log, "LedCount : %d", this->getLedCount());
|
||||||
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
|
||||||
Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms);
|
Debug(_log, "RefreshTime : %d", _refreshTimerInterval_ms);
|
||||||
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
Debug(_log, "LatchTime : %d", this->getLatchTime());
|
||||||
@ -256,7 +256,7 @@ QString ProviderRs232::discoverFirst()
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ProviderRs232::discover()
|
QJsonObject ProviderRs232::discover(const QJsonObject& /*params*/)
|
||||||
{
|
{
|
||||||
QJsonObject devicesDiscovered;
|
QJsonObject devicesDiscovered;
|
||||||
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
|
||||||
|
@ -66,12 +66,11 @@ protected:
|
|||||||
///
|
///
|
||||||
QString discoverFirst() override;
|
QString discoverFirst() override;
|
||||||
|
|
||||||
///
|
/// @param[in] params Parameters used to overwrite discovery default behaviour
|
||||||
/// @brief Discover RS232 serial devices available (for configuration).
|
|
||||||
///
|
///
|
||||||
/// @return A JSON structure holding a list of devices found
|
/// @return A JSON structure holding a list of devices found
|
||||||
///
|
///
|
||||||
QJsonObject discover() override;
|
QJsonObject discover(const QJsonObject& params) override;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Write the given bytes to the RS232-device
|
/// @brief Write the given bytes to the RS232-device
|
||||||
|
@ -214,7 +214,7 @@ void ProtoClientConnection::handleNotImplemented()
|
|||||||
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
|
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
|
||||||
{
|
{
|
||||||
std::string serializedReply = message.SerializeAsString();
|
std::string serializedReply = message.SerializeAsString();
|
||||||
uint32_t size = serializedReply.size();
|
uint32_t size = static_cast<uint32_t>(serializedReply.size());
|
||||||
uint8_t sizeData[] = {uint8_t(size >> 24), uint8_t(size >> 16), uint8_t(size >> 8), uint8_t(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((const char *) sizeData, sizeof(sizeData));
|
||||||
_socket->write(serializedReply.data(), serializedReply.length());
|
_socket->write(serializedReply.data(), serializedReply.length());
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
#undef slots
|
|
||||||
#include <Python.h>
|
|
||||||
#define slots
|
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
@ -48,7 +44,11 @@ PythonInit::PythonInit()
|
|||||||
throw std::runtime_error("Initializing Python failed!");
|
throw std::runtime_error("Initializing Python failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (PY_VERSION_HEX < 0x03090000)
|
||||||
|
// PyEval_InitThreads became deprecated in Python 3.9 and will be removed in Python 3.11
|
||||||
PyEval_InitThreads(); // Create the GIL
|
PyEval_InitThreads(); // Create the GIL
|
||||||
|
#endif
|
||||||
|
|
||||||
mainThreadState = PyEval_SaveThread();
|
mainThreadState = PyEval_SaveThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,12 @@ PythonProgram::PythonProgram(const QString & name, Logger * log) :
|
|||||||
_tstate = Py_NewInterpreter();
|
_tstate = Py_NewInterpreter();
|
||||||
if(_tstate == nullptr)
|
if(_tstate == nullptr)
|
||||||
{
|
{
|
||||||
|
#if (PY_VERSION_HEX >= 0x03020000)
|
||||||
PyThreadState_Swap(mainThreadState);
|
PyThreadState_Swap(mainThreadState);
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
|
#else
|
||||||
|
PyEval_ReleaseLock();
|
||||||
|
#endif
|
||||||
Error(_log, "Failed to get thread state for %s",QSTRING_CSTR(_name));
|
Error(_log, "Failed to get thread state for %s",QSTRING_CSTR(_name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -55,8 +59,12 @@ PythonProgram::~PythonProgram()
|
|||||||
|
|
||||||
// Clean up the thread state
|
// Clean up the thread state
|
||||||
Py_EndInterpreter(_tstate);
|
Py_EndInterpreter(_tstate);
|
||||||
|
#if (PY_VERSION_HEX >= 0x03020000)
|
||||||
PyThreadState_Swap(mainThreadState);
|
PyThreadState_Swap(mainThreadState);
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
|
#else
|
||||||
|
PyEval_ReleaseLock();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonProgram::execute(const QByteArray & python_code)
|
void PythonProgram::execute(const QByteArray & python_code)
|
||||||
|
@ -15,10 +15,6 @@ RgbChannelAdjustment::RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uin
|
|||||||
setAdjustment(adjustR, adjustG, adjustB);
|
setAdjustment(adjustR, adjustG, adjustB);
|
||||||
}
|
}
|
||||||
|
|
||||||
RgbChannelAdjustment::~RgbChannelAdjustment()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void RgbChannelAdjustment::resetInitialized()
|
void RgbChannelAdjustment::resetInitialized()
|
||||||
{
|
{
|
||||||
//Debug(_log, "initialize mapping with %d,%d,%d", _adjust[RED], _adjust[GREEN], _adjust[BLUE]);
|
//Debug(_log, "initialize mapping with %d,%d,%d", _adjust[RED], _adjust[GREEN], _adjust[BLUE]);
|
||||||
|
@ -7,10 +7,22 @@ namespace RGBW {
|
|||||||
|
|
||||||
WhiteAlgorithm stringToWhiteAlgorithm(const QString& str)
|
WhiteAlgorithm stringToWhiteAlgorithm(const QString& str)
|
||||||
{
|
{
|
||||||
if (str == "subtract_minimum") return WhiteAlgorithm::SUBTRACT_MINIMUM;
|
if (str == "subtract_minimum")
|
||||||
if (str == "sub_min_warm_adjust") return WhiteAlgorithm::SUB_MIN_WARM_ADJUST;
|
{
|
||||||
if (str == "sub_min_cool_adjust") return WhiteAlgorithm::SUB_MIN_COOL_ADJUST;
|
return WhiteAlgorithm::SUBTRACT_MINIMUM;
|
||||||
if (str.isEmpty() || str == "white_off") return WhiteAlgorithm::WHITE_OFF;
|
}
|
||||||
|
if (str == "sub_min_warm_adjust")
|
||||||
|
{
|
||||||
|
return WhiteAlgorithm::SUB_MIN_WARM_ADJUST;
|
||||||
|
}
|
||||||
|
if (str == "sub_min_cool_adjust")
|
||||||
|
{
|
||||||
|
return WhiteAlgorithm::SUB_MIN_COOL_ADJUST;
|
||||||
|
}
|
||||||
|
if (str.isEmpty() || str == "white_off")
|
||||||
|
{
|
||||||
|
return WhiteAlgorithm::WHITE_OFF;
|
||||||
|
}
|
||||||
return WhiteAlgorithm::INVALID;
|
return WhiteAlgorithm::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +32,7 @@ void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, WhiteAlgorithm algorithm)
|
|||||||
{
|
{
|
||||||
case WhiteAlgorithm::SUBTRACT_MINIMUM:
|
case WhiteAlgorithm::SUBTRACT_MINIMUM:
|
||||||
{
|
{
|
||||||
output->white = qMin(qMin(input.red, input.green), input.blue);
|
output->white = static_cast<uint8_t>(qMin(qMin(input.red, input.green), input.blue));
|
||||||
output->red = input.red - output->white;
|
output->red = input.red - output->white;
|
||||||
output->green = input.green - output->white;
|
output->green = input.green - output->white;
|
||||||
output->blue = input.blue - output->white;
|
output->blue = input.blue - output->white;
|
||||||
@ -31,14 +43,14 @@ void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, WhiteAlgorithm algorithm)
|
|||||||
{
|
{
|
||||||
// http://forum.garagecube.com/viewtopic.php?t=10178
|
// http://forum.garagecube.com/viewtopic.php?t=10178
|
||||||
// warm white
|
// warm white
|
||||||
const float F1(0.274);
|
const double F1(0.274);
|
||||||
const float F2(0.454);
|
const double F2(0.454);
|
||||||
const float F3(2.333);
|
const double F3(2.333);
|
||||||
|
|
||||||
output->white = qMin(input.red*F1,qMin(input.green*F2,input.blue*F3));
|
output->white = static_cast<uint8_t>(qMin(input.red*F1,qMin(input.green*F2,input.blue*F3)));
|
||||||
output->red = input.red - output->white/F1;
|
output->red = input.red - static_cast<uint8_t>(output->white/F1);
|
||||||
output->green = input.green - output->white/F2;
|
output->green = input.green - static_cast<uint8_t>(output->white/F2);
|
||||||
output->blue = input.blue - output->white/F3;
|
output->blue = input.blue - static_cast<uint8_t>(output->white/F3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,14 +58,14 @@ void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, WhiteAlgorithm algorithm)
|
|||||||
{
|
{
|
||||||
// http://forum.garagecube.com/viewtopic.php?t=10178
|
// http://forum.garagecube.com/viewtopic.php?t=10178
|
||||||
// cold white
|
// cold white
|
||||||
const float F1(0.299);
|
const double F1(0.299);
|
||||||
const float F2(0.587);
|
const double F2(0.587);
|
||||||
const float F3(0.114);
|
const double F3(0.114);
|
||||||
|
|
||||||
output->white = qMin(input.red*F1,qMin(input.green*F2,input.blue*F3));
|
output->white = static_cast<uint8_t>(qMin(input.red*F1,qMin(input.green*F2,input.blue*F3)));
|
||||||
output->red = input.red - output->white/F1;
|
output->red = input.red - static_cast<uint8_t>(output->white/F1);
|
||||||
output->green = input.green - output->white/F2;
|
output->green = input.green - static_cast<uint8_t>(output->white/F2);
|
||||||
output->blue = input.blue - output->white/F3;
|
output->blue = input.blue - static_cast<uint8_t>(output->white/F3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ void QtHttpClientWrapper::onReplySendHeadersRequested (void)
|
|||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
// HTTP Version + Status Code + Status Msg
|
// HTTP Version + Status Code + Status Msg
|
||||||
data.append (QtHttpServer::HTTP_VERSION);
|
data.append (QtHttpServer::HTTP_VERSION.toUtf8());
|
||||||
data.append (SPACE);
|
data.append (SPACE);
|
||||||
data.append (QByteArray::number (reply->getStatusCode ()));
|
data.append (QByteArray::number (reply->getStatusCode ()));
|
||||||
data.append (SPACE);
|
data.append (SPACE);
|
||||||
|
@ -223,7 +223,7 @@ void WebSocketClient::sendClose(int status, QString reason)
|
|||||||
sendBuffer.append(quint8(length));
|
sendBuffer.append(quint8(length));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendBuffer.append(reason);
|
sendBuffer.append(reason.toUtf8());
|
||||||
|
|
||||||
_socket->write(sendBuffer);
|
_socket->write(sendBuffer);
|
||||||
_socket->flush();
|
_socket->flush();
|
||||||
|
@ -27,8 +27,10 @@ int count(std::initializer_list<bool> values)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
for (bool value : values) {
|
for (bool value : values) {
|
||||||
if (value)
|
if (value)
|
||||||
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,16 +45,18 @@ void showHelp(Option & option){
|
|||||||
qWarning() << qPrintable(QString("\t%1\t%2\t%3").arg(shortOption, longOption, option.description()));
|
qWarning() << qPrintable(QString("\t%1\t%2\t%3").arg(shortOption, longOption, option.description()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int getInstaneIdbyName(const QJsonObject & reply, const QString name){
|
int getInstaneIdbyName(const QJsonObject & reply, const QString & name){
|
||||||
if(reply.contains("instance")){
|
if(reply.contains("instance")){
|
||||||
QJsonArray list = reply.value("instance").toArray();
|
QJsonArray list = reply.value("instance").toArray();
|
||||||
|
|
||||||
for (const auto & entry : list) {
|
for (const QJsonValueRef entry : list) {
|
||||||
const QJsonObject obj = entry.toObject();
|
const QJsonObject obj = entry.toObject();
|
||||||
if(obj["friendly_name"] == name && obj["running"].toBool())
|
if(obj["friendly_name"] == name && obj["running"].toBool())
|
||||||
|
{
|
||||||
return obj["instance"].toInt();
|
return obj["instance"].toInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::cout << "Can't find a running instance with name '" << name.toStdString()<< "' at this Hyperion server, will use first instance" << std::endl;
|
std::cout << "Can't find a running instance with name '" << name.toStdString()<< "' at this Hyperion server, will use first instance" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -78,23 +82,23 @@ int main(int argc, char * argv[])
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// create the option parser and initialize all parameters
|
// create the option parser and initialize all parameters
|
||||||
Parser parser("Application to send a command to hyperion using the Json interface");
|
Parser parser("Application to send a command to hyperion using the JSON interface");
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// art variable definition append art to Parser short-, long option description, optional default value //
|
// art variable definition append art to Parser short-, long option description, optional default value //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
Option & argAddress = parser.add<Option> ('a', "address" , "Set the address of the hyperion server [default: %1]", "127.0.0.1:19444");
|
Option & argAddress = parser.add<Option> ('a', "address" , "Set the address of the hyperion server [default: %1]", "127.0.0.1:19444");
|
||||||
Option & argToken = parser.add<Option> ('t', "token " , "If authorization tokens are required, this token is used");
|
Option & argToken = parser.add<Option> ('t', "token " , "If authorization tokens are required, this token is used");
|
||||||
Option & argInstance = parser.add<Option> ('I', "instance" , "Select a specific target instance by name for your command. By befault it uses always the first instance");
|
Option & argInstance = parser.add<Option> ('I', "instance" , "Select a specific target instance by name for your command. By default it uses always the first instance");
|
||||||
IntOption & argPriority = parser.add<IntOption> ('p', "priority" , "Used to the provided priority channel (suggested 2-99) [default: %1]", "50");
|
IntOption & argPriority = parser.add<IntOption> ('p', "priority" , "Used to the provided priority channel (suggested 2-99) [default: %1]", "50");
|
||||||
IntOption & argDuration = parser.add<IntOption> ('d', "duration" , "Specify how long the leds should be switched on in milliseconds [default: infinity]");
|
IntOption & argDuration = parser.add<IntOption> ('d', "duration" , "Specify how long the LEDs should be switched on in milliseconds [default: infinity]");
|
||||||
ColorsOption & argColor = parser.add<ColorsOption> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex getColors or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
|
ColorsOption & argColor = parser.add<ColorsOption> ('c', "color" , "Set all LEDs to a constant color (either RRGGBB hex getColors or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
|
||||||
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the leds to the colors according to the given image file");
|
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the LEDs to the colors according to the given image file");
|
||||||
Option & argEffect = parser.add<Option> ('e', "effect" , "Enable the effect with the given name");
|
Option & argEffect = parser.add<Option> ('e', "effect" , "Enable the effect with the given name");
|
||||||
Option & argEffectFile = parser.add<Option> (0x0, "effectFile" , "Arguments to use in combination with --createEffect");
|
Option & argEffectFile = parser.add<Option> (0x0, "effectFile" , "Arguments to use in combination with --createEffect");
|
||||||
Option & argEffectArgs = parser.add<Option> (0x0, "effectArgs" , "Arguments to use in combination with the specified effect. Should be a Json object string.", "");
|
Option & argEffectArgs = parser.add<Option> (0x0, "effectArgs" , "Arguments to use in combination with the specified effect. Should be a JSON object string.", "");
|
||||||
Option & argCreateEffect = parser.add<Option> (0x0, "createEffect" , "Write a new Json Effect configuration file.\nFirst parameter = Effect name.\nSecond parameter = Effect file (--effectFile).\nLast parameter = Effect arguments (--effectArgs.)", "");
|
Option & argCreateEffect = parser.add<Option> (0x0, "createEffect" , "Write a new JSON Effect configuration file.\nFirst parameter = Effect name.\nSecond parameter = Effect file (--effectFile).\nLast parameter = Effect arguments (--effectArgs.)", "");
|
||||||
Option & argDeleteEffect = parser.add<Option> (0x0, "deleteEffect" , "Delete a custom created Json Effect configuration file.");
|
Option & argDeleteEffect = parser.add<Option> (0x0, "deleteEffect" , "Delete a custom created JSON Effect configuration file.");
|
||||||
BooleanOption & argServerInfo = parser.add<BooleanOption>('l', "list" , "List server info and active effects with priority and duration");
|
BooleanOption & argServerInfo = parser.add<BooleanOption>('l', "list" , "List server info and active effects with priority and duration");
|
||||||
BooleanOption & argSysInfo = parser.add<BooleanOption>('s', "sysinfo" , "show system info");
|
BooleanOption & argSysInfo = parser.add<BooleanOption>('s', "sysinfo" , "show system info");
|
||||||
BooleanOption & argClear = parser.add<BooleanOption>('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
BooleanOption & argClear = parser.add<BooleanOption>('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
||||||
@ -102,12 +106,12 @@ int main(int argc, char * argv[])
|
|||||||
Option & argEnableComponent = parser.add<Option> ('E', "enable" , "Enable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, FORWARDER, BOBLIGHT_SERVER, GRABBER, V4L, LEDDEVICE]");
|
Option & argEnableComponent = parser.add<Option> ('E', "enable" , "Enable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, FORWARDER, BOBLIGHT_SERVER, GRABBER, V4L, LEDDEVICE]");
|
||||||
Option & argDisableComponent = parser.add<Option> ('D', "disable" , "Disable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, FORWARDER, BOBLIGHT_SERVER, GRABBER, V4L, LEDDEVICE]");
|
Option & argDisableComponent = parser.add<Option> ('D', "disable" , "Disable the Component with the given name. Available Components are [SMOOTHING, BLACKBORDER, FORWARDER, BOBLIGHT_SERVER, GRABBER, V4L, LEDDEVICE]");
|
||||||
Option & argId = parser.add<Option> ('q', "qualifier" , "Identifier(qualifier) of the adjustment to set");
|
Option & argId = parser.add<Option> ('q', "qualifier" , "Identifier(qualifier) of the adjustment to set");
|
||||||
IntOption & argBrightness = parser.add<IntOption> ('L', "brightness" , "Set the brightness gain of the leds");
|
IntOption & argBrightness = parser.add<IntOption> ('L', "brightness" , "Set the brightness gain of the LEDs");
|
||||||
IntOption & argBrightnessC = parser.add<IntOption> (0x0, "brightnessCompensation" , "Set the brightness compensation");
|
IntOption & argBrightnessC = parser.add<IntOption> (0x0, "brightnessCompensation" , "Set the brightness compensation");
|
||||||
IntOption & argBacklightThreshold = parser.add<IntOption> ('n', "backlightThreshold" , "threshold for activating backlight (minimum brightness)");
|
IntOption & argBacklightThreshold = parser.add<IntOption> ('n', "backlightThreshold" , "threshold for activating backlight (minimum brightness)");
|
||||||
IntOption & argBacklightColored = parser.add<IntOption> (0x0, "backlightColored" , "0 = white backlight; 1 = colored backlight");
|
IntOption & argBacklightColored = parser.add<IntOption> (0x0, "backlightColored" , "0 = white backlight; 1 = colored backlight");
|
||||||
DoubleOption & argGamma = parser.add<DoubleOption> ('g', "gamma" , "Set the overall gamma of the leds");
|
DoubleOption & argGamma = parser.add<DoubleOption> ('g', "gamma" , "Set the overall gamma of the LEDs");
|
||||||
BooleanOption & argPrint = parser.add<BooleanOption>(0x0, "print" , "Print the json input and output messages on stdout");
|
BooleanOption & argPrint = parser.add<BooleanOption>(0x0, "print" , "Print the JSON input and output messages on stdout");
|
||||||
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help" , "Show this help message and exit");
|
BooleanOption & argHelp = parser.add<BooleanOption>('h', "help" , "Show this help message and exit");
|
||||||
ColorOption & argRAdjust = parser.add<ColorOption> ('R', "redAdjustment" , "Set the adjustment of the red color (requires colors in hex format as RRGGBB)");
|
ColorOption & argRAdjust = parser.add<ColorOption> ('R', "redAdjustment" , "Set the adjustment of the red color (requires colors in hex format as RRGGBB)");
|
||||||
ColorOption & argGAdjust = parser.add<ColorOption> ('G', "greenAdjustment" , "Set the adjustment of the green color (requires colors in hex format as RRGGBB)");
|
ColorOption & argGAdjust = parser.add<ColorOption> ('G', "greenAdjustment" , "Set the adjustment of the green color (requires colors in hex format as RRGGBB)");
|
||||||
@ -117,15 +121,15 @@ int main(int argc, char * argv[])
|
|||||||
ColorOption & argYAdjust = parser.add<ColorOption> ('Y', "yellowAdjustment" , "Set the adjustment of the yellow color (requires colors in hex format as RRGGBB)");
|
ColorOption & argYAdjust = parser.add<ColorOption> ('Y', "yellowAdjustment" , "Set the adjustment of the yellow color (requires colors in hex format as RRGGBB)");
|
||||||
ColorOption & argWAdjust = parser.add<ColorOption> ('W', "whiteAdjustment" , "Set the adjustment of the white color (requires colors in hex format as RRGGBB)");
|
ColorOption & argWAdjust = parser.add<ColorOption> ('W', "whiteAdjustment" , "Set the adjustment of the white color (requires colors in hex format as RRGGBB)");
|
||||||
ColorOption & argbAdjust = parser.add<ColorOption> ('b', "blackAdjustment" , "Set the adjustment of the black color (requires colors in hex format as RRGGBB)");
|
ColorOption & argbAdjust = parser.add<ColorOption> ('b', "blackAdjustment" , "Set the adjustment of the black color (requires colors in hex format as RRGGBB)");
|
||||||
Option & argMapping = parser.add<Option> ('m', "ledMapping" , "Set the methode for image to led mapping valid values: multicolor_mean, unicolor_mean");
|
Option & argMapping = parser.add<Option> ('m', "ledMapping" , "Set the method for image to led mapping valid values: multi color_mean, uni-color_mean");
|
||||||
Option & argVideoMode = parser.add<Option> ('V', "videoMode" , "Set the video mode valid values: 2D, 3DSBS, 3DTAB");
|
Option & argVideoMode = parser.add<Option> ('V', "videoMode" , "Set the video mode valid values: 2D, 3DSBS, 3DTAB");
|
||||||
IntOption & argSource = parser.add<IntOption> (0x0, "sourceSelect" , "Set current active priority channel and deactivate auto source switching");
|
IntOption & argSource = parser.add<IntOption> (0x0, "sourceSelect" , "Set current active priority channel and deactivate auto source switching");
|
||||||
BooleanOption & argSourceAuto = parser.add<BooleanOption>(0x0, "sourceAutoSelect" , "Enables auto source, if disabled prio by manual selecting input source");
|
BooleanOption & argSourceAuto = parser.add<BooleanOption>(0x0, "sourceAutoSelect" , "Enables auto source, if disabled prio by manual selecting input source");
|
||||||
BooleanOption & argOff = parser.add<BooleanOption>(0x0, "off" , "Deactivates hyperion");
|
BooleanOption & argOff = parser.add<BooleanOption>(0x0, "off" , "Deactivates hyperion");
|
||||||
BooleanOption & argOn = parser.add<BooleanOption>(0x0, "on" , "Activates hyperion");
|
BooleanOption & argOn = parser.add<BooleanOption>(0x0, "on" , "Activates hyperion");
|
||||||
BooleanOption & argConfigGet = parser.add<BooleanOption>(0x0, "configGet" , "Print the current loaded Hyperion configuration file");
|
BooleanOption & argConfigGet = parser.add<BooleanOption>(0x0, "configGet" , "Print the current loaded Hyperion configuration file");
|
||||||
BooleanOption & argSchemaGet = parser.add<BooleanOption>(0x0, "schemaGet" , "Print the json schema for Hyperion configuration");
|
BooleanOption & argSchemaGet = parser.add<BooleanOption>(0x0, "schemaGet" , "Print the JSON schema for Hyperion configuration");
|
||||||
Option & argConfigSet = parser.add<Option> (0x0, "configSet" , "Write to the actual loaded configuration file. Should be a Json object string.");
|
Option & argConfigSet = parser.add<Option> (0x0, "configSet" , "Write to the actual loaded configuration file. Should be a JSON object string.");
|
||||||
|
|
||||||
// parse all _options
|
// parse all _options
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
@ -197,7 +201,9 @@ int main(int argc, char * argv[])
|
|||||||
|
|
||||||
// authorization token specified. Use it first
|
// authorization token specified. Use it first
|
||||||
if (parser.isSet(argToken))
|
if (parser.isSet(argToken))
|
||||||
|
{
|
||||||
connection.setToken(argToken.value(parser));
|
connection.setToken(argToken.value(parser));
|
||||||
|
}
|
||||||
|
|
||||||
// If a specific Hyperion instance is given, set it
|
// If a specific Hyperion instance is given, set it
|
||||||
if (parser.isSet(argInstance))
|
if (parser.isSet(argInstance))
|
||||||
@ -316,7 +322,7 @@ int main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
catch (const std::runtime_error & e)
|
catch (const std::runtime_error & e)
|
||||||
{
|
{
|
||||||
// An error occured. Display error and quit
|
// An error occurred. Display error and quit
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
HyperionDaemon *HyperionDaemon::daemon = nullptr;
|
HyperionDaemon *HyperionDaemon::daemon = nullptr;
|
||||||
|
|
||||||
HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode)
|
HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool logLvlOverwrite, bool readonlyMode)
|
||||||
: QObject(parent), _log(Logger::getInstance("DAEMON"))
|
: QObject(parent), _log(Logger::getInstance("DAEMON"))
|
||||||
, _instanceManager(new HyperionIManager(rootPath, this, readonlyMode))
|
, _instanceManager(new HyperionIManager(rootPath, this, readonlyMode))
|
||||||
, _authManager(new AuthManager(this, readonlyMode))
|
, _authManager(new AuthManager(this, readonlyMode))
|
||||||
@ -101,12 +101,14 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, bool log
|
|||||||
|
|
||||||
// set inital log lvl if the loglvl wasn't overwritten by arg
|
// set inital log lvl if the loglvl wasn't overwritten by arg
|
||||||
if (!logLvlOverwrite)
|
if (!logLvlOverwrite)
|
||||||
|
{
|
||||||
handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER));
|
handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER));
|
||||||
|
}
|
||||||
|
|
||||||
createCecHandler();
|
createCecHandler();
|
||||||
|
|
||||||
// init EffectFileHandler
|
// init EffectFileHandler
|
||||||
EffectFileHandler *efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this);
|
EffectFileHandler* efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this);
|
||||||
connect(this, &HyperionDaemon::settingsChanged, efh, &EffectFileHandler::handleSettingsUpdate);
|
connect(this, &HyperionDaemon::settingsChanged, efh, &EffectFileHandler::handleSettingsUpdate);
|
||||||
|
|
||||||
// connect and apply settings for AuthManager
|
// connect and apply settings for AuthManager
|
||||||
@ -135,7 +137,7 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, bool log
|
|||||||
// return videoMode changes from Daemon to HyperionIManager
|
// return videoMode changes from Daemon to HyperionIManager
|
||||||
connect(this, &HyperionDaemon::videoMode, _instanceManager, &HyperionIManager::newVideoMode);
|
connect(this, &HyperionDaemon::videoMode, _instanceManager, &HyperionIManager::newVideoMode);
|
||||||
|
|
||||||
// ---- grabber -----
|
// ---- grabber -----
|
||||||
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) && !defined(ENABLE_X11) && !defined(ENABLE_XCB) && !defined(ENABLE_AMLOGIC) && !defined(ENABLE_QT) && !defined(ENABLE_DX)
|
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) && !defined(ENABLE_X11) && !defined(ENABLE_XCB) && !defined(ENABLE_AMLOGIC) && !defined(ENABLE_QT) && !defined(ENABLE_DX)
|
||||||
Info(_log, "No platform capture supported on this platform");
|
Info(_log, "No platform capture supported on this platform");
|
||||||
#endif
|
#endif
|
||||||
@ -178,7 +180,7 @@ void HyperionDaemon::freeObjects()
|
|||||||
delete _jsonServer;
|
delete _jsonServer;
|
||||||
_jsonServer = nullptr;
|
_jsonServer = nullptr;
|
||||||
|
|
||||||
if (_flatBufferServer)
|
if (_flatBufferServer != nullptr)
|
||||||
{
|
{
|
||||||
auto flatBufferServerThread = _flatBufferServer->thread();
|
auto flatBufferServerThread = _flatBufferServer->thread();
|
||||||
flatBufferServerThread->quit();
|
flatBufferServerThread->quit();
|
||||||
@ -187,7 +189,7 @@ void HyperionDaemon::freeObjects()
|
|||||||
_flatBufferServer = nullptr;
|
_flatBufferServer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_protoServer)
|
if (_protoServer != nullptr)
|
||||||
{
|
{
|
||||||
auto protoServerThread = _protoServer->thread();
|
auto protoServerThread = _protoServer->thread();
|
||||||
protoServerThread->quit();
|
protoServerThread->quit();
|
||||||
@ -197,7 +199,7 @@ void HyperionDaemon::freeObjects()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//ssdp before webserver
|
//ssdp before webserver
|
||||||
if (_ssdp)
|
if (_ssdp != nullptr)
|
||||||
{
|
{
|
||||||
auto ssdpThread = _ssdp->thread();
|
auto ssdpThread = _ssdp->thread();
|
||||||
ssdpThread->quit();
|
ssdpThread->quit();
|
||||||
@ -206,18 +208,18 @@ void HyperionDaemon::freeObjects()
|
|||||||
_ssdp = nullptr;
|
_ssdp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_webserver)
|
if (_webserver != nullptr)
|
||||||
{
|
{
|
||||||
auto webserverThread =_webserver->thread();
|
auto webserverThread = _webserver->thread();
|
||||||
webserverThread->quit();
|
webserverThread->quit();
|
||||||
webserverThread->wait();
|
webserverThread->wait();
|
||||||
delete webserverThread;
|
delete webserverThread;
|
||||||
_webserver = nullptr;
|
_webserver = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sslWebserver)
|
if (_sslWebserver != nullptr)
|
||||||
{
|
{
|
||||||
auto sslWebserverThread =_sslWebserver->thread();
|
auto sslWebserverThread = _sslWebserver->thread();
|
||||||
sslWebserverThread->quit();
|
sslWebserverThread->quit();
|
||||||
sslWebserverThread->wait();
|
sslWebserverThread->wait();
|
||||||
delete sslWebserverThread;
|
delete sslWebserverThread;
|
||||||
@ -225,7 +227,7 @@ void HyperionDaemon::freeObjects()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_CEC
|
#ifdef ENABLE_CEC
|
||||||
if (_cecHandler)
|
if (_cecHandler != nullptr)
|
||||||
{
|
{
|
||||||
auto cecHandlerThread = _cecHandler->thread();
|
auto cecHandlerThread = _cecHandler->thread();
|
||||||
cecHandlerThread->quit();
|
cecHandlerThread->quit();
|
||||||
@ -239,7 +241,11 @@ void HyperionDaemon::freeObjects()
|
|||||||
// stop Hyperions (non blocking)
|
// stop Hyperions (non blocking)
|
||||||
_instanceManager->stopAll();
|
_instanceManager->stopAll();
|
||||||
|
|
||||||
|
#ifdef ENABLE_AVAHI
|
||||||
delete _bonjourBrowserWrapper;
|
delete _bonjourBrowserWrapper;
|
||||||
|
_bonjourBrowserWrapper = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
delete _amlGrabber;
|
delete _amlGrabber;
|
||||||
delete _dispmanx;
|
delete _dispmanx;
|
||||||
delete _fbGrabber;
|
delete _fbGrabber;
|
||||||
@ -249,7 +255,7 @@ void HyperionDaemon::freeObjects()
|
|||||||
delete _v4l2Grabber;
|
delete _v4l2Grabber;
|
||||||
|
|
||||||
_v4l2Grabber = nullptr;
|
_v4l2Grabber = nullptr;
|
||||||
_bonjourBrowserWrapper = nullptr;
|
|
||||||
_amlGrabber = nullptr;
|
_amlGrabber = nullptr;
|
||||||
_dispmanx = nullptr;
|
_dispmanx = nullptr;
|
||||||
_fbGrabber = nullptr;
|
_fbGrabber = nullptr;
|
||||||
@ -266,7 +272,7 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
|
|
||||||
// Create FlatBuffer server in thread
|
// Create FlatBuffer server in thread
|
||||||
_flatBufferServer = new FlatBufferServer(getSetting(settings::FLATBUFSERVER));
|
_flatBufferServer = new FlatBufferServer(getSetting(settings::FLATBUFSERVER));
|
||||||
QThread *fbThread = new QThread(this);
|
QThread* fbThread = new QThread(this);
|
||||||
fbThread->setObjectName("FlatBufferServerThread");
|
fbThread->setObjectName("FlatBufferServerThread");
|
||||||
_flatBufferServer->moveToThread(fbThread);
|
_flatBufferServer->moveToThread(fbThread);
|
||||||
connect(fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer);
|
connect(fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer);
|
||||||
@ -276,7 +282,7 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
|
|
||||||
// Create Proto server in thread
|
// Create Proto server in thread
|
||||||
_protoServer = new ProtoServer(getSetting(settings::PROTOSERVER));
|
_protoServer = new ProtoServer(getSetting(settings::PROTOSERVER));
|
||||||
QThread *pThread = new QThread(this);
|
QThread* pThread = new QThread(this);
|
||||||
pThread->setObjectName("ProtoServerThread");
|
pThread->setObjectName("ProtoServerThread");
|
||||||
_protoServer->moveToThread(pThread);
|
_protoServer->moveToThread(pThread);
|
||||||
connect(pThread, &QThread::started, _protoServer, &ProtoServer::initServer);
|
connect(pThread, &QThread::started, _protoServer, &ProtoServer::initServer);
|
||||||
@ -286,7 +292,7 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
|
|
||||||
// Create Webserver in thread
|
// Create Webserver in thread
|
||||||
_webserver = new WebServer(getSetting(settings::WEBSERVER), false);
|
_webserver = new WebServer(getSetting(settings::WEBSERVER), false);
|
||||||
QThread *wsThread = new QThread(this);
|
QThread* wsThread = new QThread(this);
|
||||||
wsThread->setObjectName("WebServerThread");
|
wsThread->setObjectName("WebServerThread");
|
||||||
_webserver->moveToThread(wsThread);
|
_webserver->moveToThread(wsThread);
|
||||||
connect(wsThread, &QThread::started, _webserver, &WebServer::initServer);
|
connect(wsThread, &QThread::started, _webserver, &WebServer::initServer);
|
||||||
@ -296,7 +302,7 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
|
|
||||||
// Create SSL Webserver in thread
|
// Create SSL Webserver in thread
|
||||||
_sslWebserver = new WebServer(getSetting(settings::WEBSERVER), true);
|
_sslWebserver = new WebServer(getSetting(settings::WEBSERVER), true);
|
||||||
QThread *sslWsThread = new QThread(this);
|
QThread* sslWsThread = new QThread(this);
|
||||||
sslWsThread->setObjectName("SSLWebServerThread");
|
sslWsThread->setObjectName("SSLWebServerThread");
|
||||||
_sslWebserver->moveToThread(sslWsThread);
|
_sslWebserver->moveToThread(sslWsThread);
|
||||||
connect(sslWsThread, &QThread::started, _sslWebserver, &WebServer::initServer);
|
connect(sslWsThread, &QThread::started, _sslWebserver, &WebServer::initServer);
|
||||||
@ -311,7 +317,7 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
getSetting(settings::JSONSERVER).object()["port"].toInt(),
|
getSetting(settings::JSONSERVER).object()["port"].toInt(),
|
||||||
getSetting(settings::WEBSERVER).object()["sslPort"].toInt(),
|
getSetting(settings::WEBSERVER).object()["sslPort"].toInt(),
|
||||||
getSetting(settings::GENERAL).object()["name"].toString());
|
getSetting(settings::GENERAL).object()["name"].toString());
|
||||||
QThread *ssdpThread = new QThread(this);
|
QThread* ssdpThread = new QThread(this);
|
||||||
ssdpThread->setObjectName("SSDPThread");
|
ssdpThread->setObjectName("SSDPThread");
|
||||||
_ssdp->moveToThread(ssdpThread);
|
_ssdp->moveToThread(ssdpThread);
|
||||||
connect(ssdpThread, &QThread::started, _ssdp, &SSDPHandler::initServer);
|
connect(ssdpThread, &QThread::started, _ssdp, &SSDPHandler::initServer);
|
||||||
@ -321,26 +327,34 @@ void HyperionDaemon::startNetworkServices()
|
|||||||
ssdpThread->start();
|
ssdpThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJsonDocument &config)
|
void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJsonDocument& config)
|
||||||
{
|
{
|
||||||
if (settingsType == settings::LOGGER)
|
if (settingsType == settings::LOGGER)
|
||||||
{
|
{
|
||||||
const QJsonObject &logConfig = config.object();
|
const QJsonObject& logConfig = config.object();
|
||||||
|
|
||||||
std::string level = logConfig["level"].toString("warn").toStdString(); // silent warn verbose debug
|
std::string level = logConfig["level"].toString("warn").toStdString(); // silent warn verbose debug
|
||||||
if (level == "silent")
|
if (level == "silent")
|
||||||
|
{
|
||||||
Logger::setLogLevel(Logger::OFF);
|
Logger::setLogLevel(Logger::OFF);
|
||||||
|
}
|
||||||
else if (level == "warn")
|
else if (level == "warn")
|
||||||
|
{
|
||||||
Logger::setLogLevel(Logger::LogLevel::WARNING);
|
Logger::setLogLevel(Logger::LogLevel::WARNING);
|
||||||
|
}
|
||||||
else if (level == "verbose")
|
else if (level == "verbose")
|
||||||
|
{
|
||||||
Logger::setLogLevel(Logger::INFO);
|
Logger::setLogLevel(Logger::INFO);
|
||||||
|
}
|
||||||
else if (level == "debug")
|
else if (level == "debug")
|
||||||
|
{
|
||||||
Logger::setLogLevel(Logger::DEBUG);
|
Logger::setLogLevel(Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (settingsType == settings::SYSTEMCAPTURE)
|
if (settingsType == settings::SYSTEMCAPTURE)
|
||||||
{
|
{
|
||||||
const QJsonObject &grabberConfig = config.object();
|
const QJsonObject& grabberConfig = config.object();
|
||||||
|
|
||||||
_grabber_width = grabberConfig["width"].toInt(96);
|
_grabber_width = grabberConfig["width"].toInt(96);
|
||||||
_grabber_height = grabberConfig["height"].toInt(96);
|
_grabber_height = grabberConfig["height"].toInt(96);
|
||||||
@ -354,11 +368,11 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
_grabber_ge2d_mode = grabberConfig["ge2d_mode"].toInt(0);
|
_grabber_ge2d_mode = grabberConfig["ge2d_mode"].toInt(0);
|
||||||
_grabber_device = grabberConfig["amlogic_grabber"].toString("amvideocap0");
|
_grabber_device = grabberConfig["amlogic_grabber"].toString("amvideocap0");
|
||||||
|
|
||||||
#ifdef ENABLE_OSX
|
#ifdef ENABLE_OSX
|
||||||
QString type = "osx";
|
QString type = "osx";
|
||||||
#else
|
#else
|
||||||
QString type = grabberConfig["type"].toString("auto");
|
QString type = grabberConfig["type"].toString("auto");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// auto eval of type
|
// auto eval of type
|
||||||
if (type == "auto")
|
if (type == "auto")
|
||||||
@ -369,7 +383,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
type = "dispmanx";
|
type = "dispmanx";
|
||||||
}
|
}
|
||||||
// amlogic -> /dev/amvideo exists
|
// amlogic -> /dev/amvideo exists
|
||||||
else if (QFile::exists("/dev/amvideo"))
|
else
|
||||||
|
{
|
||||||
|
if (QFile::exists("/dev/amvideo"))
|
||||||
{
|
{
|
||||||
type = "amlogic";
|
type = "amlogic";
|
||||||
|
|
||||||
@ -382,7 +398,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
{
|
{
|
||||||
// x11 -> if DISPLAY is set
|
// x11 -> if DISPLAY is set
|
||||||
QByteArray envDisplay = qgetenv("DISPLAY");
|
QByteArray envDisplay = qgetenv("DISPLAY");
|
||||||
if ( !envDisplay.isEmpty() )
|
if (!envDisplay.isEmpty())
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_X11)
|
#if defined(ENABLE_X11)
|
||||||
type = "x11";
|
type = "x11";
|
||||||
@ -399,6 +415,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_prevType != type)
|
if (_prevType != type)
|
||||||
{
|
{
|
||||||
@ -406,7 +423,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
|
|
||||||
// stop all capture interfaces
|
// stop all capture interfaces
|
||||||
#ifdef ENABLE_FB
|
#ifdef ENABLE_FB
|
||||||
if(_fbGrabber != nullptr)
|
if (_fbGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_fbGrabber->stop();
|
_fbGrabber->stop();
|
||||||
delete _fbGrabber;
|
delete _fbGrabber;
|
||||||
@ -414,7 +431,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_DISPMANX
|
#ifdef ENABLE_DISPMANX
|
||||||
if(_dispmanx != nullptr)
|
if (_dispmanx != nullptr)
|
||||||
{
|
{
|
||||||
_dispmanx->stop();
|
_dispmanx->stop();
|
||||||
delete _dispmanx;
|
delete _dispmanx;
|
||||||
@ -422,7 +439,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_AMLOGIC
|
#ifdef ENABLE_AMLOGIC
|
||||||
if(_amlGrabber != nullptr)
|
if (_amlGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_amlGrabber->stop();
|
_amlGrabber->stop();
|
||||||
delete _amlGrabber;
|
delete _amlGrabber;
|
||||||
@ -430,7 +447,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_OSX
|
#ifdef ENABLE_OSX
|
||||||
if(_osxGrabber != nullptr)
|
if (_osxGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_osxGrabber->stop();
|
_osxGrabber->stop();
|
||||||
delete _osxGrabber;
|
delete _osxGrabber;
|
||||||
@ -438,7 +455,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_X11
|
#ifdef ENABLE_X11
|
||||||
if(_x11Grabber != nullptr)
|
if (_x11Grabber != nullptr)
|
||||||
{
|
{
|
||||||
_x11Grabber->stop();
|
_x11Grabber->stop();
|
||||||
delete _x11Grabber;
|
delete _x11Grabber;
|
||||||
@ -446,7 +463,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_XCB
|
#ifdef ENABLE_XCB
|
||||||
if(_xcbGrabber != nullptr)
|
if (_xcbGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_xcbGrabber->stop();
|
_xcbGrabber->stop();
|
||||||
delete _xcbGrabber;
|
delete _xcbGrabber;
|
||||||
@ -454,7 +471,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_QT
|
#ifdef ENABLE_QT
|
||||||
if(_qtGrabber != nullptr)
|
if (_qtGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_qtGrabber->stop();
|
_qtGrabber->stop();
|
||||||
delete _qtGrabber;
|
delete _qtGrabber;
|
||||||
@ -462,7 +479,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_DX
|
#ifdef ENABLE_DX
|
||||||
if(_dxGrabber != nullptr)
|
if (_dxGrabber != nullptr)
|
||||||
{
|
{
|
||||||
_dxGrabber->stop();
|
_dxGrabber->stop();
|
||||||
delete _dxGrabber;
|
delete _dxGrabber;
|
||||||
@ -474,7 +491,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
if (type == "framebuffer")
|
if (type == "framebuffer")
|
||||||
{
|
{
|
||||||
if (_fbGrabber == nullptr)
|
if (_fbGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberFramebuffer(grabberConfig);
|
createGrabberFramebuffer(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_FB
|
#ifdef ENABLE_FB
|
||||||
_fbGrabber->tryStart();
|
_fbGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -482,7 +501,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "dispmanx")
|
else if (type == "dispmanx")
|
||||||
{
|
{
|
||||||
if (_dispmanx == nullptr)
|
if (_dispmanx == nullptr)
|
||||||
|
{
|
||||||
createGrabberDispmanx();
|
createGrabberDispmanx();
|
||||||
|
}
|
||||||
#ifdef ENABLE_DISPMANX
|
#ifdef ENABLE_DISPMANX
|
||||||
_dispmanx->tryStart();
|
_dispmanx->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -490,7 +511,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "amlogic")
|
else if (type == "amlogic")
|
||||||
{
|
{
|
||||||
if (_amlGrabber == nullptr)
|
if (_amlGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberAmlogic();
|
createGrabberAmlogic();
|
||||||
|
}
|
||||||
#ifdef ENABLE_AMLOGIC
|
#ifdef ENABLE_AMLOGIC
|
||||||
_amlGrabber->tryStart();
|
_amlGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -498,7 +521,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "osx")
|
else if (type == "osx")
|
||||||
{
|
{
|
||||||
if (_osxGrabber == nullptr)
|
if (_osxGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberOsx(grabberConfig);
|
createGrabberOsx(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_OSX
|
#ifdef ENABLE_OSX
|
||||||
_osxGrabber->tryStart();
|
_osxGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -506,7 +531,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "x11")
|
else if (type == "x11")
|
||||||
{
|
{
|
||||||
if (_x11Grabber == nullptr)
|
if (_x11Grabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberX11(grabberConfig);
|
createGrabberX11(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_X11
|
#ifdef ENABLE_X11
|
||||||
_x11Grabber->tryStart();
|
_x11Grabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -514,7 +541,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "xcb")
|
else if (type == "xcb")
|
||||||
{
|
{
|
||||||
if (_xcbGrabber == nullptr)
|
if (_xcbGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberXcb(grabberConfig);
|
createGrabberXcb(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_XCB
|
#ifdef ENABLE_XCB
|
||||||
_xcbGrabber->tryStart();
|
_xcbGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -522,7 +551,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "qt")
|
else if (type == "qt")
|
||||||
{
|
{
|
||||||
if (_qtGrabber == nullptr)
|
if (_qtGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberQt(grabberConfig);
|
createGrabberQt(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_QT
|
#ifdef ENABLE_QT
|
||||||
_qtGrabber->tryStart();
|
_qtGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -530,7 +561,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
else if (type == "dx")
|
else if (type == "dx")
|
||||||
{
|
{
|
||||||
if (_dxGrabber == nullptr)
|
if (_dxGrabber == nullptr)
|
||||||
|
{
|
||||||
createGrabberDx(grabberConfig);
|
createGrabberDx(grabberConfig);
|
||||||
|
}
|
||||||
#ifdef ENABLE_DX
|
#ifdef ENABLE_DX
|
||||||
_dxGrabber->tryStart();
|
_dxGrabber->tryStart();
|
||||||
#endif
|
#endif
|
||||||
@ -545,10 +578,13 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
}
|
}
|
||||||
else if (settingsType == settings::V4L2)
|
else if (settingsType == settings::V4L2)
|
||||||
{
|
{
|
||||||
const QJsonObject &grabberConfig = config.object();
|
|
||||||
|
#if defined(ENABLE_CEC) || defined(ENABLE_V4L2)
|
||||||
|
const QJsonObject& grabberConfig = config.object();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_CEC
|
#ifdef ENABLE_CEC
|
||||||
QString operation;
|
if (_cecHandler != nullptr && grabberConfig["cecDetection"].toBool(false))
|
||||||
if (_cecHandler && grabberConfig["cecDetection"].toBool(false))
|
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
@ -559,7 +595,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_v4l2Grabber != nullptr)
|
if (_v4l2Grabber != nullptr)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_V4L2
|
#ifdef ENABLE_V4L2
|
||||||
_v4l2Grabber = new V4L2Wrapper(
|
_v4l2Grabber = new V4L2Wrapper(
|
||||||
@ -632,7 +670,7 @@ void HyperionDaemon::createGrabberAmlogic()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberX11(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberX11(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_X11
|
#ifdef ENABLE_X11
|
||||||
_x11Grabber = new X11Wrapper(
|
_x11Grabber = new X11Wrapper(
|
||||||
@ -651,7 +689,7 @@ void HyperionDaemon::createGrabberX11(const QJsonObject &grabberConfig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberXcb(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberXcb(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_XCB
|
#ifdef ENABLE_XCB
|
||||||
_xcbGrabber = new XcbWrapper(
|
_xcbGrabber = new XcbWrapper(
|
||||||
@ -670,7 +708,7 @@ void HyperionDaemon::createGrabberXcb(const QJsonObject &grabberConfig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberQt(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberQt(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_QT
|
#ifdef ENABLE_QT
|
||||||
_qtGrabber = new QtWrapper(
|
_qtGrabber = new QtWrapper(
|
||||||
@ -689,7 +727,7 @@ void HyperionDaemon::createGrabberQt(const QJsonObject &grabberConfig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberDx(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberDx(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_DX
|
#ifdef ENABLE_DX
|
||||||
_dxGrabber = new DirectXWrapper(
|
_dxGrabber = new DirectXWrapper(
|
||||||
@ -708,7 +746,7 @@ void HyperionDaemon::createGrabberDx(const QJsonObject &grabberConfig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberFramebuffer(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberFramebuffer(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_FB
|
#ifdef ENABLE_FB
|
||||||
// Construct and start the framebuffer grabber if the configuration is present
|
// Construct and start the framebuffer grabber if the configuration is present
|
||||||
@ -726,7 +764,7 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject &grabberConfig)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HyperionDaemon::createGrabberOsx(const QJsonObject &grabberConfig)
|
void HyperionDaemon::createGrabberOsx(const QJsonObject& grabberConfig)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_OSX
|
#ifdef ENABLE_OSX
|
||||||
// Construct and start the osx grabber if the configuration is present
|
// Construct and start the osx grabber if the configuration is present
|
||||||
@ -749,14 +787,16 @@ void HyperionDaemon::createCecHandler()
|
|||||||
#if defined(ENABLE_V4L2) && defined(ENABLE_CEC)
|
#if defined(ENABLE_V4L2) && defined(ENABLE_CEC)
|
||||||
_cecHandler = new CECHandler;
|
_cecHandler = new CECHandler;
|
||||||
|
|
||||||
QThread * thread = new QThread(this);
|
QThread* thread = new QThread(this);
|
||||||
thread->setObjectName("CECThread");
|
thread->setObjectName("CECThread");
|
||||||
_cecHandler->moveToThread(thread);
|
_cecHandler->moveToThread(thread);
|
||||||
thread->start();
|
thread->start();
|
||||||
|
|
||||||
connect(_cecHandler, &CECHandler::cecEvent, [&] (CECEvent event) {
|
connect(_cecHandler, &CECHandler::cecEvent, [&](CECEvent event) {
|
||||||
if (_v4l2Grabber)
|
if (_v4l2Grabber != nullptr)
|
||||||
|
{
|
||||||
_v4l2Grabber->handleCecEvent(event);
|
_v4l2Grabber->handleCecEvent(event);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Info(_log, "CEC handler created");
|
Info(_log, "CEC handler created");
|
||||||
|
@ -86,18 +86,18 @@ class HyperionDaemon : public QObject
|
|||||||
friend SysTray;
|
friend SysTray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HyperionDaemon(QString rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode = false);
|
HyperionDaemon(const QString& rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode = false);
|
||||||
~HyperionDaemon();
|
~HyperionDaemon();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get webserver pointer (systray)
|
/// @brief Get webserver pointer (systray)
|
||||||
///
|
///
|
||||||
WebServer* getWebServerInstance() { return _webserver; };
|
WebServer *getWebServerInstance() { return _webserver; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get the current videoMode
|
/// @brief Get the current videoMode
|
||||||
///
|
///
|
||||||
VideoMode getVideoMode() const { return _currVideoMode; };
|
VideoMode getVideoMode() const { return _currVideoMode; }
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief get the settings
|
/// @brief get the settings
|
||||||
@ -106,7 +106,7 @@ public:
|
|||||||
|
|
||||||
void startNetworkServices();
|
void startNetworkServices();
|
||||||
|
|
||||||
static HyperionDaemon* getInstance() { return daemon; };
|
static HyperionDaemon* getInstance() { return daemon; }
|
||||||
static HyperionDaemon* daemon;
|
static HyperionDaemon* daemon;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import json, sys, glob
|
import json, sys
|
||||||
from os import path
|
from os import path
|
||||||
from jsonschema import Draft3Validator, RefResolver
|
from jsonschema import Draft3Validator, RefResolver
|
||||||
|
|
||||||
|
@ -190,12 +190,13 @@ class Draft3Validator(object):
|
|||||||
for type in types:
|
for type in types:
|
||||||
if self.is_type(type, "object"):
|
if self.is_type(type, "object"):
|
||||||
if self.is_valid(instance, type):
|
if self.is_valid(instance, type):
|
||||||
return
|
break
|
||||||
elif self.is_type(type, "string"):
|
elif self.is_type(type, "string"):
|
||||||
if self.is_type(instance, type):
|
if self.is_type(instance, type):
|
||||||
return
|
break
|
||||||
else:
|
else:
|
||||||
yield ValidationError(_types_msg(instance, types))
|
yield ValidationError(_types_msg(instance, types))
|
||||||
|
return
|
||||||
|
|
||||||
def validate_properties(self, properties, instance, schema):
|
def validate_properties(self, properties, instance, schema):
|
||||||
if not self.is_type(instance, "object"):
|
if not self.is_type(instance, "object"):
|
||||||
|
Loading…
Reference in New Issue
Block a user