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:
LordGrey 2020-11-14 17:58:56 +01:00 committed by GitHub
parent d28540a7fe
commit efc2046ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
93 changed files with 1140 additions and 1172 deletions

4
.gitignore vendored
View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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>

View File

@ -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"
} }

View File

@ -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) );
} }

View File

@ -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();
}); });
} }

View File

@ -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);

View File

@ -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
} }
] ]
} }

View File

@ -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;
}; };

View File

@ -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;

View File

@ -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,10 +30,10 @@ 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:
/// ///

View File

@ -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;
}; };

View File

@ -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);
} }

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
/// ///

View File

@ -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;

View File

@ -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(); }

View File

@ -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;

View File

@ -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.

View File

@ -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();
}; };

View File

@ -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:

View File

@ -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,7 +33,7 @@ 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:

View File

@ -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
/// ///

View File

@ -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

View File

@ -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())

View File

@ -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;

View File

@ -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())
{ {
@ -693,7 +694,8 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
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 &params = 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() );

View File

@ -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);

View File

@ -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
{ {

View File

@ -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);

View File

@ -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"))
{ {

View File

@ -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

View File

@ -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);

View File

@ -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;
} }
} }

View File

@ -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
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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.

View File

@ -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;
} }
} }

View File

@ -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,8 +166,10 @@ 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,10 +293,12 @@ 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))

View File

@ -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

View File

@ -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",

View File

@ -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
}, },

View File

@ -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,7 +178,7 @@ 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
{ {
@ -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)
{ {

View File

@ -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;

View File

@ -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 );
} }

View File

@ -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;
} }

View File

@ -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 );

View File

@ -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:

View File

@ -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()) )

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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,16 +12,16 @@ 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)
@ -81,11 +85,10 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
_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())
{ {
@ -159,10 +162,10 @@ 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();
@ -178,9 +181,9 @@ 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;
} }
@ -188,31 +191,29 @@ int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
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;
@ -227,6 +228,6 @@ void LedDeviceFadeCandy::sendFadeCandyConfiguration()
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));
} }

View File

@ -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

View File

@ -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,7 +15,6 @@
// Constants // Constants
namespace { namespace {
const bool verbose = false; const bool verbose = false;
const bool verbose3 = false; const bool verbose3 = false;
@ -65,12 +65,15 @@ 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
@ -130,9 +133,9 @@ bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
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());
@ -156,7 +159,7 @@ bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
_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
@ -224,23 +227,23 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
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)
@ -261,7 +264,7 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
{ {
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)
{ {
@ -278,7 +281,7 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
// 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)
{ {
@ -292,20 +295,20 @@ 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)
{ {
@ -319,7 +322,7 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
{ {
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
@ -375,7 +378,7 @@ 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);
@ -441,7 +444,6 @@ QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
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;
} }
@ -526,7 +528,6 @@ QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
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,32 +538,24 @@ 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) {
@ -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 );
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, "[%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();
}

View File

@ -49,9 +49,11 @@ public:
/// ///
/// @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
@ -159,13 +161,6 @@ private:
/// ///
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

View File

@ -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 0s
0x01, //xy Brightness
0x00, // Reserved, write 0s
};
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;
@ -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 );

View File

@ -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 0s
0x01, //xy Brightness
0x00, // Reserved, write 0s
};
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

View File

@ -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 );

View File

@ -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

View File

@ -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 );

View File

@ -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

View File

@ -1,4 +1,3 @@
// STL includes // STL includes
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
@ -70,7 +69,7 @@ bool ProviderUdp::init(const QJsonObject &deviceConfig)
} }
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);
@ -131,20 +130,26 @@ int ProviderUdp::close()
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;
} }

View File

@ -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);

View File

@ -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,

View File

@ -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 );

View File

@ -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

View File

@ -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());

View File

@ -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();
} }

View File

@ -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)

View File

@ -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]);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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();

View File

@ -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;
} }

View File

@ -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,7 +101,9 @@ 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();
@ -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,7 +208,7 @@ void HyperionDaemon::freeObjects()
_ssdp = nullptr; _ssdp = nullptr;
} }
if(_webserver) if (_webserver != nullptr)
{ {
auto webserverThread = _webserver->thread(); auto webserverThread = _webserver->thread();
webserverThread->quit(); webserverThread->quit();
@ -215,7 +217,7 @@ void HyperionDaemon::freeObjects()
_webserver = nullptr; _webserver = nullptr;
} }
if (_sslWebserver) if (_sslWebserver != nullptr)
{ {
auto sslWebserverThread = _sslWebserver->thread(); auto sslWebserverThread = _sslWebserver->thread();
sslWebserverThread->quit(); sslWebserverThread->quit();
@ -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;
@ -329,14 +335,22 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
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)
{ {
@ -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";
@ -399,6 +415,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
} }
} }
} }
}
if (_prevType != type) if (_prevType != type)
{ {
@ -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)
{ {
#if defined(ENABLE_CEC) || defined(ENABLE_V4L2)
const QJsonObject& grabberConfig = config.object(); 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(
@ -755,8 +793,10 @@ void HyperionDaemon::createCecHandler()
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");

View File

@ -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:

View File

@ -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

View File

@ -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"):