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
*.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
### Added
- Cololight support (Cololight Plus & Strip) incl. configuration wizard
- 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
- Grabber: DirectX9 support (#1039)
- 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)
- Added DirectX SDK to CompileHowto
- LED-Devices: Cololight support (Cololight Plus & Strip) incl. configuration wizard
- 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
- 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)
- Windows Installer/Uninstaller notification when Hyperion is running (#1033)
- 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
- 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
### Fixed
- Properly save Hue light state between sessions (#1014)
- AVAHI included in Webserver (#996)
- Also allow an 8-LED configuration when using Karatelight (#1037)
- Fix #1007 - LED's retain last state after clearing a source (#1008)
- Fix Lightpack issue #1015 (#1049)
- Fix #771 color calibration for Kodi 18 (#1044)
- Color calibration for Kodi 18 (#1044)
- LED-Devices: Karatelight, allow an 8-LED configuration (#1037)
- LED-Devices: Save Hue light state between sessions (#1014)
- LED-Devices: LED's retain last state after clearing a source (#1008)
- LED-Devices: Lightpack issue #1015 (#1049)
- Fix various JSON API issues (#1036)
- Fix issue #909, Have ratio correction first and then scale (#1047)
- Fix display argument in hyperion-qt (#1027)
- Fix typos (#1051)
- 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
- 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
# 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
#
# 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")
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${SUBDIRQT}/msvc2019_64")
if (NOT DEFINED ENV{Qt5_DIR})
message(STATUS "Set Qt5 module path: ${SUBDIRQT}")
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${SUBDIRQT}/msvc2019_64/lib/cmake/Qt5")
else()
message(STATUS "Qt5_BASE_DIR: $ENV{Qt5_BASE_DIR}")
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()
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
if (ENABLE_DX)
find_package(DirectX9 REQUIRED)

View File

@ -21,6 +21,7 @@ import socket
import serial
import serial.threaded
from __future__ import division
class SerialToNet(serial.threaded.Protocol):
"""serial->socket"""
@ -152,7 +153,7 @@ to this service over the network.
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(('', args.localport))
srv.bind(('0.0.0.0', args.localport))
try:
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>
</td>
<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>
</td>
</tr>
@ -59,7 +59,7 @@
<label class="ltdlabel" for="ip_cl_bottom" data-i18n="conf_leds_layout_cl_bottom">Bottom</label>
</td>
<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>
</td>
</tr>
@ -68,7 +68,7 @@
<label class="ltdlabel" for="ip_cl_left" data-i18n="conf_leds_layout_cl_left">Left</label>
</td>
<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>
</td>
</tr>
@ -77,7 +77,7 @@
<label class="ltdlabel" for="ip_cl_right" data-i18n="conf_leds_layout_cl_right">Right</label>
</td>
<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>
</td>
</tr>
@ -266,7 +266,7 @@
<label class="ltdlabel" for="ip_ma_ledshoriz" data-i18n="conf_leds_layout_ma_horiz">Horizontal</label>
</td>
<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>
</td>
</tr>
@ -275,7 +275,7 @@
<label class="ltdlabel" for="ip_ma_ledsvert" data-i18n="conf_leds_layout_ma_vert">Vertical</label>
</td>
<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>
</td>
</tr>

View File

@ -359,10 +359,10 @@ function migrateLedConfig(slConfig){
//Default Classic layout
newLedConfig.classic = {
"top" : 8,
"bottom" : 8,
"left" : 5,
"right" : 5,
"top" : 1,
"bottom" : 0,
"left" : 0,
"right" : 0,
"glength" : 0,
"gpos" : 0,
"position" : 0,
@ -386,8 +386,8 @@ function migrateLedConfig(slConfig){
newLedConfig.classic.overlap = slConfig.overlap;
//Default Matrix layout
newLedConfig["matrix"] = { "ledshoriz": 10,
"ledsvert" : 10,
newLedConfig["matrix"] = { "ledshoriz": 1,
"ledsvert" : 1,
"cabling" : "snake",
"start" : "top-left"
}

View File

@ -454,9 +454,9 @@ function requestAdjustment(type, value, complete)
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) );
}

View File

@ -389,7 +389,7 @@ function showInfoDialog(type,header,message)
$(document).on('click', '[data-dismiss-modal]', function () {
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 () {
kodiAddress = $(this).val().trim();
$('#wizp1_body').find("kodiAddress").val(kodiAddress);
$('#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
@ -1585,7 +1587,7 @@ function beginWizardAtmoOrb() {
lights = [];
configuredLights = [];
configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
var configruedOrbIds = conf_editor.getEditor("root.specificOptions.orbIds").getValue().trim();
if (configruedOrbIds.length !== 0) {
configuredLights = configruedOrbIds.split(",").map(Number);
}
@ -1648,13 +1650,16 @@ function beginWizardAtmoOrb() {
async function discover_atmoorb_lights(multiCastGroup, multiCastPort) {
var light = {};
if (multiCastGroup === "")
multiCastGroup = "239.255.255.250";
var params = {};
if (multiCastGroup !== "")
{
params.multiCastGroup = multiCastGroup;
}
if (multiCastPort === "")
multiCastPort = 49692;
let params = { multiCastGroup: multiCastGroup, multiCastPort: multiCastPort };
if (multiCastPort !== 0)
{
params.multiCastPort = multiCastPort;
}
// Get discovered lights
const res = await requestLedDeviceDiscovery('atmoorb', params);

View File

@ -120,7 +120,7 @@
"backgroundEffect" :
{
"enable" : true,
"enable" : false,
"type" : "effect",
"color" : [255,138,0],
"effect" : "Warm mood blobs"
@ -197,10 +197,10 @@
{
"classic":
{
"top" : 8,
"bottom" : 8,
"left" : 5,
"right" : 5,
"top" : 1,
"bottom" : 0,
"left" : 0,
"right" : 0,
"glength" : 0,
"gpos" : 0,
"position" : 0,
@ -221,8 +221,8 @@
"matrix":
{
"ledshoriz": 10,
"ledsvert" : 10,
"ledshoriz": 1,
"ledsvert" : 1,
"cabling" : "snake",
"start" : "top-left"
}
@ -231,160 +231,10 @@
"leds":
[
{
"hmax": 0.125,
"hmax": 1,
"hmin": 0,
"vmax": 0.08,
"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
{
/// Falg indicating if the border is unknown
/// Flag indicating if the border is unknown
bool unknown;
/// The size of the detected horizontal border
@ -48,7 +48,7 @@ namespace hyperion
public:
///
/// 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);
@ -67,9 +67,9 @@ namespace hyperion
template <typename Pixel_T>
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
// center will check right and bottom sids
// centre will check right and bottom sides
int width = image.width();
int height = image.height();
int width33percent = width / 3;
@ -281,7 +281,7 @@ namespace hyperion
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
///
@ -295,7 +295,7 @@ namespace hyperion
}
private:
/// Threshold for the blackborder detector [0 .. 255]
/// Threshold for the black-border detector [0 .. 255]
const uint8_t _blackborderThreshold;
};

View File

@ -44,14 +44,14 @@ namespace hyperion
void setEnabled(bool enable);
///
/// Sets the _hardDisabled state, if True prevents the enable from COMP_BLACKBORDER state emit (mimiks wrong state to external!)
/// It's not possible to enable bb from this method, if the user requsted a disable!
/// 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 black-border detection from this method, if the user requested a disable!
/// @param disable The new state
///
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
/// will return true else false
///
@ -64,10 +64,11 @@ namespace hyperion
{
// get the border for the single image
BlackBorder imageBorder;
if (!enabled())
{
imageBorder.horizontalSize = 0;
imageBorder.verticalSize = 0;
if (!enabled())
{
imageBorder.unknown=true;
_currentBorder = imageBorder;
return true;
@ -98,7 +99,7 @@ namespace hyperion
private slots:
///
/// @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
///
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
@ -121,7 +122,7 @@ namespace hyperion
///
bool updateBorder(const BlackBorder & newDetectedBorder);
/// flag for blackborder detector usage
/// flag for black-border detector usage
bool _enabled;
/// 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
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;
/// The border detection mode
QString _detectionMode;
/// The blackborder detector
/// The black-border detector
BlackBorderDetector* _detector;
/// The current detected border
@ -148,9 +149,9 @@ namespace hyperion
/// The border detected in the previous frame
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;
/// 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;
/// old threshold
double _oldThreshold;

View File

@ -19,7 +19,7 @@ private:
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
/// Searching for hyperion http service by default
///
BonjourBrowserWrapper(QObject * parent = 0);
BonjourBrowserWrapper(QObject * parent = nullptr);
public:
@ -30,36 +30,36 @@ public:
///
/// @brief Get all available sessions
///
QMap<QString,BonjourRecord> getAllServices() { return _hyperionSessions; };
QMap<QString, BonjourRecord> getAllServices() { return _hyperionSessions; }
static BonjourBrowserWrapper* instance;
static BonjourBrowserWrapper* getInstance(){ return instance; };
static BonjourBrowserWrapper *getInstance() { return instance; }
signals:
///
/// @brief Emits whenever a change happend
///
void browserChange(const QMap<QString,BonjourRecord>& bRegisters);
void browserChange( const QMap<QString, BonjourRecord> &bRegisters );
private:
/// map of service names and browsers
QMap< QString, BonjourServiceBrowser* > _browsedServices;
QMap<QString, BonjourServiceBrowser *> _browsedServices;
/// Resolver
BonjourServiceResolver* _bonjourResolver;
BonjourServiceResolver *_bonjourResolver;
// contains all current active service sessions
QMap<QString,BonjourRecord> _hyperionSessions;
QMap<QString, BonjourRecord> _hyperionSessions;
QString _bonjourCurrentServiceToResolve;
/// timer to resolve changes
QTimer* _timerBonjourResolver;
QTimer *_timerBonjourResolver;
private slots:
///
/// @brief is called whenever a BonjourServiceBrowser emits change
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
void currentBonjourRecordsChanged( const QList<BonjourRecord> &list );
/// @brief new record resolved
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
void bonjourRecordResolved( const QHostInfo &hostInfo, int port );
///
/// @brief timer slot which updates regularly entries

View File

@ -33,6 +33,8 @@ public:
QString value(Parser &parser) const;
const char* getCString(Parser &parser) const;
virtual ~Option();
protected:
QString _error;
};

View File

@ -1,7 +1,6 @@
#pragma once
#include <QtCore>
#include <QtGui>
#include "ColorOption.h"
#include "ColorsOption.h"
#include "DoubleOption.h"
@ -24,8 +23,8 @@ protected:
/* No public inheritance because we need to modify a few methods */
QCommandLineParser _parser;
QStringList _getNames(const char shortOption, const QString longOption);
QString _getDescription(const QString description, const QString default_=QString());
QStringList _getNames(const char shortOption, const QString& longOption);
QString _getDescription(const QString& description, const QString& default_=QString());
public:
~Parser() override;
@ -97,24 +96,24 @@ public:
{
if(description.size())
setApplicationDescription(description);
};
}
QCommandLineOption addHelpOption()
{
return _parser.addHelpOption();
};
}
bool addOption(Option &option);
bool addOption(Option *option);
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString())
{
_parser.addPositionalArgument(name, description, syntax);
};
}
QCommandLineOption addVersionOption()
{
return _parser.addVersionOption();
};
}
QString applicationDescription() const
{
@ -166,7 +165,7 @@ public:
_parser.setSingleDashWordOptionMode(singleDashWordOptionMode);
}
void showHelp(int exitCode = 0)
[[ noreturn ]] void showHelp(int exitCode = 0)
{
_parser.showHelp(exitCode);
}

View File

@ -1,11 +1,5 @@
#pragma once
// Python includes
// collide of qt slots macro
#undef slots
#include "Python.h"
#define slots
// Qt includes
#include <QThread>
#include <QJsonObject>
@ -44,13 +38,13 @@ public:
int getPriority() const { return _priority; }
///
/// @brief Set manual interuption to true,
/// Note: DO NOT USE QThread::interuption!
/// @brief Set manual interruption to true,
/// Note: DO NOT USE QThread::interruption!
///
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
///
bool isInterruptionRequested() { return _interupt; }
@ -88,7 +82,7 @@ private:
QVector<ColorRgb> _colors;
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 {};
QSize _imageSize;

View File

@ -15,7 +15,7 @@ private:
public:
static EffectFileHandler* efhInstance;
static EffectFileHandler* getInstance() { return efhInstance; };
static EffectFileHandler* getInstance() { return efhInstance; }
///
/// @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
///
bool setWidthHeight(int width, int height) override { return true; };
bool setWidthHeight(int width, int height) override { return true; }
///
/// @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
///
bool setWidthHeight(int width, int height) override { return true; };
bool setWidthHeight(int width, int height) override { return true; }
///
/// @brief Apply new pixelDecimation

View File

@ -15,7 +15,7 @@ public:
~XcbWrapper() override;
public slots:
virtual void action();
void action() override;
private:
XcbGrabber _grabber;

View File

@ -21,7 +21,7 @@ class AuthManager : public QObject
private:
friend class HyperionDaemon;
/// constructor is private, can be called from HyperionDaemon
AuthManager(QObject *parent = 0, bool readonlyMode = false);
AuthManager(QObject *parent = nullptr, bool readonlyMode = false);
public:
struct AuthDefinition

View File

@ -19,14 +19,14 @@ public:
// listen for config changes
connect(_hyperion, &Hyperion::settingsChanged, this, &BGEffectHandler::handleSettingsUpdate);
// init
// initialization
handleSettingsUpdate(settings::BGEFFECT, _hyperion->getSetting(settings::BGEFFECT));
};
}
private slots:
///
/// @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
///
void handleSettingsUpdate(settings::type type, const QJsonDocument& config)
@ -36,7 +36,7 @@ private slots:
const QJsonObject& BGEffectConfig = config.object();
#define BGCONFIG_ARRAY bgColorConfig.toArray()
// clear bg prioritiy
// clear background priority
_hyperion->clear(254);
// initial background effect/color
if (BGEffectConfig["enable"].toBool(true))
@ -48,24 +48,24 @@ private slots:
{
std::vector<ColorRgb> bg_color = {
ColorRgb {
(uint8_t)BGCONFIG_ARRAY.at(0).toInt(0),
(uint8_t)BGCONFIG_ARRAY.at(1).toInt(0),
(uint8_t)BGCONFIG_ARRAY.at(2).toInt(0)
static_cast<uint8_t>(BGCONFIG_ARRAY.at(0).toInt(0)),
static_cast<uint8_t>(BGCONFIG_ARRAY.at(1).toInt(0)),
static_cast<uint8_t>(BGCONFIG_ARRAY.at(2).toInt(0))
}
};
_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
{
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
}
};
}
private:
/// Hyperion instance pointer

View File

@ -111,7 +111,7 @@ public slots:
///
/// 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()
@ -298,7 +298,7 @@ public slots:
///
/// @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
@ -527,7 +527,7 @@ private:
Logger * _log;
/// count of hardware leds
unsigned _hwLedCount;
int _hwLedCount;
QSize _ledGridSize;

View File

@ -19,9 +19,9 @@
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
/// color-tranform is applied based on a gamma-correction.
/// color-transform is applied based on a gamma-correction.
///
class ImageProcessor : public QObject
{
@ -39,7 +39,7 @@ public:
~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.
/// NB All earlier obtained references will be invalid.
///
@ -53,7 +53,7 @@ public:
///
void setLedString(const LedString& ledString);
/// Returns starte of black border detector
/// Returns state of black border detector
bool blackBorderDetectorEnabled() const;
/// Returns the current _userMappingType, this may not be the current applied type!
@ -66,7 +66,7 @@ public:
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)
/// @param mapType The new mapping type
///
@ -85,7 +85,7 @@ public slots:
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.
/// NB All earlier obtained references will be invalid.
///
@ -117,7 +117,7 @@ public:
// Check black border detection
verifyBorder(image);
// Create a result vector and call the 'in place' functionl
// Create a result vector and call the 'in place' function
switch (_mappingType)
{
case 1: colors = _imageToLeds->getUniLedColor(image); break;
@ -225,7 +225,7 @@ private:
/// The processor for black border detection
hyperion::BlackBorderProcessor * _borderProcessor;
/// The mapping of image-pixels to leds
/// The mapping of image-pixels to LEDs
hyperion::ImageToLedsMap* _imageToLeds;
/// Type of image 2 led mapping

View File

@ -175,7 +175,7 @@ namespace hyperion
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 cummGreen = 0;
uint_fast32_t cummBlue = 0;
@ -209,7 +209,7 @@ namespace hyperion
template <typename Pixel_T>
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 cummGreen = 0;
uint_fast32_t cummBlue = 0;

View File

@ -107,16 +107,6 @@ struct Led
class LedString
{
public:
///
/// Constructs the LedString with no leds
///
LedString();
///
/// Destructor of this LedString
///
~LedString();
///
/// Returns the led specifications
///

View File

@ -11,22 +11,22 @@
///
/// 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
{
public:
MultiColorAdjustment(unsigned ledCnt);
MultiColorAdjustment(int ledCnt);
~MultiColorAdjustment();
/**
* 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 setAdjustmentForLed(const QString& id, unsigned startLed, unsigned endLed);
void setAdjustmentForLed(const QString& id, int startLed, int endLed);
bool verifyAdjustments() const;

View File

@ -58,10 +58,10 @@ public:
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
///
/// @param ledCount The number of leds
/// @param ledCount The number of LEDs
///
PriorityMuxer(int ledCount, QObject * parent);
@ -87,18 +87,18 @@ public:
/// @brief Get the state of source auto selection
/// @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
/// @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
/// @param[in] ledCount The count of leds
/// @brief Update all LED-Colors with min length of >= 1 to fit the new led length
/// @param[in] ledCount The count of LEDs
///
void updateLedColorsLength(int ledCount);
@ -146,13 +146,13 @@ public:
/// @param[in] priority The priority of the channel
/// @param[in] component The component of the channel
/// @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
///
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 ledColors The colors
/// @param timeout_ms The new timeout (defaults to -1 endless)
@ -174,7 +174,7 @@ public:
/// @param priority The priority
/// @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
@ -182,7 +182,7 @@ public:
/// @param[in] priority The priority of the channel to clear
/// @return True if priority has been cleared else false (not found)
///
bool clearInput(uint8_t priority);
bool clearInput(int priority);
///
/// Clears all priority channels
@ -190,7 +190,7 @@ public:
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(); }

View File

@ -3,14 +3,14 @@
#include <utils/Logger.h>
#include <utils/settings.h>
// qt incl
// qt includes
#include <QJsonObject>
class Hyperion;
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
{
@ -24,7 +24,7 @@ public:
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 correct If true will correct json against schema before save
/// @return True on success else false
@ -32,7 +32,7 @@ public:
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
/// @return The requested json data as QJsonDocument
///
@ -42,11 +42,11 @@ public:
/// @brief get the full settings object of this instance (with global settings)
/// @return The requested json
///
const QJsonObject & getSettings() const { return _qconfig; };
const QJsonObject & getSettings() const { return _qconfig; }
signals:
///
/// @brief Emits whenever a config part changed.
/// @brief Emits whenever a configuration part changed.
/// @param type The settings type from enum
/// @param data The data as QJsonDocument
///
@ -54,7 +54,7 @@ signals:
private:
///
/// @brief Add possile migrations steps for config here
/// @brief Add possible migrations steps for configuration here
/// @param config The configuration object
/// @return True when a migration has been triggered
///
@ -73,7 +73,7 @@ private:
/// the schema
static QJsonObject schemaJson;
/// the current config of this instance
/// the current configuration of this instance
QJsonObject _qconfig;
bool _readonlyMode;

View File

@ -62,7 +62,7 @@ public:
///
/// @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.
@ -87,9 +87,11 @@ public:
/// @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.
///
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @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).
@ -116,7 +118,7 @@ public:
///
/// @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
@ -193,7 +195,7 @@ public slots:
///
/// @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.
@ -348,7 +350,7 @@ protected:
/// @param size of the array
/// @param number Number of array items to be converted.
/// @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.

View File

@ -66,64 +66,61 @@ public:
/// @brief Overwrite description address
/// @param addr new address
///
void setDescriptionAddress(const QString& addr) { _descAddress = addr; };
void setDescriptionAddress( const QString &addr ) { _descAddress = addr; }
///
/// @brief Set 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
///
void setFlatBufPort(quint16 port) { _fbsPort = QString::number(port); };
void setFlatBufPort( quint16 port ){_fbsPort = QString::number( 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
///
void setProtoBufPort(quint16 port) { _pbsPort = QString::number(port); };
void setProtoBufPort( quint16 port ) { _pbsPort = QString::number( 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
///
void setJsonServerPort(quint16 port) { _jssPort = QString::number(port); };
void setJsonServerPort( quint16 port ) { _jssPort = QString::number( 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
///
void setSSLServerPort(quint16 port) { _sslPort = QString::number(port); };
void setSSLServerPort( quint16 port ) { _sslPort = QString::number( port ); }
///
/// @brief get new ssl server port
///
quint16 getSSLServerPort() const { return _sslPort.toInt(); };
quint16 getSSLServerPort() const { return _sslPort.toInt(); }
///
/// @brief set new hyperion name
///
void setHyperionName(const QString &name) { _name = name; };
void setHyperionName( const QString &name ) { _name = name; }
///
/// @brief get hyperion name
///
QString getHyperionName() const { return _name; };
QString getHyperionName() const { return _name; }
signals:
///
@ -133,23 +130,18 @@ signals:
/// @param address The ip 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:
Logger* _log;
QUdpSocket* _udpSocket;
Logger *_log;
QUdpSocket *_udpSocket;
QString _serverHeader,
_uuid,
_fbsPort,
_pbsPort,
_jssPort,
_sslPort,
_name,
_descAddress;
QString _serverHeader, _uuid, _fbsPort, _pbsPort, _jssPort, _sslPort, _name, _descAddress;
bool _running;
private slots:
void readPendingDatagrams();
};

View File

@ -38,7 +38,7 @@ public:
_height(other._height),
_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)
@ -150,7 +150,7 @@ public:
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()
@ -163,7 +163,7 @@ public:
_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:

View File

@ -16,7 +16,7 @@ class NetOrigin : public QObject
Q_OBJECT
private:
friend class HyperionDaemon;
NetOrigin(QObject* parent = 0, Logger* log = Logger::getInstance("NETWORK"));
NetOrigin(QObject* parent = nullptr, Logger* log = Logger::getInstance("NETWORK"));
public:
///
@ -33,8 +33,8 @@ public:
///
bool isLocalAddress(const QHostAddress& address, const QHostAddress& local) const;
static NetOrigin* getInstance(){ return instance; };
static NetOrigin* instance;
static NetOrigin *getInstance() { return instance; }
static NetOrigin *instance;
private slots:
///

View File

@ -19,9 +19,6 @@ public:
/// @param adjustB
RgbChannelAdjustment(uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName="");
/// Destructor
~RgbChannelAdjustment();
///
/// Transform the given array value
///

View File

@ -36,9 +36,9 @@ namespace hyperion {
{
std::vector<ColorRgb> fg_color = {
ColorRgb {
(uint8_t)FGCONFIG_ARRAY.at(0).toInt(0),
(uint8_t)FGCONFIG_ARRAY.at(1).toInt(0),
(uint8_t)FGCONFIG_ARRAY.at(2).toInt(0)
static_cast<uint8_t>(FGCONFIG_ARRAY.at(0).toInt(0)),
static_cast<uint8_t>(FGCONFIG_ARRAY.at(1).toInt(0)),
static_cast<uint8_t>(FGCONFIG_ARRAY.at(2).toInt(0))
}
};
hyperion->setColor(FG_PRIORITY, fg_color, fg_duration_ms);
@ -62,22 +62,22 @@ namespace hyperion {
{
const double backlightThreshold = colorConfig["backlightThreshold"].toDouble(0.0);
const bool backlightColored = colorConfig["backlightColored"].toBool(false);
const double brightness = colorConfig["brightness"].toInt(100);
const double brightnessComp = colorConfig["brightnessCompensation"].toInt(100);
const int brightness = colorConfig["brightness"].toInt(100);
const int brightnessComp = colorConfig["brightnessCompensation"].toInt(100);
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
const double gammaG = colorConfig["gammaGreen"].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)
{
const QJsonArray& channelConfig = colorConfig[channelName].toArray();
return RgbChannelAdjustment(
channelConfig[0].toInt(defaultR),
channelConfig[1].toInt(defaultG),
channelConfig[2].toInt(defaultB),
static_cast<uint8_t>(channelConfig[0].toInt(defaultR)),
static_cast<uint8_t>(channelConfig[1].toInt(defaultG)),
static_cast<uint8_t>(channelConfig[2].toInt(defaultB)),
"ChannelAdjust_" + channelName.toUpper()
);
}
@ -101,7 +101,7 @@ namespace hyperion {
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
MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt);
@ -233,7 +233,7 @@ namespace hyperion {
std::sort(midPointsY.begin(), 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
// Expected is at least 50% of width <-> height

View File

@ -48,7 +48,7 @@ public:
{
case QJsonValue::Array:
{
for (const QJsonValue &v : value.toArray())
for (const QJsonValueRef v : value.toArray())
{
ret = getDefaultValue(v);
if (!ret.isEmpty())

View File

@ -33,7 +33,7 @@ class WebServer : public QObject
Q_OBJECT
public:
WebServer (const QJsonDocument& config, bool useSsl, QObject * parent = 0);
WebServer (const QJsonDocument& config, bool useSsl, QObject * parent = nullptr);
~WebServer () override;

View File

@ -473,6 +473,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
{
grabbers["active"] = GrabberWrapper::getInstance()->getActive();
}
// get available grabbers
for (auto grabber : GrabberWrapper::availableGrabbers())
{
@ -688,12 +689,13 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
if (subsArr.contains("all"))
{
subsArr = QJsonArray();
for (const auto &entry : _jsonCB->getCommands())
for (const auto& entry : _jsonCB->getCommands())
{
subsArr.append(entry);
}
}
for (const auto &entry : subsArr)
for (const QJsonValueRef entry : subsArr)
{
// config callbacks just if auth is set
if ((entry == "settings-update" || entry == "token-update") && !API::isAdminAuthorized())
@ -1416,7 +1418,8 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString &
if (subc == "discover")
{
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() );

View File

@ -386,7 +386,7 @@ void BoblightClientConnection::sendLightMessage()
sendMessage(QByteArray(buffer, n));
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);
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;
///
/// 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
{

View File

@ -21,6 +21,11 @@ Option::Option(const QCommandLineOption &other)
: QCommandLineOption(other)
{}
Option::~Option()
{
}
QString Option::value(Parser &parser) const
{
return parser.value(*this);

View File

@ -1,5 +1,3 @@
#include <QtDebug>
#include <QtGui>
#include "commandline/Parser.h"
using namespace commandline;
@ -21,7 +19,7 @@ bool Parser::parse(const QStringList &arguments)
QString value = this->value(*option);
if (!option->validate(*this, value)) {
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);
}
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());
}
QString Parser::errorText() const
{
return (_errorText.size()) ? _errorText : _parser.errorText();
return (!_errorText.isEmpty()) ? _errorText : _parser.errorText();
}
bool Parser::addOption(Option &option)
@ -66,27 +63,27 @@ bool Parser::addOption(Option * const 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;
if (shortOption != 0x0)
{
names << QString(shortOption);
}
if (longOption.size())
if (longOption.size() != 0)
{
names << longOption;
}
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 */
QString formattedDescription(tr(qPrintable(description)));
/* Fill in the default if needed */
if (default_.size())
if (!default_.isEmpty())
{
if(!formattedDescription.contains("%1"))
{

View File

@ -56,8 +56,8 @@ void Effect::setModuleParameters()
PyModule_AddObject(module, "__effectObj", PyCapsule_New((void*)this, "hyperion.__effectObj", nullptr));
// add ledCount variable to the interpreter
unsigned ledCount = 0;
QMetaObject::invokeMethod(_hyperion, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned, ledCount));
int ledCount = 0;
QMetaObject::invokeMethod(_hyperion, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, ledCount));
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", ledCount));
// add minimumWriteTime variable to the interpreter

View File

@ -138,7 +138,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args)
int argCount = PyTuple_Size(args);
if (argCount == 3)
{
// three seperate arguments for red, green, and blue
// three separate arguments for red, green, and blue
ColorRgb color;
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))
{
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);
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;
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);
@ -48,29 +48,35 @@ void ComponentRegister::handleCompStateChangeRequest(hyperion::Components comps,
if(!activated && _prevComponentStates.empty())
{
Debug(_log,"Disable Hyperion, store current component states");
for(const auto comp : _componentStates)
for(const auto &comp : _componentStates)
{
// save state
_prevComponentStates.emplace(comp.first, comp.second);
// disable if enabled
if(comp.second)
{
emit _hyperion->compStateChangeRequest(comp.first, false);
}
}
setNewComponentState(COMP_ALL, false);
}
else if(activated && !_prevComponentStates.empty())
else
{
if(activated && !_prevComponentStates.empty())
{
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.second)
{
emit _hyperion->compStateChangeRequest(comp.first, true);
}
}
_prevComponentStates.clear();
setNewComponentState(COMP_ALL, true);
}
}
_inProgress = false;
}
}

View File

@ -18,7 +18,7 @@
#include <utils/GlobalSignals.h>
#include <utils/Logger.h>
// Leddevice includes
// LedDevice includes
#include <leddevice/LedDeviceWrapper.h>
#include <hyperion/MultiColorAdjustment.h>
@ -46,14 +46,19 @@ Hyperion::Hyperion(quint8 instance, bool readonlyMode)
, _componentRegister(this)
, _ledString(hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
, _imageProcessor(new ImageProcessor(_ledString, this))
, _muxer(_ledString.leds().size(), this)
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(_ledString.leds().size(), getSetting(settings::COLOR).object()))
, _muxer(static_cast<int>(_ledString.leds().size()), this)
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), getSetting(settings::COLOR).object()))
, _ledDeviceWrapper(nullptr)
, _deviceSmooth(nullptr)
, _effectEngine(nullptr)
, _messageForwarder(nullptr)
, _log(Logger::getInstance("HYPERION"))
, _hwLedCount()
, _ledGridSize(hyperion::getLedLayoutGridSize(getSetting(settings::LEDS).array()))
, _BGEffectHandler(nullptr)
,_captureCont(nullptr)
, _ledBuffer(_ledString.leds().size(), ColorRgb::BLACK)
, _boblightServer(nullptr)
, _readOnlyMode(readonlyMode)
{
@ -78,9 +83,9 @@ void Hyperion::start()
}
// 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())
{
_ledStringColorOrder.push_back(led.colorOrder);
@ -97,12 +102,14 @@ void Hyperion::start()
// listen for settings updates of this instance (LEDS & COLOR)
connect(_settingsManager, &SettingsManager::settingsChanged, this, &Hyperion::handleSettingsUpdate);
#if 0
// set color correction activity state
const QJsonObject color = getSetting(settings::COLOR).object();
#endif
// initialize leddevices
// initialize LED-devices
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);
connect(this, &Hyperion::compStateChangeRequest, _ledDeviceWrapper, &LedDeviceWrapper::handleComponentState);
@ -115,7 +122,9 @@ void Hyperion::start()
// create the message forwarder only on main instance
if (_instIndex == 0)
{
_messageForwarder = new MessageForwarder(this);
}
// create the effect engine; needs to be initialized after smoothing!
_effectEngine = new EffectEngine(this);
@ -136,14 +145,14 @@ void Hyperion::start()
connect(GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor, this, &Hyperion::setColor);
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();
// boblight, can't live in global scope as it depends on layout
_boblightServer = new BoblightServer(this, getSetting(settings::BOBLSERVER));
connect(this, &Hyperion::settingsChanged, _boblightServer, &BoblightServer::handleSettingsUpdate);
// instance inited, enter thread event loop
// instance initiated, enter thread event loop
emit started();
}
@ -178,7 +187,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
const QJsonObject obj = config.object();
// change in color recreate ledAdjustments
delete _raw2ledAdjustment;
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(_ledString.leds().size(), obj);
_raw2ledAdjustment = hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), obj);
if (!_raw2ledAdjustment->verifyAdjustments())
{
@ -189,13 +198,13 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
{
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();
// 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()));
_imageProcessor->setLedString(_ledString);
_muxer.updateLedColorsLength(_ledString.leds().size());
_muxer.updateLedColorsLength(static_cast<int>(_ledString.leds().size()));
_ledGridSize = hyperion::getLedLayoutGridSize(leds);
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
_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
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
_effectEngine->startCachedEffects();
@ -222,7 +231,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
QJsonObject dev = config.object();
// 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
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
dev["currentLedCount"] = int(_hwLedCount); // Inject led count info
dev["currentLedCount"] = _hwLedCount; // Inject led count info
_ledDeviceWrapper->createLedDevice(dev);
// 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);
}
unsigned Hyperion::getLedCount() const
int Hyperion::getLedCount() const
{
return _ledString.leds().size();
return static_cast<int>(_ledString.leds().size());
}
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
if(clearEffect)
{
_effectEngine->channelCleared(priority);
}
// if this priority is visible, update immediately
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
if(clearEffect)
{
_effectEngine->channelCleared(priority);
}
// if this priority is visible, update immediately
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
if (clearEffects)
{
_effectEngine->channelCleared(priority);
}
// create full led vector from single/multiple colors
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);
if (newLedColors.size() == size)
{
goto end;
}
}
}
end:
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
{
clear(priority);
}
// register color
registerInput(priority, hyperion::COMP_COLOR, origin);
@ -414,13 +433,14 @@ void Hyperion::adjustmentsUpdated()
bool Hyperion::clear(int priority, bool forceClearAll)
{
bool isCleared = false;
if (priority < 0)
{
_muxer.clearAll(forceClearAll);
// send clearall signal to the effect engine
_effectEngine->allChannelsCleared();
return true;
isCleared = true;
}
else
{
@ -429,9 +449,11 @@ bool Hyperion::clear(int priority, bool forceClearAll)
_effectEngine->channelCleared(priority);
if (_muxer.clearInput(priority))
return true;
{
isCleared = true;
}
return false;
}
return isCleared;
}
int Hyperion::getCurrentPriority() const
@ -532,9 +554,9 @@ void Hyperion::handleVisibleComponentChanged(hyperion::Components comp)
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)
{
Debug(_log,"No source left -> switch LED-Device off");
@ -604,8 +626,8 @@ void Hyperion::update()
i++;
}
// fill additional hw leds with black
if ( _hwLedCount > _ledBuffer.size() )
// fill additional hardware LEDs with black
if ( _hwLedCount > static_cast<int>(_ledBuffer.size()) )
{
_ledBuffer.resize(_hwLedCount, ColorRgb::BLACK);
}
@ -623,16 +645,18 @@ void Hyperion::update()
{
_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())
{
_deviceSmooth->updateLedValues(_ledBuffer);
}
}
}
//else
//{
// /LEDDevice is disabled
// Debug(_log, "LEDDevice is disabled - no update required");
//}
#if 0
else
{
//LEDDevice is disabled
Debug(_log, "LEDDevice is disabled - no update required");
}
#endif
}

View File

@ -5,16 +5,6 @@
// hyperion includes
#include <hyperion/LedString.h>
LedString::LedString()
{
// empty
}
LedString::~LedString()
{
// empty
}
std::vector<Led>& LedString::leds()
{
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].
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
@ -43,15 +43,16 @@ const char* SETTINGS_KEY_DECAY = "decay";
using namespace hyperion;
const int64_t DEFAUL_SETTLINGTIME = 200; // settlingtime in ms
const double DEFAUL_UPDATEFREQUENCY = 25; // updatefrequncy in hz
const int64_t DEFAUL_UPDATEINTERVALL = static_cast<int64_t>(1000 / DEFAUL_UPDATEFREQUENCY); // updateintervall in ms
const int DEFAUL_UPDATEFREQUENCY = 25; // updatefrequncy in hz
constexpr std::chrono::milliseconds DEFAUL_UPDATEINTERVALL{1000/ DEFAUL_UPDATEFREQUENCY};
const unsigned DEFAUL_OUTPUTDEPLAY = 0; // outputdelay in ms
LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion *hyperion)
: QObject(hyperion)
, _log(Logger::getInstance("SMOOTHING"))
, _hyperion(hyperion)
, _updateInterval(DEFAUL_UPDATEINTERVALL)
, _updateInterval(DEFAUL_UPDATEINTERVALL.count())
, _settlingTime(DEFAUL_SETTLINGTIME)
, _timer(new QTimer(this))
, _outputDelay(DEFAUL_OUTPUTDEPLAY)
@ -61,7 +62,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
, _pause(false)
, _currentConfigId(0)
, _enabled(false)
, tempValues(std::vector<uint64_t>(0, 0l))
, tempValues(std::vector<uint64_t>(0, 0L))
{
// init cfg 0 (default)
addConfig(DEFAUL_SETTLINGTIME, DEFAUL_UPDATEFREQUENCY, DEFAUL_OUTPUTDEPLAY);
@ -69,7 +70,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
selectConfig(0, true);
// 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);
// listen for comp changes
@ -77,7 +78,7 @@ LinearColorSmoothing::LinearColorSmoothing(const QJsonDocument &config, Hyperion
// timer
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)
@ -89,7 +90,9 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson
QJsonObject obj = config.object();
if (enabled() != obj["enable"].toBool(true))
{
setEnable(obj["enable"].toBool(true));
}
_continuousOutput = obj["continuousOutput"].toBool(true);
@ -105,7 +108,7 @@ void LinearColorSmoothing::handleSettingsUpdate(settings::type type, const QJson
cfg.pause = false;
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.interpolationRate = obj[SETTINGS_KEY_INTERPOLATION_RATE].toDouble(DEFAUL_UPDATEFREQUENCY);
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;
if (!_enabled)
{
return -1;
retval = -1;
}
else
{
@ -173,13 +176,13 @@ void LinearColorSmoothing::intitializeComponentVectors(const size_t ledCount)
const size_t len = 3 * ledCount;
meanValues = std::vector<floatT>(len, 0.0f);
residualErrors = std::vector<floatT>(len, 0.0f);
tempValues = std::vector<uint64_t>(len, 0l);
meanValues = std::vector<floatT>(len, 0.0F);
residualErrors = std::vector<floatT>(len, 0.0F);
tempValues = std::vector<uint64_t>(len, 0L);
}
// Zero the temp vector
std::fill(tempValues.begin(), tempValues.end(), 0l);
std::fill(tempValues.begin(), tempValues.end(), 0L);
}
void LinearColorSmoothing::writeDirect()
@ -232,9 +235,9 @@ void LinearColorSmoothing::assembleAndDitherFrame()
// Update the colors
ColorRgb &prev = _previousValues[i];
prev.red = (uint8_t)ir;
prev.green = (uint8_t)ig;
prev.blue = (uint8_t)ib;
prev.red = static_cast<uint8_t>(ir);
prev.green = static_cast<uint8_t>(ig);
prev.blue = static_cast<uint8_t>(ib);
// Determine the component errors
residualErrors[3 * i + 0] = fr - ir;
@ -262,15 +265,15 @@ void LinearColorSmoothing::assembleFrame()
// Update the colors
ColorRgb &prev = _previousValues[i];
prev.red = (uint8_t)ir;
prev.green = (uint8_t)ig;
prev.blue = (uint8_t)ib;
prev.red = static_cast<uint8_t>(ir);
prev.green = static_cast<uint8_t>(ig);
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) {
// 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();
@ -309,7 +312,7 @@ void LinearColorSmoothing::interpolateFrame()
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
floatT fs = 0.0f;
floatT fs = 0.0F;
// 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)
@ -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
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)
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)) {
const int64_t nextActionExpected = std::min(interpolationTarget, writeTarget);
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_RES_MICROS = 100l; // Expected resolution is >= 100µs on stock linux
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
if(microsTillNextAction > SLEEP_RES_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
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
, (1.0f * (_renderedCounter - _renderedStatCounter) / ((now - _renderedStatTime) / 1000000.0f))
, (1.0F * (_renderedCounter - _renderedStatCounter) / ((now - _renderedStatTime) / 1000000.0F))
, _interpolationCounter - _interpolationStatCounter
, (1.0f * (_interpolationCounter - _interpolationStatCounter) / ((now - _renderedStatTime) / 1000000.0f))
, (now - _renderedStatTime) / 1000.0f
, (1.0F * (_interpolationCounter - _interpolationStatCounter) / ((now - _renderedStatTime) / 1000000.0F))
, (now - _renderedStatTime) / 1000.0F
);
_renderedStatTime = now;
_renderedStatCounter = _renderedCounter;
@ -413,7 +416,7 @@ void LinearColorSmoothing::performDecay(const int64_t now) {
void LinearColorSmoothing::performLinear(const int64_t 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();
for (size_t i = 0; i < N; ++i)
@ -461,7 +464,7 @@ void LinearColorSmoothing::updateLeds()
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();
@ -478,7 +481,7 @@ void LinearColorSmoothing::rememberFrame(const std::vector<ColorRgb> &ledColors)
if (p > 0)
{
//Info(_log, "rememberFrame - erasing %d frames", p);
//Debug(_log, "rememberFrame - erasing %d frames", 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);
_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
if (_writeToLedsEnable)
{
_outputQueue.push_back(ledColors);
}
// 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)
{
@ -581,7 +586,7 @@ unsigned LinearColorSmoothing::addConfig(int settlingTime_ms, double ledUpdateFr
SmoothingType::Linear,
false,
settlingTime_ms,
int64_t(1000.0 / ledUpdateFrequency_hz),
static_cast<int>(1000.0 / ledUpdateFrequency_hz),
ledUpdateFrequency_hz,
ledUpdateFrequency_hz,
updateDelay,
@ -603,7 +608,7 @@ unsigned LinearColorSmoothing::updateConfig(unsigned cfgID, int settlingTime_ms,
SmoothingType::Linear,
false,
settlingTime_ms,
int64_t(1000.0 / ledUpdateFrequency_hz),
static_cast<int>(1000.0 / ledUpdateFrequency_hz),
ledUpdateFrequency_hz,
ledUpdateFrequency_hz,
updateDelay,
@ -630,7 +635,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool 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;
_settlingTime = _cfgList[cfg].settlingTime;
@ -642,14 +647,14 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
_interpolationIntervalMicros = int64_t(1000000.0 / _interpolationRate);
_dithering = _cfgList[cfg].dithering;
_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
const float decay = _decay;
const floatT inv_window = _invWindow;
// 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
_weightFrame = [inv_window,decay](const int64_t fs, const int64_t fe, const int64_t ws) {
const floatT s = (fs - ws) * inv_window;
@ -660,7 +665,7 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, bool force)
} else {
// For decay == 1 use linear interpolation of the moving average values
// 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
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 );
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;
}

View File

@ -7,7 +7,7 @@
// Qt includes
#include <QVector>
// hyperion incluse
// hyperion includes
#include <leddevice/LedDevice.h>
#include <utils/Components.h>
@ -30,7 +30,7 @@ enum SmoothingType {
Decay,
};
/// Linear Smooting class
/// Linear Smoothing class
///
/// 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.
@ -94,12 +94,12 @@ public:
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 ledUpdateFrequency_hz The frequency of update
/// @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);
@ -112,12 +112,12 @@ public:
/// @param ledUpdateFrequency_hz The frequency of update
/// @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);
///
/// @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 force Overwrite in any case the current values (used for cfg 0 settings update)
///
@ -128,7 +128,7 @@ public:
public slots:
///
/// @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
///
void handleSettingsUpdate(settings::type type, const QJsonDocument &config);
@ -167,7 +167,7 @@ private:
Hyperion *_hyperion;
/// 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)
int64_t _settlingTime;
@ -243,7 +243,7 @@ private:
/// The interval time in microseconds for interpolation of LED Frames.
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;
/// 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.
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.
int64_t updateInterval;
/// The interval time in milliseconds of the timer used for scheduling LED update operations. A value of 0 indicates sub-millisecond timing.
int updateInterval;
// The rate at which color frames should be written to LED device.
double outputRate;
@ -275,13 +275,13 @@ private:
/// The number of frames the output is delayed
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;
/// The decay power > 0. A value of exactly 1 is linear decay, higher numbers indicate a faster decay rate.
double decay;
};
/// smooth config list
/// smooth configuration list
QVector<SMOOTHING_CFG> _cfgList;
unsigned _currentConfigId;
@ -329,7 +329,7 @@ private:
/// Prepares a frame of LED colors by interpolating using the current smoothing window
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
/// by applying the weighting-function to the color components of each frame.

View File

@ -2,7 +2,7 @@
#include <utils/Logger.h>
#include <hyperion/MultiColorAdjustment.h>
MultiColorAdjustment::MultiColorAdjustment(unsigned ledCnt)
MultiColorAdjustment::MultiColorAdjustment(int ledCnt)
: _ledAdjustments(ledCnt, nullptr)
, _log(Logger::getInstance("ADJUSTMENT"))
{
@ -25,7 +25,7 @@ void MultiColorAdjustment::addAdjustment(ColorAdjustment * 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
if(startLed > endLed)
@ -34,19 +34,19 @@ void MultiColorAdjustment::setAdjustmentForLed(const QString& id, unsigned start
return;
}
// 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");
endLed = _ledAdjustments.size()-1;
Warning(_log,"The color calibration 'LED index' field has LEDs specified which aren't part of your led layout");
endLed = static_cast<int>(_ledAdjustments.size()-1);
}
// Get the identified adjustment (don't care if is nullptr)
ColorAdjustment * adjustment = getAdjustment(id);
//Debug(_log,"ColorAdjustment Profile [%s], startLed[%u], endLed[%u]", QSTRING_CSTR(id), startLed, endLed);
for (unsigned iLed=startLed; iLed<=endLed; ++iLed)
//Debug(_log,"ColorAdjustment Profile [%s], startLed[%d], endLed[%d]", QSTRING_CSTR(id), startLed, endLed);
for (int iLed=startLed; iLed<=endLed; ++iLed)
{
//Debug(_log,"_ledAdjustments [%u] -> [%p]", iLed, adjustment);
//Debug(_log,"_ledAdjustments [%d] -> [%p]", iLed, adjustment);
_ledAdjustments[iLed] = adjustment;
}
}

View File

@ -84,7 +84,7 @@ bool PriorityMuxer::setSourceAutoSelectEnabled(bool enable, bool update)
return false;
}
bool PriorityMuxer::setPriority(uint8_t priority)
bool PriorityMuxer::setPriority(int 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)
{
// detect new registers
bool newInput = false, reusedInput = false;
bool newInput = false;
bool reusedInput = false;
if (!_activeInputs.contains(priority))
newInput = true;
else if(_prevVisComp == component || _activeInputs[priority].componentId == component)
@ -165,7 +166,9 @@ void PriorityMuxer::registerInput(int priority, hyperion::Components component,
}
if (reusedInput)
{
emit timeRunner();
}
}
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");
if (_currentPriority < priority)
{
emit prioritiesChanged();
}
setCurrentTime();
}
@ -218,7 +223,7 @@ bool PriorityMuxer::setInputImage(int priority, const Image<ColorRgb>& image, in
return false;
}
// calc final timeout
// calculate final timeout
if(timeout_ms > 0)
timeout_ms = QDateTime::currentMSecsSinceEpoch() + timeout_ms;
@ -252,13 +257,13 @@ bool PriorityMuxer::setInputImage(int priority, const Image<ColorRgb>& image, in
return true;
}
bool PriorityMuxer::setInputInactive(quint8 priority)
bool PriorityMuxer::setInputInactive(int priority)
{
Image<ColorRgb> image;
return setInputImage(priority, image, -100);
}
bool PriorityMuxer::clearInput(uint8_t priority)
bool PriorityMuxer::clearInput(int priority)
{
if (priority < PriorityMuxer::LOWEST_PRIORITY && _activeInputs.remove(priority))
{
@ -288,9 +293,11 @@ void PriorityMuxer::clearAll(bool forceClearAll)
{
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)
{
clearInput(key);
}
}
}
}
void PriorityMuxer::setCurrentTime()
@ -303,7 +310,7 @@ void PriorityMuxer::setCurrentTime()
{
if (infoIt->timeoutTime_ms > 0 && infoIt->timeoutTime_ms <= now)
{
quint8 tPrio = infoIt->priority;
int tPrio = infoIt->priority;
infoIt = _activeInputs.erase(infoIt);
Debug(_log,"Timeout clear for priority %d",tPrio);
emit prioritiesChanged();
@ -321,7 +328,7 @@ void PriorityMuxer::setCurrentTime()
++infoIt;
}
}
// eval if manual selected prio is still available
// evaluate, if manual selected priority is still available
if(!_sourceAutoSelectEnabled)
{
if(_activeInputs.contains(_manualSelectedPriority))

View File

@ -11,6 +11,7 @@
"options":
{
"enum_titles": ["edt_conf_enum_automatic","AMLogic","DispmanX","DirectX9","Framebuffer","OSX","QT","X11","XCB"]
},
"default" : "auto",
"propertyOrder" : 1

View File

@ -8,22 +8,22 @@
"top": {
"type": "integer",
"minimum": 0,
"default": 8
"default": 1
},
"bottom": {
"type": "integer",
"minimum": 0,
"default": 8
"default": 0
},
"left": {
"type": "integer",
"minimum": 0,
"default": 5
"default": 0
},
"right": {
"type": "integer",
"minimum": 0,
"default": 5
"default": 0
},
"glength": {
"type": "integer",

View File

@ -47,7 +47,7 @@
"title" : "edt_conf_smooth_interpolationRate_title",
"minimum" : 1.0,
"maximum": 1000.0,
"default" : 0,
"default" : 1.0,
"append" : "edt_append_hz",
"propertyOrder" : 5
},
@ -57,7 +57,7 @@
"title" : "edt_conf_smooth_outputRate_title",
"minimum" : 1.0,
"maximum": 1000.0,
"default" : 0,
"default" : 1.0,
"append" : "edt_append_hz",
"propertyOrder" : 6
},

View File

@ -149,7 +149,7 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
_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 ) );
setRewriteTime ( deviceConfig["rewriteTime"].toInt( _refreshTimerInterval_ms) );
@ -178,11 +178,11 @@ int LedDevice::updateLeds(const std::vector<ColorRgb>& ledValues)
if ( !_isEnabled || !_isOn || !_isDeviceReady || _isDeviceInError )
{
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready! ";
return -1;
retval = -1;
}
else
{
qint64 elapsedTimeMs = _lastWriteTime.msecsTo(QDateTime::currentDateTime());
qint64 elapsedTimeMs = _lastWriteTime.msecsTo( QDateTime::currentDateTime() );
if (_latchTime_ms == 0 || elapsedTimeMs >= _latchTime_ms)
{
//std::cout << "LedDevice::updateLeds(), Elapsed time since last write (" << elapsedTimeMs << ") ms > _latchTime_ms (" << _latchTime_ms << ") ms" << std::endl;
@ -356,7 +356,7 @@ bool LedDevice::restoreState()
return rc;
}
QJsonObject LedDevice::discover()
QJsonObject LedDevice::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
@ -392,8 +392,9 @@ QJsonObject LedDevice::getProperties(const QJsonObject& params)
return properties;
}
void LedDevice::setLedCount(unsigned int ledCount)
void LedDevice::setLedCount(int ledCount)
{
assert(ledCount >= 0);
_ledCount = ledCount;
_ledRGBCount = _ledCount * sizeof(ColorRgb);
_ledRGBWCount = _ledCount * sizeof(ColorRgbw);
@ -401,12 +402,14 @@ void LedDevice::setLedCount(unsigned int ledCount)
void LedDevice::setLatchTime( int latchTime_ms )
{
assert(latchTime_ms >= 0);
_latchTime_ms = latchTime_ms;
Debug(_log, "LatchTime updated to %dms", _latchTime_ms);
}
void LedDevice::setRewriteTime( int rewriteTime_ms )
{
assert(rewriteTime_ms >= 0);
_refreshTimerInterval_ms = rewriteTime_ms;
if ( _refreshTimerInterval_ms > 0 )
@ -441,7 +444,7 @@ void LedDevice::printLedValues(const std::vector<ColorRgb>& ledValues)
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)
{

View File

@ -36,16 +36,17 @@ LedDevice * LedDeviceFactory::construct(const QJsonObject & deviceConfig)
if (device == nullptr)
{
Error(log, "Dummy device used, because configured device '%s' is unknown", QSTRING_CSTR(type) );
throw std::runtime_error("unknown device");
}
}
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());
const QJsonObject dummyDeviceConfig;
device = LedDeviceFile::construct(QJsonObject());
QJsonObject dummyDeviceConfig;
dummyDeviceConfig.insert("type",dummyDeviceType);
device = LedDeviceFile::construct(dummyDeviceConfig);
}
return device;

View File

@ -1,7 +1,6 @@
#include "LedDeviceTemplate.h"
LedDeviceTemplate::LedDeviceTemplate(const QJsonObject &deviceConfig)
: LedDevice()
LedDeviceTemplate::LedDeviceTemplate(const QJsonObject & /*deviceConfig*/)
{
}
@ -19,7 +18,7 @@ bool LedDeviceTemplate::init(const QJsonObject &deviceConfig)
{
// Initialise LedDevice configuration and execution environment
// ...
if ( 0 /*Error during init*/)
if ( false /*Error during init*/)
{
//Build an errortext, illustrative
QString errortext = QString ("Error message: %1").arg("errno/text");
@ -56,7 +55,7 @@ int LedDeviceTemplate::open()
}
// On error/exceptions, set LedDevice in error
if ( retval < 0 )
if ( false /* retval < 0*/ )
{
this->setInError( errortext );
}

View File

@ -146,8 +146,8 @@ QString LedDeviceWrapper::getColorOrder() const
unsigned int LedDeviceWrapper::getLedCount() const
{
unsigned int value = 0;
QMetaObject::invokeMethod(_ledDevice, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(unsigned int, value));
int value = 0;
QMetaObject::invokeMethod(_ledDevice, "getLedCount", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, value));
return value;
}

View File

@ -190,7 +190,7 @@ void ProviderHID::unblockAfterDelay()
_blockedForDelay = false;
}
QJsonObject ProviderHID::discover()
QJsonObject ProviderHID::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );

View File

@ -31,9 +31,11 @@ public:
///
/// @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
///
QJsonObject discover() override;
QJsonObject discover(const QJsonObject& params) override;
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);
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, "RefreshTime : %d", _refreshTimerInterval_ms);
Debug(_log, "LatchTime : %d", this->getLatchTime());
@ -89,8 +89,8 @@ bool LedDeviceAtmoOrb::init(const QJsonObject &deviceConfig)
}
}
uint numberOrbs = _orbIds.size();
uint configuredLedCount = this->getLedCount();
int numberOrbs = _orbIds.size();
int configuredLedCount = this->getLedCount();
if ( _orbIds.empty() )
{
@ -111,7 +111,7 @@ bool LedDeviceAtmoOrb::init(const QJsonObject &deviceConfig)
{
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;
@ -276,16 +276,21 @@ void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes)
_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;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
QJsonArray deviceList;
_multicastGroup = params["multiCastGroup"].toString(MULTICAST_GROUP_DEFAULT_ADDRESS);
_multiCastGroupPort = static_cast<quint16>(params["multiCastPort"].toInt(MULTICAST_GROUP_DEFAULT_PORT));
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);
if ( _udpSocket->waitForReadyRead(DEFAULT_DISCOVERY_TIMEOUT.count()) )

View File

@ -43,9 +43,11 @@ public:
///
/// @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
///
virtual QJsonObject discover() override;
QJsonObject discover(const QJsonObject& params) override;
///
/// @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_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
LedDeviceCololight::LedDeviceCololight(const QJsonObject& deviceConfig)
@ -174,7 +113,7 @@ bool LedDeviceCololight::initLedsConfiguration()
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))
@ -187,7 +126,7 @@ bool LedDeviceCololight::initLedsConfiguration()
{
Debug(_log, "LedCount : %d", getLedCount());
uint configuredLedCount = static_cast<uint>(_devConfig["currentLedCount"].toInt(1));
int configuredLedCount = _devConfig["currentLedCount"].toInt(1);
if (getLedCount() < configuredLedCount)
{
@ -200,7 +139,7 @@ bool LedDeviceCololight::initLedsConfiguration()
{
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;
}
@ -269,7 +208,7 @@ bool LedDeviceCololight::getInfo()
{
_modelType = MODLUE_LAYOUT;
_distance = ledNum / COLOLIGHT_BEADS_PER_MODULE;
setLedCount(static_cast<uint>(_distance));
setLedCount(_distance);
}
}
else
@ -455,7 +394,7 @@ bool LedDeviceCololight::sendRequest(const appID appID, const QByteArray& comman
packet.append(static_cast<char>(_sequenceNumber));
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);
@ -606,7 +545,7 @@ bool LedDeviceCololight::powerOff()
return off;
}
QJsonObject LedDeviceCololight::discover()
QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType);

View File

@ -29,6 +29,68 @@ enum effect : uint32_t {
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
///
@ -54,9 +116,11 @@ public:
///
/// @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
///
QJsonObject discover() override;
QJsonObject discover(const QJsonObject& params) override;
///
/// @brief Get a Cololight device's resource properties

View File

@ -1,5 +1,9 @@
#include "LedDeviceFadeCandy.h"
#include <QtEndian>
#include <chrono>
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types#ssize-t
#if defined(_MSC_VER)
#include <BaseTsd.h>
@ -8,22 +12,22 @@ typedef SSIZE_T ssize_t;
// Constants
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 unsigned OPC_SET_PIXELS = 0; // OPC command codes
const unsigned OPC_SYS_EX = 255; // OPC command codes
const unsigned OPC_HEADER_SIZE = 4; // OPC header size
const int MAX_NUM_LEDS = 10000; // OPC can handle 21845 LEDs - in theory, fadecandy device should handle 10000 LEDs
const int OPC_SET_PIXELS = 0; // OPC command codes
const int OPC_SYS_EX = 255; // OPC command codes
const int OPC_HEADER_SIZE = 4; // OPC header size
} //End of constants
// 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)
, _client(nullptr)
,_host()
,_port(STREAM_DEFAULT_PORT)
, _host()
, _port(STREAM_DEFAULT_PORT)
{
}
@ -32,20 +36,20 @@ LedDeviceFadeCandy::~LedDeviceFadeCandy()
delete _client;
}
LedDevice* LedDeviceFadeCandy::construct(const QJsonObject &deviceConfig)
LedDevice* LedDeviceFadeCandy::construct(const QJsonObject& deviceConfig)
{
return new LedDeviceFadeCandy(deviceConfig);
}
bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
bool LedDeviceFadeCandy::init(const QJsonObject& deviceConfig)
{
bool isInitOK = false;
if ( LedDevice::init(deviceConfig) )
if (LedDevice::init(deviceConfig))
{
if (getLedCount() > MAX_NUM_LEDS)
{
QString errortext = QString ("More LED configured than allowed (%1)").arg(MAX_NUM_LEDS);
QString errortext = QString("More LED configured than allowed (%1)").arg(MAX_NUM_LEDS);
this->setInError(errortext);
isInitOK = false;
}
@ -55,7 +59,7 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
_port = deviceConfig["port"].toInt(STREAM_DEFAULT_PORT);
//If host not configured the init fails
if ( _host.isEmpty() )
if (_host.isEmpty())
{
this->setInError("No target hostname nor IP defined");
}
@ -63,8 +67,8 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
{
_channel = deviceConfig["channel"].toInt(0);
_gamma = deviceConfig["gamma"].toDouble(1.0);
_noDither = ! deviceConfig["dither"].toBool(false);
_noInterp = ! deviceConfig["interpolation"].toBool(false);
_noDither = !deviceConfig["dither"].toBool(false);
_noInterp = !deviceConfig["interpolation"].toBool(false);
_manualLED = deviceConfig["manualLed"].toBool(false);
_ledOnOff = deviceConfig["ledOn"].toBool(false);
_setFcConfig = deviceConfig["setFcConfig"].toBool(false);
@ -74,20 +78,19 @@ bool LedDeviceFadeCandy::init(const QJsonObject &deviceConfig)
_whitePoint_b = 1.0;
const QJsonArray whitePointConfig = deviceConfig["whitePoint"].toArray();
if ( !whitePointConfig.isEmpty() && whitePointConfig.size() == 3 )
if (!whitePointConfig.isEmpty() && whitePointConfig.size() == 3)
{
_whitePoint_r = whitePointConfig[0].toDouble() / 255.0;
_whitePoint_g = whitePointConfig[1].toDouble() / 255.0;
_whitePoint_b = whitePointConfig[2].toDouble() / 255.0;
}
_opc_data.resize( _ledRGBCount + OPC_HEADER_SIZE );
_opc_data[0] = _channel;
_opc_data.resize(static_cast<int>(_ledRGBCount) + OPC_HEADER_SIZE);
_opc_data[0] = static_cast<char>(_channel);
_opc_data[1] = OPC_SET_PIXELS;
_opc_data[2] = _ledRGBCount >> 8;
_opc_data[3] = _ledRGBCount & 0xff;
qToBigEndian<quint16>(static_cast<quint16>(_ledRGBCount), _opc_data.data() + 2);
if ( initNetwork() )
if (initNetwork())
{
isInitOK = true;
}
@ -101,7 +104,7 @@ bool LedDeviceFadeCandy::initNetwork()
{
bool isInitOK = false;
if ( _client == nullptr )
if (_client == nullptr)
{
_client = new QTcpSocket(this);
isInitOK = true;
@ -116,10 +119,10 @@ int LedDeviceFadeCandy::open()
_isDeviceReady = false;
// Try to open the LedDevice
if ( !tryConnect() )
if (!tryConnect())
{
errortext = QString ("Failed to open device.");
this->setInError( errortext );
errortext = QString("Failed to open device.");
this->setInError(errortext);
}
else
{
@ -136,7 +139,7 @@ int LedDeviceFadeCandy::close()
_isDeviceReady = false;
// LedDevice specific closing activities
if ( _client != nullptr )
if (_client != nullptr)
{
_client->close();
// Everything is OK -> device is closed
@ -147,7 +150,7 @@ int LedDeviceFadeCandy::close()
bool LedDeviceFadeCandy::isConnected() const
{
bool connected = false;
if ( _client != nullptr )
if (_client != nullptr)
{
connected = _client->state() == QAbstractSocket::ConnectedState;
}
@ -156,13 +159,13 @@ bool LedDeviceFadeCandy::isConnected() const
bool LedDeviceFadeCandy::tryConnect()
{
if ( _client != nullptr )
if (_client != nullptr)
{
if ( _client->state() == QAbstractSocket::UnconnectedState ) {
_client->connectToHost( _host, _port);
if ( _client->waitForConnected(1000) )
if (_client->state() == QAbstractSocket::UnconnectedState) {
_client->connectToHost(_host, static_cast<quint16>(_port));
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)
{
sendFadeCandyConfiguration();
@ -173,50 +176,48 @@ bool LedDeviceFadeCandy::tryConnect()
return isConnected();
}
int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
int LedDeviceFadeCandy::write(const std::vector<ColorRgb>& ledValues)
{
uint idx = OPC_HEADER_SIZE;
for (const ColorRgb& color : ledValues)
{
_opc_data[idx ] = unsigned( color.red );
_opc_data[idx+1] = unsigned( color.green );
_opc_data[idx+2] = unsigned( color.blue );
_opc_data[idx] = static_cast<char>(color.red);
_opc_data[idx + 1] = static_cast<char>(color.green);
_opc_data[idx + 2] = static_cast<char>(color.blue);
idx += 3;
}
int retval = transferData()<0 ? -1 : 0;
int retval = transferData() < 0 ? -1 : 0;
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;
}
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;
uint data_size = msg.size() + 4;
sysExData.resize( 4 + OPC_HEADER_SIZE );
int data_size = msg.size() + 4;
sysExData.resize(4 + OPC_HEADER_SIZE);
sysExData[0] = 0;
sysExData[1] = OPC_SYS_EX;
sysExData[2] = data_size >>8;
sysExData[3] = data_size &0xff;
sysExData[4] = systemId >>8;
sysExData[5] = systemId &0xff;
sysExData[6] = commandId >>8;
sysExData[7] = commandId &0xff;
sysExData[1] = static_cast<char>(OPC_SYS_EX);
qToBigEndian<quint16>(static_cast<quint16>(data_size), sysExData.data() + 2);
qToBigEndian<quint16>(static_cast<quint16>(systemId), sysExData.data() + 4);
qToBigEndian<quint16>(static_cast<quint16>(commandId), sysExData.data() + 6);
sysExData += msg;
return _client->write( sysExData, sysExData.size() );
return _client->write(sysExData, sysExData.size());
}
return -1;
}
@ -224,9 +225,9 @@ int LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, const QBy
void LedDeviceFadeCandy::sendFadeCandyConfiguration()
{
Debug(_log, "send configuration to fadecandy");
QString data = "{\"gamma\": "+QString::number(_gamma,'g',4)+", \"whitepoint\": ["+QString::number(_whitePoint_r,'g',4)+", "+QString::number(_whitePoint_g,'g',4)+", "+QString::number(_whitePoint_b,'g',4)+"]}";
sendSysEx(1, 1, data.toLocal8Bit() );
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());
char firmware_data = ((uint8_t)_noDither | ((uint8_t)_noInterp << 1) | ((uint8_t)_manualLED << 2) | ((uint8_t)_ledOnOff << 3) );
sendSysEx(1, 2, QByteArray(1,firmware_data) );
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));
}

View File

@ -40,7 +40,7 @@ public:
///
/// @param deviceConfig Device's configuration as JSON-Object
///
explicit LedDeviceFadeCandy(const QJsonObject &deviceConfig);
explicit LedDeviceFadeCandy(const QJsonObject& deviceConfig);
///
/// @brief Destructor of the LedDevice
@ -52,7 +52,7 @@ public:
///
/// @param[in] deviceConfig Device's configuration as JSON-Object
/// @return LedDevice constructed
static LedDevice* construct(const QJsonObject &deviceConfig);
static LedDevice* construct(const QJsonObject& deviceConfig);
protected:
@ -62,7 +62,7 @@ protected:
/// @param[in] deviceConfig the JSON device configuration
/// @return True, if success
///
bool init(const QJsonObject &deviceConfig) override;
bool init(const QJsonObject& deviceConfig) override;
///
/// @brief Opens the output device.
@ -84,7 +84,7 @@ protected:
/// @param[in] ledValues The RGB-color per LED
/// @return Zero on success, else negative
///
int write(const std::vector<ColorRgb> & ledValues) override;
int write(const std::vector<ColorRgb>& ledValues) override;
private:
@ -113,7 +113,7 @@ private:
///
/// @return amount of transferred bytes. -1 error while transferring, -2 error while connecting
///
int transferData();
qint64 transferData();
///
/// @brief Send system exclusive commands
@ -122,7 +122,7 @@ private:
/// @param[in] commandId id of command
/// @param[in] msg the sysEx message
/// @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
@ -131,8 +131,8 @@ private:
QTcpSocket* _client;
QString _host;
uint16_t _port;
unsigned _channel;
int _port;
int _channel;
QByteArray _opc_data;
// fadecandy sysEx
@ -145,7 +145,6 @@ private:
bool _noInterp;
bool _manualLED;
bool _ledOnOff;
};
#endif // LEDEVICEFADECANDY_H

View File

@ -7,6 +7,7 @@
// Qt includes
#include <QEventLoop>
#include <QNetworkReply>
#include <QtEndian>
//std includes
#include <sstream>
@ -14,18 +15,17 @@
// Constants
namespace {
const bool verbose = false;
const bool verbose3 = false;
// Configuration settings
const char CONFIG_ADDRESS[] = "host";
//const char CONFIG_PORT[] = "port";
const char CONFIG_AUTH_TOKEN[] ="token";
const char CONFIG_AUTH_TOKEN[] = "token";
const char CONFIG_PANEL_ORDER_TOP_DOWN[] ="panelOrderTopDown";
const char CONFIG_PANEL_ORDER_LEFT_RIGHT[] ="panelOrderLeftRight";
const char CONFIG_PANEL_START_POS[] ="panelStartPos";
const char CONFIG_PANEL_ORDER_TOP_DOWN[] = "panelOrderTopDown";
const char CONFIG_PANEL_ORDER_LEFT_RIGHT[] = "panelOrderLeftRight";
const char CONFIG_PANEL_START_POS[] = "panelStartPos";
// Panel configuration settings
const char PANEL_LAYOUT[] = "layout";
@ -61,16 +61,19 @@ const char API_BASE_PATH[] = "/api/v1/%1/";
const char API_ROOT[] = "";
//const char API_EXT_MODE_STRING_V1[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\"}}";
const char API_EXT_MODE_STRING_V2[] = "{\"write\" : {\"command\" : \"display\", \"animType\" : \"extControl\", \"extControlVersion\" : \"v2\"}}";
const char API_STATE[] ="state";
const char API_STATE[] = "state";
const char API_PANELLAYOUT[] = "panelLayout";
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
const char SSDP_ID[] = "ssdp:all";
const char SSDP_FILTER_HEADER[] = "ST";
const char SSDP_CANVAS[] = "nanoleaf:nl29";
const char SSDP_LIGHTPANELS[] = "nanoleaf_aurora:light";
} //End of constants
// Nanoleaf Panel Shapetypes
@ -81,7 +84,7 @@ enum SHAPETYPES {
CONTROL_SQUARE_PRIMARY,
CONTROL_SQUARE_PASSIVE,
POWER_SUPPLY,
};
};
// Nanoleaf external control versions
enum EXTCONTROLVERSIONS {
@ -89,20 +92,20 @@ enum EXTCONTROLVERSIONS {
EXTCTRLVER_V2
};
LedDeviceNanoleaf::LedDeviceNanoleaf(const QJsonObject &deviceConfig)
LedDeviceNanoleaf::LedDeviceNanoleaf(const QJsonObject& deviceConfig)
: ProviderUdp(deviceConfig)
,_restApi(nullptr)
,_apiPort(API_DEFAULT_PORT)
,_topDown(true)
,_leftRight(true)
,_startPos(0)
,_endPos(0)
,_extControlVersion (EXTCTRLVER_V2),
, _restApi(nullptr)
, _apiPort(API_DEFAULT_PORT)
, _topDown(true)
, _leftRight(true)
, _startPos(0)
, _endPos(0)
, _extControlVersion(EXTCTRLVER_V2),
_panelLedCount(0)
{
}
LedDevice* LedDeviceNanoleaf::construct(const QJsonObject &deviceConfig)
LedDevice* LedDeviceNanoleaf::construct(const QJsonObject& deviceConfig)
{
return new LedDeviceNanoleaf(deviceConfig);
}
@ -113,7 +116,7 @@ LedDeviceNanoleaf::~LedDeviceNanoleaf()
_restApi = nullptr;
}
bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
bool LedDeviceNanoleaf::init(const QJsonObject& deviceConfig)
{
// Overwrite non supported/required features
setLatchTime(0);
@ -121,69 +124,69 @@ bool LedDeviceNanoleaf::init(const QJsonObject &deviceConfig)
if (deviceConfig["rewriteTime"].toInt(0) > 0)
{
Info (_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored.");
Info(_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored.");
}
DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData() );
DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData());
bool isInitOK = false;
if ( LedDevice::init(deviceConfig) )
if (LedDevice::init(deviceConfig))
{
uint configuredLedCount = this->getLedCount();
Debug(_log, "DeviceType : %s", QSTRING_CSTR( this->getActiveDeviceType() ));
Debug(_log, "LedCount : %u", configuredLedCount);
Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() ));
int configuredLedCount = this->getLedCount();
Debug(_log, "DeviceType : %s", QSTRING_CSTR(this->getActiveDeviceType()));
Debug(_log, "LedCount : %d", configuredLedCount);
Debug(_log, "ColorOrder : %s", QSTRING_CSTR(this->getColorOrder()));
Debug(_log, "RewriteTime : %d", this->getRewriteTime());
Debug(_log, "LatchTime : %d", this->getLatchTime());
// Read panel organisation configuration
if ( deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].isString() )
if (deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].isString())
{
_topDown = deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].toString().toInt() == 0;
_topDown = deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].toString().toInt() == 0;
}
else
{
_topDown = deviceConfig[ CONFIG_PANEL_ORDER_TOP_DOWN ].toInt() == 0;
_topDown = deviceConfig[CONFIG_PANEL_ORDER_TOP_DOWN].toInt() == 0;
}
if ( deviceConfig[ CONFIG_PANEL_ORDER_LEFT_RIGHT ].isString() )
if (deviceConfig[CONFIG_PANEL_ORDER_LEFT_RIGHT].isString())
{
_leftRight = deviceConfig[ CONFIG_PANEL_ORDER_LEFT_RIGHT ].toString().toInt() == 0;
_leftRight = deviceConfig[CONFIG_PANEL_ORDER_LEFT_RIGHT].toString().toInt() == 0;
}
else
{
_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
//Set hostname as per configuration and_defaultHost default port
_hostname = deviceConfig[ CONFIG_ADDRESS ].toString();
_hostname = deviceConfig[CONFIG_ADDRESS].toString();
_apiPort = API_DEFAULT_PORT;
_authToken = deviceConfig[ CONFIG_AUTH_TOKEN ].toString();
_authToken = deviceConfig[CONFIG_AUTH_TOKEN].toString();
//If host not configured the init failed
if ( _hostname.isEmpty() )
if (_hostname.isEmpty())
{
this->setInError("No target hostname nor IP defined");
isInitOK = false;
}
else
{
if ( initRestAPI( _hostname, _apiPort, _authToken ) )
if (initRestAPI(_hostname, _apiPort, _authToken))
{
// Read LedDevice configuration and validate against device configuration
if ( initLedsConfiguration() )
if (initLedsConfiguration())
{
// Set UDP streaming host and port
_devConfig["host"] = _hostname;
_devConfig["port"] = STREAM_CONTROL_DEFAULT_PORT;
isInitOK = ProviderUdp::init(_devConfig);
Debug(_log, "Hostname/IP : %s", QSTRING_CSTR( _hostname ));
Debug(_log, "Hostname/IP : %s", QSTRING_CSTR(_hostname));
Debug(_log, "Port : %d", _port);
}
}
@ -201,9 +204,9 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
// Read Panel count and panel Ids
_restApi->setPath(API_ROOT);
httpResponse response = _restApi->get();
if ( response.error() )
if (response.error())
{
this->setInError ( response.getErrorReason() );
this->setInError(response.getErrorReason());
isInitOK = false;
}
else
@ -215,35 +218,35 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
QString deviceManufacturer = jsonAllPanelInfo[DEV_DATA_MANUFACTURER].toString();
_deviceFirmwareVersion = jsonAllPanelInfo[DEV_DATA_FIRMWAREVERSION].toString();
Debug(_log, "Name : %s", QSTRING_CSTR( deviceName ));
Debug(_log, "Model : %s", QSTRING_CSTR( _deviceModel ));
Debug(_log, "Manufacturer : %s", QSTRING_CSTR( deviceManufacturer ));
Debug(_log, "FirmwareVersion: %s", QSTRING_CSTR( _deviceFirmwareVersion));
Debug(_log, "Name : %s", QSTRING_CSTR(deviceName));
Debug(_log, "Model : %s", QSTRING_CSTR(_deviceModel));
Debug(_log, "Manufacturer : %s", QSTRING_CSTR(deviceManufacturer));
Debug(_log, "FirmwareVersion: %s", QSTRING_CSTR(_deviceFirmwareVersion));
// Get panel details from /panelLayout/layout
QJsonObject jsonPanelLayout = jsonAllPanelInfo[API_PANELLAYOUT].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();
std::map<uint, std::map<uint, uint>> panelMap;
std::map<int, std::map<int, int>> panelMap;
// Loop over all children.
for (const QJsonValue value : positionData)
foreach(const QJsonValue & value, positionData)
{
QJsonObject panelObj = value.toObject();
uint panelId = static_cast<uint>(panelObj[PANEL_ID].toInt());
uint panelX = static_cast<uint>(panelObj[PANEL_POS_X].toInt());
uint panelY = static_cast<uint>(panelObj[PANEL_POS_Y].toInt());
uint panelshapeType = static_cast<uint>(panelObj[PANEL_SHAPE_TYPE].toInt());
//uint panelOrientation = static_cast<uint>(panelObj[PANEL_ORIENTATION].toInt());
int panelId = panelObj[PANEL_ID].toInt();
int panelX = panelObj[PANEL_POS_X].toInt();
int panelY = panelObj[PANEL_POS_Y].toInt();
int panelshapeType = panelObj[PANEL_SHAPE_TYPE].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
if ( panelshapeType != RHYTM )
if (panelshapeType != RHYTM)
{
panelMap[panelY][panelX] = panelId;
}
@ -254,16 +257,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
}
// Travers panels top down
for(auto posY = panelMap.crbegin(); posY != panelMap.crend(); ++posY)
for (auto posY = panelMap.crbegin(); posY != panelMap.crend(); ++posY)
{
// Sort panels left to right
if ( _leftRight )
if (_leftRight)
{
for( auto posX = posY->second.cbegin(); posX != posY->second.cend(); ++posX)
for (auto posX = posY->second.cbegin(); posX != posY->second.cend(); ++posX)
{
DebugIf(verbose3, _log, "panelMap[%u][%u]=%u", posY->first, posX->first, posX->second );
DebugIf(verbose3, _log, "panelMap[%d][%d]=%d", posY->first, posX->first, posX->second);
if ( _topDown )
if (_topDown)
{
_panelIds.push_back(posX->second);
}
@ -276,11 +279,11 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
else
{
// Sort panels right to left
for( auto posX = posY->second.crbegin(); posX != posY->second.crend(); ++posX)
for (auto posX = posY->second.crbegin(); posX != posY->second.crend(); ++posX)
{
DebugIf(verbose3, _log, "panelMap[%u][%u]=%u", posY->first, posX->first, posX->second );
DebugIf(verbose3, _log, "panelMap[%d][%d]=%d", posY->first, posX->first, posX->second);
if ( _topDown )
if (_topDown)
{
_panelIds.push_back(posX->second);
}
@ -292,22 +295,22 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
}
}
this->_panelLedCount = static_cast<uint>(_panelIds.size());
_devConfig["hardwareLedCount"] = static_cast<int>(_panelLedCount);
this->_panelLedCount = _panelIds.size();
_devConfig["hardwareLedCount"] = _panelLedCount;
Debug(_log, "PanelsNum : %u", panelNum);
Debug(_log, "PanelLedCount : %u", _panelLedCount);
Debug(_log, "PanelsNum : %d", panelNum);
Debug(_log, "PanelLedCount : %d", _panelLedCount);
// Check. if enough panels were found.
uint configuredLedCount = this->getLedCount();
int configuredLedCount = this->getLedCount();
_endPos = _startPos + configuredLedCount - 1;
Debug(_log, "Sort Top>Down : %d", _topDown);
Debug(_log, "Sort Left>Right: %d", _leftRight);
Debug(_log, "Start Panel Pos: %u", _startPos);
Debug(_log, "End Panel Pos : %u", _endPos);
Debug(_log, "Start Panel Pos: %d", _startPos);
Debug(_log, "End Panel Pos : %d", _endPos);
if (_panelLedCount < configuredLedCount )
if (_panelLedCount < configuredLedCount)
{
QString errorReason = QString("Not enough panels [%1] for configured LEDs [%2] found!")
.arg(_panelLedCount)
@ -317,16 +320,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
}
else
{
if ( _panelLedCount > this->getLedCount() )
if (_panelLedCount > this->getLedCount())
{
Info(_log, "%s: More panels [%u] than configured LEDs [%u].", QSTRING_CSTR(this->getActiveDeviceType()), _panelLedCount, configuredLedCount );
Info(_log, "%s: More panels [%d] than configured LEDs [%d].", QSTRING_CSTR(this->getActiveDeviceType()), _panelLedCount, configuredLedCount);
}
// Check, if start position + number of configured LEDs is greater than number of panels available
if ( _endPos >= _panelLedCount )
if (_endPos >= _panelLedCount)
{
QString errorReason = QString("Start panel [%1] out of range. Start panel position can be max [%2] given [%3] panel available!")
.arg(_startPos).arg(_panelLedCount-configuredLedCount).arg(_panelLedCount);
.arg(_startPos).arg(_panelLedCount - configuredLedCount).arg(_panelLedCount);
this->setInError(errorReason);
isInitOK = false;
@ -336,16 +339,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration()
return isInitOK;
}
bool LedDeviceNanoleaf::initRestAPI(const QString &hostname, int port, const QString &token )
bool LedDeviceNanoleaf::initRestAPI(const QString& hostname, int port, const QString& token)
{
bool isInitOK = false;
if ( _restApi == nullptr )
if (_restApi == nullptr)
{
_restApi = new ProviderRestApi(hostname, port );
_restApi = new ProviderRestApi(hostname, port);
//Base-path is api-path + authentication token
_restApi->setBasePath( QString(API_BASE_PATH).arg(token) );
_restApi->setBasePath(QString(API_BASE_PATH).arg(token));
isInitOK = true;
}
@ -360,13 +363,13 @@ int LedDeviceNanoleaf::open()
QJsonDocument responseDoc = changeToExternalControlMode();
// Resolve port for Light Panels
QJsonObject jsonStreamControllInfo = responseDoc.object();
if ( ! jsonStreamControllInfo.isEmpty() )
if (!jsonStreamControllInfo.isEmpty())
{
//Set default streaming port
_port = static_cast<uchar>(jsonStreamControllInfo[STREAM_CONTROL_PORT].toInt());
}
if ( ProviderUdp::open() == 0 )
if (ProviderUdp::open() == 0)
{
// Everything is OK, device is ready
_isDeviceReady = true;
@ -375,10 +378,10 @@ int LedDeviceNanoleaf::open()
return retval;
}
QJsonObject LedDeviceNanoleaf::discover()
QJsonObject LedDeviceNanoleaf::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );
devicesDiscovered.insert("ledDeviceType", _activeDeviceType);
QJsonArray deviceList;
@ -391,35 +394,35 @@ QJsonObject LedDeviceNanoleaf::discover()
discover.setSearchFilter(searchTargetFilter, SSDP_FILTER_HEADER);
QString searchTarget = SSDP_ID;
if ( discover.discoverServices(searchTarget) > 0 )
if (discover.discoverServices(searchTarget) > 0)
{
deviceList = discover.getServicesDiscoveredJson();
}
devicesDiscovered.insert("devices", deviceList);
Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() );
Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());
return devicesDiscovered;
}
QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
{
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() );
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
QJsonObject properties;
// Get Nanoleaf device properties
QString host = params["host"].toString("");
if ( !host.isEmpty() )
if (!host.isEmpty())
{
QString authToken = params["token"].toString("");
QString filter = params["filter"].toString("");
// Resolve hostname and port (or use default API port)
QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts);
QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts);
QString apiHost = addressparts[0];
int apiPort;
if ( addressparts.size() > 1)
if (addressparts.size() > 1)
{
apiPort = addressparts[1].toInt();
}
@ -433,34 +436,33 @@ QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params)
// Perform request
httpResponse response = _restApi->get();
if ( response.error() )
if (response.error())
{
Warning (_log, "%s get properties failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
Warning(_log, "%s get properties failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
}
properties.insert("properties", response.getBody().object());
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;
}
void LedDeviceNanoleaf::identify(const QJsonObject& params)
{
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() );
Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData());
QString host = params["host"].toString("");
if ( !host.isEmpty() )
if (!host.isEmpty())
{
QString authToken = params["token"].toString("");
// Resolve hostname and port (or use default API port)
QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts);
QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts);
QString apiHost = addressparts[0];
int apiPort;
if ( addressparts.size() > 1)
if (addressparts.size() > 1)
{
apiPort = addressparts[1].toInt();
}
@ -474,33 +476,33 @@ void LedDeviceNanoleaf::identify(const QJsonObject& params)
// Perform request
httpResponse response = _restApi->put();
if ( response.error() )
if (response.error())
{
Warning (_log, "%s identification failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
Warning(_log, "%s identification failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason()));
}
}
}
bool LedDeviceNanoleaf::powerOn()
{
if ( _isDeviceReady)
if (_isDeviceReady)
{
changeToExternalControlMode();
//Power-on Nanoleaf device
_restApi->setPath(API_STATE);
_restApi->put( getOnOffRequest(true) );
_restApi->put(getOnOffRequest(true));
}
return true;
}
bool LedDeviceNanoleaf::powerOff()
{
if ( _isDeviceReady)
if (_isDeviceReady)
{
//Power-off the Nanoleaf device physically
_restApi->setPath(API_STATE);
_restApi->put( getOnOffRequest(false) );
_restApi->put(getOnOffRequest(false));
}
return true;
}
@ -508,7 +510,7 @@ bool LedDeviceNanoleaf::powerOff()
QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const
{
QString state = isOn ? STATE_VALUE_TRUE : STATE_VALUE_FALSE;
return QString( "{\"%1\":{\"%2\":%3}}" ).arg(STATE_ON, STATE_ONOFF_VALUE, state);
return QString("{\"%1\":{\"%2\":%3}}").arg(STATE_ON, STATE_ONOFF_VALUE, state);
}
QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
@ -518,15 +520,14 @@ QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode()
//Enable UDP Mode v2
_restApi->setPath(API_EFFECT);
httpResponse response =_restApi->put(API_EXT_MODE_STRING_V2);
httpResponse response = _restApi->put(API_EXT_MODE_STRING_V2);
return response.getBody();
}
int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
int LedDeviceNanoleaf::write(const std::vector<ColorRgb>& ledValues)
{
int retVal = 0;
uint udpBufferSize;
//
// nPanels 2B
@ -537,35 +538,27 @@ int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
//
// Note: Nanoleaf Light Panels (Aurora) now support External Control V2 (tested with FW 3.2.0)
udpBufferSize = _panelLedCount * 8 + 2;
std::vector<uint8_t> udpbuffer;
int udpBufferSize = STREAM_FRAME_PANEL_NUM_SIZE + _panelLedCount * STREAM_FRAME_PANEL_INFO_SIZE;
QByteArray udpbuffer;
udpbuffer.resize(udpBufferSize);
uchar lowByte; // lower byte
uchar highByte; // upper byte
uint i=0;
int i = 0;
// Set number of panels
highByte = static_cast<uchar>(_panelLedCount >>8 );
lowByte = static_cast<uchar>(_panelLedCount & 0xFF);
udpbuffer[i++] = highByte;
udpbuffer[i++] = lowByte;
qToBigEndian<quint16>(static_cast<quint16>(_panelLedCount), udpbuffer.data() + i);
i += 2;
ColorRgb color;
//Maintain LED counter independent from PanelCounter
uint ledCounter = 0;
for ( uint panelCounter=0; panelCounter < _panelLedCount; panelCounter++ )
int ledCounter = 0;
for (int panelCounter = 0; panelCounter < _panelLedCount; panelCounter++)
{
uint panelID = _panelIds[panelCounter];
highByte = static_cast<uchar>(panelID >>8 );
lowByte = static_cast<uchar>(panelID & 0xFF);
int panelID = _panelIds[panelCounter];
// Set panels configured
if( panelCounter >= _startPos && panelCounter <= _endPos ) {
if (panelCounter >= _startPos && panelCounter <= _endPos) {
color = static_cast<ColorRgb>(ledValues.at(ledCounter));
++ledCounter;
}
@ -573,49 +566,35 @@ int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
{
// Set panels not configured to 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
udpbuffer[i++] = highByte;
udpbuffer[i++] = lowByte;
qToBigEndian<quint16>(static_cast<quint16>(panelID), udpbuffer.data() + i);
i += 2;
// Set panel's color LEDs
udpbuffer[i++] = color.red;
udpbuffer[i++] = color.green;
udpbuffer[i++] = color.blue;
udpbuffer[i++] = static_cast<char>(color.red);
udpbuffer[i++] = static_cast<char>(color.green);
udpbuffer[i++] = static_cast<char>(color.blue);
// Set white LED
udpbuffer[i++] = 0; // W not set manually
// Set transition time
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());
DebugIf(verbose3, _log, "writeBytes(): [%d]",retVal);
if (verbose3)
{
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;
}
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

@ -32,7 +32,7 @@ public:
///
/// @param deviceConfig Device's configuration as JSON-Object
///
explicit LedDeviceNanoleaf(const QJsonObject &deviceConfig);
explicit LedDeviceNanoleaf(const QJsonObject& deviceConfig);
///
/// @brief Destructor of the LED-device
@ -44,14 +44,16 @@ public:
///
/// @param[in] deviceConfig Device's configuration as JSON-Object
/// @return LedDevice constructed
static LedDevice* construct(const QJsonObject &deviceConfig);
static LedDevice* construct(const QJsonObject& deviceConfig);
///
/// @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
///
QJsonObject discover() override;
QJsonObject discover(const QJsonObject& params) override;
///
/// @brief Get the Nanoleaf device's resource properties
@ -93,7 +95,7 @@ protected:
/// @param[in] deviceConfig the JSON device configuration
/// @return True, if success
///
bool init(const QJsonObject &deviceConfig) override;
bool init(const QJsonObject& deviceConfig) override;
///
/// @brief Opens the output device.
@ -108,7 +110,7 @@ protected:
/// @param[in] ledValues The RGB-color per LED
/// @return Zero on success, else negative
//////
int write(const std::vector<ColorRgb> & ledValues) override;
int write(const std::vector<ColorRgb>& ledValues) override;
///
/// @brief Power-/turn on the Nanoleaf device.
@ -135,7 +137,7 @@ private:
///
/// @return True, if success
///
bool initRestAPI(const QString &hostname, int port, const QString &token );
bool initRestAPI(const QString& hostname, int port, const QString& token);
///
/// @brief Get Nanoleaf device details and configuration
@ -157,14 +159,7 @@ private:
/// @param isOn True, if to switch on device
/// @return Command to switch device on/off
///
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;
QString getOnOffRequest(bool isOn) const;
///REST-API wrapper
ProviderRestApi* _restApi;
@ -175,8 +170,8 @@ private:
bool _topDown;
bool _leftRight;
uint _startPos;
uint _endPos;
int _startPos;
int _endPos;
//Nanoleaf device details
QString _deviceModel;
@ -184,11 +179,10 @@ private:
ushort _extControlVersion;
/// The number of panels with LEDs
uint _panelLedCount;
int _panelLedCount;
/// Array of the panel ids.
QVector<uint> _panelIds;
QVector<int> _panelIds;
};
#endif // LEDEVICENANOLEAF_H

View File

@ -6,11 +6,11 @@
#include <chrono>
bool verbose = false;
// Constants
namespace {
bool verbose = false;
// Configuration settings
const char CONFIG_ADDRESS[] = "output";
//const char CONFIG_PORT[] = "port";
@ -97,31 +97,6 @@ const int STREAM_SSL_HANDSHAKE_ATTEMPTS = 5;
constexpr std::chrono::milliseconds STREAM_REWRITE_TIME{20};
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
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( "LedCount", "%u", this->getLedCount() );
log( "LedCount", "%d", this->getLedCount() );
log( "ColorOrder", "%s", QSTRING_CSTR( this->getColorOrder() ) );
log( "RefreshTime", "%d", _refreshTimerInterval_ms );
log( "LatchTime", "%d", this->getLatchTime() );
@ -313,7 +288,7 @@ bool LedDevicePhilipsHueBridge::init(const QJsonObject &deviceConfig)
if ( address.isEmpty() )
{
this->setInError("No target hostname nor IP defined");
return false;
isInitOK = false;
}
else
{
@ -485,7 +460,7 @@ void LedDevicePhilipsHueBridge::setBridgeConfig(const QJsonDocument &doc)
log( "Bridge-ID", "%s", QSTRING_CSTR( deviceBridgeID ));
log( "SoftwareVersion", "%s", QSTRING_CSTR( _deviceFirmwareVersion ));
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)
@ -511,7 +486,7 @@ void LedDevicePhilipsHueBridge::setLightsMap(const QJsonDocument &doc)
}
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() )
{
for (const auto id : lArray)
for (const QJsonValueRef id : lArray)
{
unsigned int lightId = id.toString().toUInt();
if( lightId > 0 )
@ -1253,7 +1228,7 @@ QByteArray LedDevicePhilipsHue::prepareStreamData() const
{
QByteArray msg;
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)
{
@ -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>((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;
@ -1298,7 +1273,7 @@ int LedDevicePhilipsHue::close()
}
bool LedDevicePhilipsHue::switchOn()
{
{
Debug(_log, "");
bool rc = false;
@ -1327,7 +1302,7 @@ bool LedDevicePhilipsHue::switchOn()
rc = true;
}
}
}
}
return rc;
}
@ -1388,7 +1363,7 @@ void LedDevicePhilipsHue::stopBlackTimeoutTimer()
bool LedDevicePhilipsHue::noSignalDetection()
{
if( _allLightsBlack )
if( _allLightsBlack && _switchOffOnBlack)
{
if( !_stopConnection && _isInitLeds )
{
@ -1614,7 +1589,7 @@ bool LedDevicePhilipsHue::restoreState()
return rc;
}
QJsonObject LedDevicePhilipsHue::discover()
QJsonObject LedDevicePhilipsHue::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );

View File

@ -17,6 +17,31 @@
#include "ProviderRestApi.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.
*/
@ -326,7 +351,7 @@ public:
///
/// @brief Destructor of the LED-device
///
~LedDevicePhilipsHue();
~LedDevicePhilipsHue() override;
///
/// @brief Constructs the LED-device
@ -339,9 +364,11 @@ public:
/// @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.
///
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @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

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 char API_BASE_PATH[] = "/json/";
const char API_PATH_INFO[] = "info";
//const char API_PATH_INFO[] = "info";
const char API_PATH_STATE[] = "state";
// List of State Information
@ -60,9 +60,9 @@ bool LedDeviceWled::init(const QJsonObject &deviceConfig)
if ( LedDevice::init(deviceConfig) )
{
// Initialise LedDevice configuration and execution environment
uint configuredLedCount = this->getLedCount();
int configuredLedCount = this->getLedCount();
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, "LatchTime : %d", this->getLatchTime());
@ -166,7 +166,7 @@ bool LedDeviceWled::powerOff()
return off;
}
QJsonObject LedDeviceWled::discover()
QJsonObject LedDeviceWled::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );

View File

@ -37,9 +37,11 @@ public:
///
/// @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
///
QJsonObject discover() override;
QJsonObject discover(const QJsonObject& params) override;
///
/// @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 )
{
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
std::this_thread::sleep_for(std::chrono::milliseconds(_waitTimeQuota));
@ -452,7 +452,7 @@ YeelightResponse YeelightLight::handleResponse(int correlationID, QByteArray con
// Debug output
if(!yeeResponse.getResult().empty())
{
for(const auto item : yeeResponse.getResult())
for(const QJsonValueRef item : yeeResponse.getResult())
{
log ( 3, "Result:", "%s", QSTRING_CSTR( item.toString() ));
}
@ -524,7 +524,7 @@ QJsonObject YeelightLight::getProperties()
if( !result.empty())
{
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() ));
properties.insert( propertyList.at(i).toString(), item );
@ -1008,7 +1008,7 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
if ( LedDevice::init(deviceConfig) )
{
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, "RewriteTime : %d", this->getRewriteTime());
Debug(_log, "LatchTime : %d", this->getLatchTime());
@ -1073,8 +1073,8 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
Debug(_log, "Debuglevel : %d", _debuglevel);
QJsonArray configuredYeelightLights = _devConfig[CONFIG_LIGHTS].toArray();
uint configuredYeelightsCount = 0;
for (const QJsonValue light : configuredYeelightLights)
int configuredYeelightsCount = 0;
for (const QJsonValueRef light : configuredYeelightLights)
{
QString host = light.toObject().value("host").toString();
int port = light.toObject().value("port").toInt(API_DEFAULT_PORT);
@ -1085,9 +1085,9 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig)
++configuredYeelightsCount;
}
}
Debug(_log, "Light configured : %u", configuredYeelightsCount );
Debug(_log, "Light configured : %d", configuredYeelightsCount );
uint configuredLedCount = this->getLedCount();
int configuredLedCount = this->getLedCount();
if (configuredYeelightsCount < configuredLedCount )
{
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 )
{
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();
@ -1347,7 +1347,7 @@ bool LedDeviceYeelight::restoreState()
return rc;
}
QJsonObject LedDeviceYeelight::discover()
QJsonObject LedDeviceYeelight::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );

View File

@ -435,12 +435,11 @@ public:
///
static LedDevice* construct(const QJsonObject &deviceConfig);
///
/// @brief Discover Yeelight devices available (for configuration).
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @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

View File

@ -1,4 +1,3 @@
// STL includes
#include <cstring>
#include <cstdio>
@ -16,9 +15,9 @@
const ushort MAX_PORT = 65535;
ProviderUdp::ProviderUdp(const QJsonObject &deviceConfig)
ProviderUdp::ProviderUdp(const QJsonObject& deviceConfig)
: LedDevice(deviceConfig)
, _udpSocket (nullptr)
, _udpSocket(nullptr)
, _port(1)
, _defaultHost("127.0.0.1")
{
@ -30,48 +29,48 @@ ProviderUdp::~ProviderUdp()
delete _udpSocket;
}
bool ProviderUdp::init(const QJsonObject &deviceConfig)
bool ProviderUdp::init(const QJsonObject& deviceConfig)
{
bool isInitOK = false;
// Initialise sub-class
if ( LedDevice::init(deviceConfig) )
if (LedDevice::init(deviceConfig))
{
QString host = deviceConfig["host"].toString(_defaultHost);
if (_address.setAddress(host) )
if (_address.setAddress(host))
{
Debug( _log, "Successfully parsed %s as an IP-address.", QSTRING_CSTR(_address.toString()));
Debug(_log, "Successfully parsed %s as an IP-address.", QSTRING_CSTR(_address.toString()));
}
else
{
QHostInfo hostInfo = QHostInfo::fromName(host);
if ( hostInfo.error() == QHostInfo::NoError )
if (hostInfo.error() == QHostInfo::NoError)
{
_address = hostInfo.addresses().first();
Debug( _log, "Successfully resolved IP-address (%s) for hostname (%s).", QSTRING_CSTR(_address.toString()), QSTRING_CSTR(host));
Debug(_log, "Successfully resolved IP-address (%s) for hostname (%s).", QSTRING_CSTR(_address.toString()), QSTRING_CSTR(host));
}
else
{
QString errortext = QString ("Failed resolving IP-address for [%1], (%2) %3").arg(host).arg(hostInfo.error()).arg(hostInfo.errorString());
this->setInError ( errortext );
QString errortext = QString("Failed resolving IP-address for [%1], (%2) %3").arg(host).arg(hostInfo.error()).arg(hostInfo.errorString());
this->setInError(errortext);
isInitOK = false;
}
}
if ( !_isDeviceInError )
if (!_isDeviceInError)
{
int config_port = deviceConfig["port"].toInt(_port);
if ( config_port <= 0 || config_port > MAX_PORT )
if (config_port <= 0 || config_port > MAX_PORT)
{
QString errortext = QString ("Invalid target port [%1]!").arg(config_port);
this->setInError ( errortext );
QString errortext = QString("Invalid target port [%1]!").arg(config_port);
this->setInError(errortext);
isInitOK = false;
}
else
{
_port = static_cast<int>(config_port);
Debug( _log, "UDP socket will write to %s:%u", QSTRING_CSTR(_address.toString()) , _port );
_port = static_cast<quint16>(config_port);
Debug(_log, "UDP socket will write to %s:%u", QSTRING_CSTR(_address.toString()), _port);
_udpSocket = new QUdpSocket(this);
@ -88,16 +87,16 @@ int ProviderUdp::open()
_isDeviceReady = false;
// Try to bind the UDP-Socket
if ( _udpSocket != nullptr )
if (_udpSocket != nullptr)
{
if ( _udpSocket->state() != QAbstractSocket::BoundState )
if (_udpSocket->state() != QAbstractSocket::BoundState)
{
QHostAddress localAddress = QHostAddress::Any;
quint16 localPort = 0;
if ( !_udpSocket->bind(localAddress, localPort) )
if (!_udpSocket->bind(localAddress, localPort))
{
QString warntext = QString ("Could not bind local address: %1, (%2) %3").arg(localAddress.toString()).arg(_udpSocket->error()).arg(_udpSocket->errorString());
Warning ( _log, "%s", QSTRING_CSTR(warntext));
QString warntext = QString("Could not bind local address: %1, (%2) %3").arg(localAddress.toString()).arg(_udpSocket->error()).arg(_udpSocket->errorString());
Warning(_log, "%s", QSTRING_CSTR(warntext));
}
}
// Everything is OK, device is ready
@ -106,7 +105,7 @@ int ProviderUdp::open()
}
else
{
this->setInError( " Open error. UDP Socket not initialised!" );
this->setInError(" Open error. UDP Socket not initialised!");
}
return retval;
}
@ -116,12 +115,12 @@ int ProviderUdp::close()
int retval = 0;
_isDeviceReady = false;
if ( _udpSocket != nullptr )
if (_udpSocket != nullptr)
{
// Test, if device requires closing
if ( _udpSocket->isOpen() )
if (_udpSocket->isOpen())
{
Debug(_log,"Close UDP-device: %s", QSTRING_CSTR( this->getActiveDeviceType() ) );
Debug(_log, "Close UDP-device: %s", QSTRING_CSTR(this->getActiveDeviceType()));
_udpSocket->close();
// Everything is OK -> device is closed
}
@ -129,22 +128,28 @@ int ProviderUdp::close()
return retval;
}
int ProviderUdp::writeBytes(const unsigned size, const uint8_t * data)
int ProviderUdp::writeBytes(const unsigned size, const uint8_t* data)
{
qint64 retVal = _udpSocket->writeDatagram((const char *)data,size,_address,_port);
int rc = 0;
qint64 bytesWritten = _udpSocket->writeDatagram(reinterpret_cast<const char*>(data), size, _address, _port);
WarningIf((retVal<0), _log, "&s", QSTRING_CSTR(QString
("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
return retVal;
if (bytesWritten == -1 || bytesWritten != size)
{
Warning(_log, "%s", QSTRING_CSTR(QString("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
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
("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
return retVal;
if (bytesWritten == -1 || bytesWritten != bytes.size())
{
Warning(_log, "%s", QSTRING_CSTR(QString("(%1:%2) Write Error: (%3) %4").arg(_address.toString()).arg(_port).arg(_udpSocket->error()).arg(_udpSocket->errorString())));
rc = -1;
}
return rc;
}

View File

@ -21,7 +21,7 @@ public:
///
/// @brief Constructs an UDP LED-device
///
ProviderUdp(const QJsonObject &deviceConfig);
ProviderUdp(const QJsonObject& deviceConfig);
///
/// @brief Destructor of the UDP LED-device
@ -38,7 +38,7 @@ protected:
/// @param[in] deviceConfig the JSON device configuration
/// @return True, if success
///
bool init(const QJsonObject &deviceConfig) override;
bool init(const QJsonObject& deviceConfig) override;
///
/// @brief Opens the output device.
@ -62,7 +62,7 @@ protected:
///
/// @return Zero on success, else negative
///
int writeBytes(const unsigned size, const uint8_t *data);
int writeBytes(const unsigned size, const uint8_t* data);
///
/// @brief Writes the given bytes to the UDP-device
@ -71,10 +71,10 @@ protected:
///
/// @return Zero on success, else negative
///
int writeBytes(const QByteArray &bytes);
int writeBytes(const QByteArray& bytes);
///
QUdpSocket * _udpSocket;
QUdpSocket* _udpSocket;
QHostAddress _address;
quint16 _port;
QString _defaultHost;

View File

@ -26,6 +26,14 @@ bool LedDeviceFile::init(const QJsonObject &deviceConfig)
bool initOK = LedDevice::init(deviceConfig);
_fileName = deviceConfig["output"].toString("/dev/null");
#if _WIN32
if (_fileName == "/dev/null" )
{
_fileName = "NULL";
}
#endif
_printTimeStamp = deviceConfig["printTimeStamp"].toBool(false);
initFile(_fileName);

View File

@ -1,5 +1,7 @@
#include "LedDeviceAdalight.h"
#include <QtEndian>
#include <cassert>
LedDeviceAdalight::LedDeviceAdalight(const QJsonObject &deviceConfig)
@ -50,8 +52,7 @@ bool LedDeviceAdalight::init(const QJsonObject &deviceConfig)
_ledBuffer[0] = 'A';
_ledBuffer[1] = 'd';
_ledBuffer[2] = 'a';
_ledBuffer[3] = (totalLedCount >> 8) & 0xFF; // LED count high byte
_ledBuffer[4] = totalLedCount & 0xFF; // LED count low byte
qToBigEndian<quint16>(static_cast<quint16>(totalLedCount), &_ledBuffer[3]);
_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,

View File

@ -34,7 +34,7 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig)
{
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, "RefreshTime : %d", _refreshTimerInterval_ms);
Debug(_log, "LatchTime : %d", this->getLatchTime());
@ -256,7 +256,7 @@ QString ProviderRs232::discoverFirst()
return "";
}
QJsonObject ProviderRs232::discover()
QJsonObject ProviderRs232::discover(const QJsonObject& /*params*/)
{
QJsonObject devicesDiscovered;
devicesDiscovered.insert("ledDeviceType", _activeDeviceType );

View File

@ -66,12 +66,11 @@ protected:
///
QString discoverFirst() override;
///
/// @brief Discover RS232 serial devices available (for configuration).
/// @param[in] params Parameters used to overwrite discovery default behaviour
///
/// @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

View File

@ -214,7 +214,7 @@ void ProtoClientConnection::handleNotImplemented()
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
{
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)};
_socket->write((const char *) sizeData, sizeof(sizeData));
_socket->write(serializedReply.data(), serializedReply.length());

View File

@ -1,7 +1,3 @@
#undef slots
#include <Python.h>
#define slots
// utils
#include <utils/Logger.h>
@ -48,7 +44,11 @@ PythonInit::PythonInit()
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
#endif
mainThreadState = PyEval_SaveThread();
}

View File

@ -19,8 +19,12 @@ PythonProgram::PythonProgram(const QString & name, Logger * log) :
_tstate = Py_NewInterpreter();
if(_tstate == nullptr)
{
#if (PY_VERSION_HEX >= 0x03020000)
PyThreadState_Swap(mainThreadState);
PyEval_SaveThread();
#else
PyEval_ReleaseLock();
#endif
Error(_log, "Failed to get thread state for %s",QSTRING_CSTR(_name));
return;
}
@ -55,8 +59,12 @@ PythonProgram::~PythonProgram()
// Clean up the thread state
Py_EndInterpreter(_tstate);
#if (PY_VERSION_HEX >= 0x03020000)
PyThreadState_Swap(mainThreadState);
PyEval_SaveThread();
#else
PyEval_ReleaseLock();
#endif
}
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);
}
RgbChannelAdjustment::~RgbChannelAdjustment()
{
}
void RgbChannelAdjustment::resetInitialized()
{
//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)
{
if (str == "subtract_minimum") return WhiteAlgorithm::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;
if (str.isEmpty() || str == "white_off") return WhiteAlgorithm::WHITE_OFF;
if (str == "subtract_minimum")
{
return WhiteAlgorithm::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;
}
if (str.isEmpty() || str == "white_off")
{
return WhiteAlgorithm::WHITE_OFF;
}
return WhiteAlgorithm::INVALID;
}
@ -20,7 +32,7 @@ void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, WhiteAlgorithm algorithm)
{
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->green = input.green - 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
// warm white
const float F1(0.274);
const float F2(0.454);
const float F3(2.333);
const double F1(0.274);
const double F2(0.454);
const double F3(2.333);
output->white = qMin(input.red*F1,qMin(input.green*F2,input.blue*F3));
output->red = input.red - output->white/F1;
output->green = input.green - output->white/F2;
output->blue = input.blue - output->white/F3;
output->white = static_cast<uint8_t>(qMin(input.red*F1,qMin(input.green*F2,input.blue*F3)));
output->red = input.red - static_cast<uint8_t>(output->white/F1);
output->green = input.green - static_cast<uint8_t>(output->white/F2);
output->blue = input.blue - static_cast<uint8_t>(output->white/F3);
break;
}
@ -46,14 +58,14 @@ void Rgb_to_Rgbw(ColorRgb input, ColorRgbw * output, WhiteAlgorithm algorithm)
{
// http://forum.garagecube.com/viewtopic.php?t=10178
// cold white
const float F1(0.299);
const float F2(0.587);
const float F3(0.114);
const double F1(0.299);
const double F2(0.587);
const double F3(0.114);
output->white = qMin(input.red*F1,qMin(input.green*F2,input.blue*F3));
output->red = input.red - output->white/F1;
output->green = input.green - output->white/F2;
output->blue = input.blue - output->white/F3;
output->white = static_cast<uint8_t>(qMin(input.red*F1,qMin(input.green*F2,input.blue*F3)));
output->red = input.red - static_cast<uint8_t>(output->white/F1);
output->green = input.green - static_cast<uint8_t>(output->white/F2);
output->blue = input.blue - static_cast<uint8_t>(output->white/F3);
break;
}

View File

@ -242,7 +242,7 @@ void QtHttpClientWrapper::onReplySendHeadersRequested (void)
{
QByteArray data;
// HTTP Version + Status Code + Status Msg
data.append (QtHttpServer::HTTP_VERSION);
data.append (QtHttpServer::HTTP_VERSION.toUtf8());
data.append (SPACE);
data.append (QByteArray::number (reply->getStatusCode ()));
data.append (SPACE);

View File

@ -223,7 +223,7 @@ void WebSocketClient::sendClose(int status, QString reason)
sendBuffer.append(quint8(length));
}
sendBuffer.append(reason);
sendBuffer.append(reason.toUtf8());
_socket->write(sendBuffer);
_socket->flush();

View File

@ -27,8 +27,10 @@ int count(std::initializer_list<bool> values)
int count = 0;
for (bool value : values) {
if (value)
{
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()));
}
int getInstaneIdbyName(const QJsonObject & reply, const QString name){
int getInstaneIdbyName(const QJsonObject & reply, const QString & name){
if(reply.contains("instance")){
QJsonArray list = reply.value("instance").toArray();
for (const auto & entry : list) {
for (const QJsonValueRef entry : list) {
const QJsonObject obj = entry.toObject();
if(obj["friendly_name"] == name && obj["running"].toBool())
{
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;
return 0;
}
@ -78,23 +82,23 @@ int main(int argc, char * argv[])
try
{
// 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 //
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 & 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 & 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)");
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the leds to the colors according to the given image file");
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)");
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 & 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 & 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 & 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 & 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 & 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");
@ -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 & 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");
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 & 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");
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");
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 & 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 & 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 & 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)");
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");
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 & argOff = parser.add<BooleanOption>(0x0, "off" , "Deactivates 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 & 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.");
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.");
// parse all _options
parser.process(app);
@ -197,7 +201,9 @@ int main(int argc, char * argv[])
// authorization token specified. Use it first
if (parser.isSet(argToken))
{
connection.setToken(argToken.value(parser));
}
// If a specific Hyperion instance is given, set it
if (parser.isSet(argInstance))
@ -316,7 +322,7 @@ int main(int argc, char * argv[])
}
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;
return 1;
}

View File

@ -61,7 +61,7 @@
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"))
, _instanceManager(new HyperionIManager(rootPath, this, readonlyMode))
, _authManager(new AuthManager(this, readonlyMode))
@ -101,12 +101,14 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, bool log
// set inital log lvl if the loglvl wasn't overwritten by arg
if (!logLvlOverwrite)
{
handleSettingsUpdate(settings::LOGGER, getSetting(settings::LOGGER));
}
createCecHandler();
// init EffectFileHandler
EffectFileHandler *efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this);
EffectFileHandler* efh = new EffectFileHandler(rootPath, getSetting(settings::EFFECTS), this);
connect(this, &HyperionDaemon::settingsChanged, efh, &EffectFileHandler::handleSettingsUpdate);
// connect and apply settings for AuthManager
@ -135,7 +137,7 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, bool log
// return videoMode changes from Daemon to HyperionIManager
connect(this, &HyperionDaemon::videoMode, _instanceManager, &HyperionIManager::newVideoMode);
// ---- grabber -----
// ---- grabber -----
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) && !defined(ENABLE_X11) && !defined(ENABLE_XCB) && !defined(ENABLE_AMLOGIC) && !defined(ENABLE_QT) && !defined(ENABLE_DX)
Info(_log, "No platform capture supported on this platform");
#endif
@ -178,7 +180,7 @@ void HyperionDaemon::freeObjects()
delete _jsonServer;
_jsonServer = nullptr;
if (_flatBufferServer)
if (_flatBufferServer != nullptr)
{
auto flatBufferServerThread = _flatBufferServer->thread();
flatBufferServerThread->quit();
@ -187,7 +189,7 @@ void HyperionDaemon::freeObjects()
_flatBufferServer = nullptr;
}
if (_protoServer)
if (_protoServer != nullptr)
{
auto protoServerThread = _protoServer->thread();
protoServerThread->quit();
@ -197,7 +199,7 @@ void HyperionDaemon::freeObjects()
}
//ssdp before webserver
if (_ssdp)
if (_ssdp != nullptr)
{
auto ssdpThread = _ssdp->thread();
ssdpThread->quit();
@ -206,18 +208,18 @@ void HyperionDaemon::freeObjects()
_ssdp = nullptr;
}
if(_webserver)
if (_webserver != nullptr)
{
auto webserverThread =_webserver->thread();
auto webserverThread = _webserver->thread();
webserverThread->quit();
webserverThread->wait();
delete webserverThread;
_webserver = nullptr;
}
if (_sslWebserver)
if (_sslWebserver != nullptr)
{
auto sslWebserverThread =_sslWebserver->thread();
auto sslWebserverThread = _sslWebserver->thread();
sslWebserverThread->quit();
sslWebserverThread->wait();
delete sslWebserverThread;
@ -225,7 +227,7 @@ void HyperionDaemon::freeObjects()
}
#ifdef ENABLE_CEC
if (_cecHandler)
if (_cecHandler != nullptr)
{
auto cecHandlerThread = _cecHandler->thread();
cecHandlerThread->quit();
@ -239,7 +241,11 @@ void HyperionDaemon::freeObjects()
// stop Hyperions (non blocking)
_instanceManager->stopAll();
#ifdef ENABLE_AVAHI
delete _bonjourBrowserWrapper;
_bonjourBrowserWrapper = nullptr;
#endif
delete _amlGrabber;
delete _dispmanx;
delete _fbGrabber;
@ -249,7 +255,7 @@ void HyperionDaemon::freeObjects()
delete _v4l2Grabber;
_v4l2Grabber = nullptr;
_bonjourBrowserWrapper = nullptr;
_amlGrabber = nullptr;
_dispmanx = nullptr;
_fbGrabber = nullptr;
@ -266,7 +272,7 @@ void HyperionDaemon::startNetworkServices()
// Create FlatBuffer server in thread
_flatBufferServer = new FlatBufferServer(getSetting(settings::FLATBUFSERVER));
QThread *fbThread = new QThread(this);
QThread* fbThread = new QThread(this);
fbThread->setObjectName("FlatBufferServerThread");
_flatBufferServer->moveToThread(fbThread);
connect(fbThread, &QThread::started, _flatBufferServer, &FlatBufferServer::initServer);
@ -276,7 +282,7 @@ void HyperionDaemon::startNetworkServices()
// Create Proto server in thread
_protoServer = new ProtoServer(getSetting(settings::PROTOSERVER));
QThread *pThread = new QThread(this);
QThread* pThread = new QThread(this);
pThread->setObjectName("ProtoServerThread");
_protoServer->moveToThread(pThread);
connect(pThread, &QThread::started, _protoServer, &ProtoServer::initServer);
@ -286,7 +292,7 @@ void HyperionDaemon::startNetworkServices()
// Create Webserver in thread
_webserver = new WebServer(getSetting(settings::WEBSERVER), false);
QThread *wsThread = new QThread(this);
QThread* wsThread = new QThread(this);
wsThread->setObjectName("WebServerThread");
_webserver->moveToThread(wsThread);
connect(wsThread, &QThread::started, _webserver, &WebServer::initServer);
@ -296,7 +302,7 @@ void HyperionDaemon::startNetworkServices()
// Create SSL Webserver in thread
_sslWebserver = new WebServer(getSetting(settings::WEBSERVER), true);
QThread *sslWsThread = new QThread(this);
QThread* sslWsThread = new QThread(this);
sslWsThread->setObjectName("SSLWebServerThread");
_sslWebserver->moveToThread(sslWsThread);
connect(sslWsThread, &QThread::started, _sslWebserver, &WebServer::initServer);
@ -311,7 +317,7 @@ void HyperionDaemon::startNetworkServices()
getSetting(settings::JSONSERVER).object()["port"].toInt(),
getSetting(settings::WEBSERVER).object()["sslPort"].toInt(),
getSetting(settings::GENERAL).object()["name"].toString());
QThread *ssdpThread = new QThread(this);
QThread* ssdpThread = new QThread(this);
ssdpThread->setObjectName("SSDPThread");
_ssdp->moveToThread(ssdpThread);
connect(ssdpThread, &QThread::started, _ssdp, &SSDPHandler::initServer);
@ -321,26 +327,34 @@ void HyperionDaemon::startNetworkServices()
ssdpThread->start();
}
void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJsonDocument &config)
void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJsonDocument& config)
{
if (settingsType == settings::LOGGER)
{
const QJsonObject &logConfig = config.object();
const QJsonObject& logConfig = config.object();
std::string level = logConfig["level"].toString("warn").toStdString(); // silent warn verbose debug
if (level == "silent")
{
Logger::setLogLevel(Logger::OFF);
}
else if (level == "warn")
{
Logger::setLogLevel(Logger::LogLevel::WARNING);
}
else if (level == "verbose")
{
Logger::setLogLevel(Logger::INFO);
}
else if (level == "debug")
{
Logger::setLogLevel(Logger::DEBUG);
}
}
if (settingsType == settings::SYSTEMCAPTURE)
{
const QJsonObject &grabberConfig = config.object();
const QJsonObject& grabberConfig = config.object();
_grabber_width = grabberConfig["width"].toInt(96);
_grabber_height = grabberConfig["height"].toInt(96);
@ -354,11 +368,11 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
_grabber_ge2d_mode = grabberConfig["ge2d_mode"].toInt(0);
_grabber_device = grabberConfig["amlogic_grabber"].toString("amvideocap0");
#ifdef ENABLE_OSX
#ifdef ENABLE_OSX
QString type = "osx";
#else
#else
QString type = grabberConfig["type"].toString("auto");
#endif
#endif
// auto eval of type
if (type == "auto")
@ -369,7 +383,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
type = "dispmanx";
}
// amlogic -> /dev/amvideo exists
else if (QFile::exists("/dev/amvideo"))
else
{
if (QFile::exists("/dev/amvideo"))
{
type = "amlogic";
@ -382,7 +398,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
{
// x11 -> if DISPLAY is set
QByteArray envDisplay = qgetenv("DISPLAY");
if ( !envDisplay.isEmpty() )
if (!envDisplay.isEmpty())
{
#if defined(ENABLE_X11)
type = "x11";
@ -399,6 +415,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
}
}
}
if (_prevType != type)
{
@ -406,7 +423,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
// stop all capture interfaces
#ifdef ENABLE_FB
if(_fbGrabber != nullptr)
if (_fbGrabber != nullptr)
{
_fbGrabber->stop();
delete _fbGrabber;
@ -414,7 +431,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_DISPMANX
if(_dispmanx != nullptr)
if (_dispmanx != nullptr)
{
_dispmanx->stop();
delete _dispmanx;
@ -422,7 +439,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_AMLOGIC
if(_amlGrabber != nullptr)
if (_amlGrabber != nullptr)
{
_amlGrabber->stop();
delete _amlGrabber;
@ -430,7 +447,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_OSX
if(_osxGrabber != nullptr)
if (_osxGrabber != nullptr)
{
_osxGrabber->stop();
delete _osxGrabber;
@ -438,7 +455,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_X11
if(_x11Grabber != nullptr)
if (_x11Grabber != nullptr)
{
_x11Grabber->stop();
delete _x11Grabber;
@ -446,7 +463,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_XCB
if(_xcbGrabber != nullptr)
if (_xcbGrabber != nullptr)
{
_xcbGrabber->stop();
delete _xcbGrabber;
@ -454,7 +471,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_QT
if(_qtGrabber != nullptr)
if (_qtGrabber != nullptr)
{
_qtGrabber->stop();
delete _qtGrabber;
@ -462,7 +479,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
#endif
#ifdef ENABLE_DX
if(_dxGrabber != nullptr)
if (_dxGrabber != nullptr)
{
_dxGrabber->stop();
delete _dxGrabber;
@ -474,7 +491,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
if (type == "framebuffer")
{
if (_fbGrabber == nullptr)
{
createGrabberFramebuffer(grabberConfig);
}
#ifdef ENABLE_FB
_fbGrabber->tryStart();
#endif
@ -482,7 +501,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "dispmanx")
{
if (_dispmanx == nullptr)
{
createGrabberDispmanx();
}
#ifdef ENABLE_DISPMANX
_dispmanx->tryStart();
#endif
@ -490,7 +511,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "amlogic")
{
if (_amlGrabber == nullptr)
{
createGrabberAmlogic();
}
#ifdef ENABLE_AMLOGIC
_amlGrabber->tryStart();
#endif
@ -498,7 +521,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "osx")
{
if (_osxGrabber == nullptr)
{
createGrabberOsx(grabberConfig);
}
#ifdef ENABLE_OSX
_osxGrabber->tryStart();
#endif
@ -506,7 +531,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "x11")
{
if (_x11Grabber == nullptr)
{
createGrabberX11(grabberConfig);
}
#ifdef ENABLE_X11
_x11Grabber->tryStart();
#endif
@ -514,7 +541,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "xcb")
{
if (_xcbGrabber == nullptr)
{
createGrabberXcb(grabberConfig);
}
#ifdef ENABLE_XCB
_xcbGrabber->tryStart();
#endif
@ -522,7 +551,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "qt")
{
if (_qtGrabber == nullptr)
{
createGrabberQt(grabberConfig);
}
#ifdef ENABLE_QT
_qtGrabber->tryStart();
#endif
@ -530,7 +561,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
else if (type == "dx")
{
if (_dxGrabber == nullptr)
{
createGrabberDx(grabberConfig);
}
#ifdef ENABLE_DX
_dxGrabber->tryStart();
#endif
@ -545,10 +578,13 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
}
else if (settingsType == settings::V4L2)
{
const QJsonObject &grabberConfig = config.object();
#if defined(ENABLE_CEC) || defined(ENABLE_V4L2)
const QJsonObject& grabberConfig = config.object();
#endif
#ifdef ENABLE_CEC
QString operation;
if (_cecHandler && grabberConfig["cecDetection"].toBool(false))
if (_cecHandler != nullptr && grabberConfig["cecDetection"].toBool(false))
{
QMetaObject::invokeMethod(_cecHandler, "start", Qt::QueuedConnection);
}
@ -559,7 +595,9 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs
#endif
if (_v4l2Grabber != nullptr)
{
return;
}
#ifdef ENABLE_V4L2
_v4l2Grabber = new V4L2Wrapper(
@ -632,7 +670,7 @@ void HyperionDaemon::createGrabberAmlogic()
#endif
}
void HyperionDaemon::createGrabberX11(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberX11(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_X11
_x11Grabber = new X11Wrapper(
@ -651,7 +689,7 @@ void HyperionDaemon::createGrabberX11(const QJsonObject &grabberConfig)
#endif
}
void HyperionDaemon::createGrabberXcb(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberXcb(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_XCB
_xcbGrabber = new XcbWrapper(
@ -670,7 +708,7 @@ void HyperionDaemon::createGrabberXcb(const QJsonObject &grabberConfig)
#endif
}
void HyperionDaemon::createGrabberQt(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberQt(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_QT
_qtGrabber = new QtWrapper(
@ -689,7 +727,7 @@ void HyperionDaemon::createGrabberQt(const QJsonObject &grabberConfig)
#endif
}
void HyperionDaemon::createGrabberDx(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberDx(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_DX
_dxGrabber = new DirectXWrapper(
@ -708,7 +746,7 @@ void HyperionDaemon::createGrabberDx(const QJsonObject &grabberConfig)
#endif
}
void HyperionDaemon::createGrabberFramebuffer(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberFramebuffer(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_FB
// Construct and start the framebuffer grabber if the configuration is present
@ -726,7 +764,7 @@ void HyperionDaemon::createGrabberFramebuffer(const QJsonObject &grabberConfig)
#endif
}
void HyperionDaemon::createGrabberOsx(const QJsonObject &grabberConfig)
void HyperionDaemon::createGrabberOsx(const QJsonObject& grabberConfig)
{
#ifdef ENABLE_OSX
// Construct and start the osx grabber if the configuration is present
@ -749,14 +787,16 @@ void HyperionDaemon::createCecHandler()
#if defined(ENABLE_V4L2) && defined(ENABLE_CEC)
_cecHandler = new CECHandler;
QThread * thread = new QThread(this);
QThread* thread = new QThread(this);
thread->setObjectName("CECThread");
_cecHandler->moveToThread(thread);
thread->start();
connect(_cecHandler, &CECHandler::cecEvent, [&] (CECEvent event) {
if (_v4l2Grabber)
connect(_cecHandler, &CECHandler::cecEvent, [&](CECEvent event) {
if (_v4l2Grabber != nullptr)
{
_v4l2Grabber->handleCecEvent(event);
}
});
Info(_log, "CEC handler created");

View File

@ -86,18 +86,18 @@ class HyperionDaemon : public QObject
friend SysTray;
public:
HyperionDaemon(QString rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode = false);
HyperionDaemon(const QString& rootPath, QObject *parent, bool logLvlOverwrite, bool readonlyMode = false);
~HyperionDaemon();
///
/// @brief Get webserver pointer (systray)
///
WebServer* getWebServerInstance() { return _webserver; };
WebServer *getWebServerInstance() { return _webserver; }
///
/// @brief Get the current videoMode
///
VideoMode getVideoMode() const { return _currVideoMode; };
VideoMode getVideoMode() const { return _currVideoMode; }
///
/// @brief get the settings
@ -106,7 +106,7 @@ public:
void startNetworkServices();
static HyperionDaemon* getInstance() { return daemon; };
static HyperionDaemon* getInstance() { return daemon; }
static HyperionDaemon* daemon;
public slots:

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python
import json, sys, glob
import json, sys
from os import path
from jsonschema import Draft3Validator, RefResolver

View File

@ -190,12 +190,13 @@ class Draft3Validator(object):
for type in types:
if self.is_type(type, "object"):
if self.is_valid(instance, type):
return
break
elif self.is_type(type, "string"):
if self.is_type(instance, type):
return
break
else:
yield ValidationError(_types_msg(instance, types))
return
def validate_properties(self, properties, instance, schema):
if not self.is_type(instance, "object"):