diff --git a/.travis.yml b/.travis.yml
index 2c3419c3..7fd8ec6a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,6 +22,6 @@ before_install:
- ./.travis/travis_install.sh
script:
- ./.travis/travis_build.sh
-after_success:
- ./test/testrunner.sh
+after_success:
- ./.travis/travis_deploy.sh
\ No newline at end of file
diff --git a/.travis/travis_deploy.sh b/.travis/travis_deploy.sh
index fc6eba6f..db7e398a 100644
--- a/.travis/travis_deploy.sh
+++ b/.travis/travis_deploy.sh
@@ -4,7 +4,7 @@
sf_upload()
{
/usr/bin/expect <<-EOD
- spawn scp $1 $2 hyperionsf37@frs.sourceforge.net:/home/frs/project/hyperion-project/dev/$3
+ spawn scp $1 hyperionsf37@frs.sourceforge.net:/home/frs/project/hyperion-project/dev/$2
expect "*(yes/no)*"
send "yes\r"
expect "*password:*"
@@ -13,7 +13,7 @@ sf_upload()
EOD
}
-deploylist="hyperion-2.0.0-Linux-x86.deb hyperion-2.0.0-Linux-x86.tar.gz"
+deploylist="hyperion-2.0.0-Linux-x86.tar.gz"
if [[ $TRAVIS_OS_NAME == 'linux' ]]; then
cd $TRAVIS_BUILD_DIR/build
diff --git a/assets/webconfig/content/connection_lost.html b/assets/webconfig/content/connection_lost.html
index fa883b28..409a208f 100644
--- a/assets/webconfig/content/connection_lost.html
+++ b/assets/webconfig/content/connection_lost.html
@@ -1,15 +1,22 @@
-
-
-
-
-
Connection to Hyperion Service lost!
-
-
+
+
+
+
+
Lost connection to Hyperion service!
+
+ Possible reasons:
+
1. Hyperion restarts
+
2. You perform an update
+
3. An older browser session
+
3. Hyperion isn't running
+
+
+
This page will be automatically refreshed.
+
We reconnect again after Hyperion is available.
+
If not, click me
+
+
diff --git a/assets/webconfig/css/hyperion.css b/assets/webconfig/css/hyperion.css
index 4c04f22a..392ff51e 100644
--- a/assets/webconfig/css/hyperion.css
+++ b/assets/webconfig/css/hyperion.css
@@ -49,8 +49,15 @@ table.borderless td,table.borderless th{border: none !important;}
.introd{padding-left:14px;border-left:5px solid #0088cc;}
.introd h4{line-height:25px;}
+/*backported bootstrap 4 forms-label alignment*/
+.col-form-label {
+ padding-top: .5rem;
+ padding-bottom: .5rem;
+ margin-bottom: 0;
+}
+
.overlay {
- background-image: url('/img/hyperion/hyperionlogo.png');
+ background-image: url('/img/hyperion/hyperionwhitelogo.png');
background-repeat: no-repeat;
background-position: center center;
background-color: rgba(1, 1, 1, 0.7);
diff --git a/assets/webconfig/img/hyperion/hyperionlostconnection.png b/assets/webconfig/img/hyperion/hyperionlostconnection.png
new file mode 100644
index 00000000..3b899029
Binary files /dev/null and b/assets/webconfig/img/hyperion/hyperionlostconnection.png differ
diff --git a/assets/webconfig/img/hyperion/hyperionwhitelogo.png b/assets/webconfig/img/hyperion/hyperionwhitelogo.png
new file mode 100644
index 00000000..65338f68
Binary files /dev/null and b/assets/webconfig/img/hyperion/hyperionwhitelogo.png differ
diff --git a/assets/webconfig/index.html b/assets/webconfig/index.html
index 935ec129..fbadfd00 100644
--- a/assets/webconfig/index.html
+++ b/assets/webconfig/index.html
@@ -98,6 +98,7 @@
+
diff --git a/assets/webconfig/js/content_generalconf.js b/assets/webconfig/js/content_generalconf.js
index 1341ba56..26f67a94 100644
--- a/assets/webconfig/js/content_generalconf.js
+++ b/assets/webconfig/js/content_generalconf.js
@@ -23,20 +23,6 @@ $(hyperion).one("cmd-config-getschema", function(event) {
parsedConfSchemaJSON = event.response.result;
schema = parsedConfSchemaJSON.properties;
- blackborderdetector = schema.blackborderdetector;
- color = schema.color;
- effects = schema.effects;
- forwarder = schema.forwarder;
- initialEffect = schema.initialEffect;
- kodiVideoChecker = schema.kodiVideoChecker;
- smoothing = schema.smoothing;
- logger = schema.logger;
- jsonServer = schema.jsonServer;
- protoServer = schema.protoServer;
- boblightServer = schema.boblightServer;
- udpListener = schema.udpListener;
- webConfig = schema.webConfig;
-
var element = document.getElementById('editor_container');
var general_conf_editor = new JSONEditor(element,{
@@ -50,19 +36,19 @@ $(hyperion).one("cmd-config-getschema", function(event) {
schema: {
title:'',
properties: {
- blackborderdetector,
- color,
- effects,
- forwarder,
- initialEffect,
- kodiVideoChecker,
- smoothing,
- logger,
- jsonServer,
- protoServer,
- boblightServer,
- udpListener,
- webConfig
+ blackborderdetector: schema.blackborderdetector,
+ color : schema.color,
+ effects : schema.effects,
+ forwarder : schema.forwarder,
+ initialEffect : schema.initialEffect,
+ kodiVideoChecker : schema.kodiVideoChecker,
+ smoothing : schema.smoothing,
+ logger : schema.logger,
+ jsonServer : schema.jsonServer,
+ protoServer : schema.protoServer,
+ boblightServer : schema.boblightServer,
+ udpListener : schema.udpListener,
+ webConfig : schema.webConfig
}
}
});
@@ -80,7 +66,7 @@ $(hyperion).one("cmd-config-getschema", function(event) {
// });
//Alternative Function with submit button to get Values
- $('btn_submit').off().on('click',function() {
+ $('#btn_submit').off().on('click',function() {
console.log(general_conf_editor.getValue());
});
diff --git a/assets/webconfig/js/content_grabber.js b/assets/webconfig/js/content_grabber.js
index f6d2234b..6d442464 100644
--- a/assets/webconfig/js/content_grabber.js
+++ b/assets/webconfig/js/content_grabber.js
@@ -20,15 +20,14 @@ function removeAdvanced(obj,searchStack)
}
*/
+var grabber_conf_editor = null;
$(hyperion).one("cmd-config-getschema", function(event) {
parsedConfSchemaJSON = event.response.result;
schema = parsedConfSchemaJSON.properties;
- schema_framegrabber = schema.framegrabber;
- schema_grabberv4l2 = schema["grabber-v4l2"];
var element = document.getElementById('editor_container');
- var grabber_conf_editor = new JSONEditor(element,{
+ grabber_conf_editor = new JSONEditor(element,{
theme: 'bootstrap3',
iconlib: "fontawesome4",
disable_collapse: 'true',
@@ -39,8 +38,8 @@ $(hyperion).one("cmd-config-getschema", function(event) {
schema: {
title:'',
properties: {
- schema_framegrabber,
- schema_grabberv4l2,
+ framegrabber: schema.framegrabber,
+ grabberV4L2 : schema["grabberV4L2"]
}
}
});
@@ -59,7 +58,7 @@ $(document).ready( function() {
document.getElementById('btn_submit').addEventListener('click',function() {
// Get the value from the editor
- //console.log(general_conf_editor.getValue());
+ console.log(grabber_conf_editor.getValue());
});
// $("[type='checkbox']").bootstrapSwitch();
});
diff --git a/assets/webconfig/js/content_index.js b/assets/webconfig/js/content_index.js
index fc90b20b..6d14d88a 100644
--- a/assets/webconfig/js/content_index.js
+++ b/assets/webconfig/js/content_index.js
@@ -1,6 +1,5 @@
$(document).ready( function() {
$("#main-nav").hide();
- $("#page-content").hide();
$("#loading_overlay").addClass("overlay");
loadContentTo("#container_connection_lost","connection_lost");
initWebSocket();
@@ -62,7 +61,6 @@ $(document).ready( function() {
});
$("#loading_overlay").removeClass("overlay");
$("#main-nav").show('slide', {direction: 'left'}, 1000);
- $("#page-content").show('slide', {direction: 'down'}, 2000);
}); // end cmd-serverinfo
diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js
index 2330136b..24bb7557 100644
--- a/assets/webconfig/js/content_leds.js
+++ b/assets/webconfig/js/content_leds.js
@@ -153,8 +153,8 @@ $(document).ready(function() {
schema: {
title:' ',
properties: {
- generalOptions,
- specificOptions,
+ generalOptions : generalOptions,
+ specificOptions : specificOptions,
}
}
});
diff --git a/assets/webconfig/js/content_remote.js b/assets/webconfig/js/content_remote.js
index 85fc680e..ac9b551b 100644
--- a/assets/webconfig/js/content_remote.js
+++ b/assets/webconfig/js/content_remote.js
@@ -96,6 +96,7 @@ $(document).ready(function() {
$('#cp2').colorpicker().on('changeColor', function(e) {
color = e.color.toRGB();
+ $("#effect_select").val("__none__");
requestSetColor(color.r, color.g, color.b);
});
});
@@ -106,7 +107,10 @@ $(document).ready(function() {
efx = $(this).val();
if(efx != "__none__")
{
- requestPlayEffect(efx);
+ requestPriorityClear();
+ $(hyperion).one("cmd-clear", function(event) {
+ setTimeout(function() {requestPlayEffect(efx)}, 100);
+ });
}
});
diff --git a/assets/webconfig/js/lib/jsoneditor.js b/assets/webconfig/js/lib/jsoneditor.js
index 8b81c0ff..6ddc4869 100755
--- a/assets/webconfig/js/lib/jsoneditor.js
+++ b/assets/webconfig/js/lib/jsoneditor.js
@@ -1938,6 +1938,7 @@ JSONEditor.defaults.editors.string = JSONEditor.AbstractEditor.extend({
var self = this, i;
if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
+ if(this.schema.append) this.append = this.theme.getFormInputAppend(this.schema.append);
this.format = this.schema.format;
if(!this.format && this.schema.media && this.schema.media.type) {
@@ -2122,7 +2123,7 @@ JSONEditor.defaults.editors.string = JSONEditor.AbstractEditor.extend({
if(this.format) this.input.setAttribute('data-schemaformat',this.format);
- this.control = this.theme.getFormControl(this.label, this.input, this.description);
+ this.control = this.theme.getFormControl(this.label, this.input, this.description, this.append);
this.container.appendChild(this.control);
// Any special formatting that needs to happen after the input is added to the dom
@@ -2716,6 +2717,12 @@ JSONEditor.defaults.editors.object = JSONEditor.AbstractEditor.extend({
this.description = this.theme.getDescription(this.schema.description);
this.container.appendChild(this.description);
}
+
+ // Appends
+ if(this.schema.append) {
+ this.append = this.theme.getAppend(this.schema.append);
+ this.container.appendChild(this.append);
+ }
// Validation error placeholder area
this.error_holder = document.createElement('div');
@@ -3313,6 +3320,10 @@ JSONEditor.defaults.editors.array = JSONEditor.AbstractEditor.extend({
if(this.schema.description) {
this.description = this.theme.getDescription(this.schema.description);
this.container.appendChild(this.description);
+ }
+ if(this.schema.append) {
+ this.append = this.theme.getAppend(this.schema.append);
+ this.container.appendChild(this.append);
}
this.error_holder = document.createElement('div');
this.container.appendChild(this.error_holder);
@@ -3988,6 +3999,10 @@ JSONEditor.defaults.editors.table = JSONEditor.defaults.editors.array.extend({
if(this.schema.description) {
this.description = this.theme.getDescription(this.schema.description);
this.container.appendChild(this.description);
+ }
+ if(this.schema.append) {
+ this.append = this.theme.getAppend(this.schema.append);
+ this.container.appendChild(this.append);
}
this.panel = this.theme.getIndentedPanel();
this.container.appendChild(this.panel);
@@ -4974,7 +4989,8 @@ JSONEditor.defaults.editors.select = JSONEditor.AbstractEditor.extend({
var self = this;
if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-
+ if(this.schema.append) this.append = this.theme.getFormInputAppend(this.schema.append);
+
if(this.options.compact) this.container.className += ' compact';
this.input = this.theme.getSelectInput(this.enum_options);
@@ -5320,6 +5336,7 @@ JSONEditor.defaults.editors.selectize = JSONEditor.AbstractEditor.extend({
var self = this;
if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
+ if(this.schema.append) this.append = this.theme.getFormInputAppend(this.schema.append);
if(this.options.compact) this.container.className += ' compact';
@@ -5547,6 +5564,7 @@ JSONEditor.defaults.editors.multiselect = JSONEditor.AbstractEditor.extend({
var self = this, i;
if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
+ if(this.schema.append) this.append = this.theme.getFormInputAppend(this.schema.append);
if((!this.schema.format && this.option_keys.length < 8) || this.schema.format === "checkbox") {
this.input_type = 'checkboxes';
@@ -6025,6 +6043,9 @@ JSONEditor.defaults.editors.arraySelectize = JSONEditor.AbstractEditor.extend({
if(this.schema.description) {
this.description = this.theme.getDescription(this.schema.description);
}
+ if(this.schema.append) {
+ this.append = this.theme.getAppend(this.schema.append);
+ }
this.input = document.createElement('select');
this.input.setAttribute('multiple', 'multiple');
@@ -6307,6 +6328,11 @@ JSONEditor.AbstractTheme = Class.extend({
el.innerHTML = text;
return el;
},
+ getAppend: function(text) {
+ var el = document.createElement('p');
+ el.innerHTML = text;
+ return el;
+ },
getCheckboxDescription: function(text) {
return this.getDescription(text);
},
@@ -6518,7 +6544,13 @@ JSONEditor.defaults.themes.bootstrap2 = JSONEditor.AbstractTheme.extend({
el.textContent = text;
return el;
},
- getFormControl: function(label, input, description) {
+ getFormInputAppend: function(text) {
+ var el = document.createElement('div');
+ el.className = 'input-group-addon';
+ el.textContent = text;
+ return el;
+ },
+ getFormControl: function(label, input, description, append) {
var ret = document.createElement('div');
ret.className = 'control-group';
@@ -6676,26 +6708,35 @@ JSONEditor.defaults.themes.bootstrap3 = JSONEditor.AbstractTheme.extend({
}
return el;
},
- getFormControl: function(label, input, description) {
+ getFormControl: function(label, input, description, append) {
var group = document.createElement('div');
+ var subgroup = document.createElement('div');
- if(label && input.type === 'checkbox') {
- group.className += ' checkbox';
- label.appendChild(input);
- label.style.fontSize = '14px';
- group.style.marginTop = '0';
- group.appendChild(label);
- input.style.position = 'relative';
- input.style.cssFloat = 'left';
- }
+ if (append){
+ group.className += ' form-group';
+ if(label) {
+ label.className += ' col-form-label col-md-2';
+ group.appendChild(label);
+ }
+ group.appendChild(subgroup);
+ subgroup.className += 'col-md-10 input-group';
+ subgroup.appendChild(input);
+ subgroup.appendChild(append);
+ }
else {
group.className += ' form-group';
if(label) {
- label.className += ' control-label';
+ label.className += ' col-form-label col-md-2';
group.appendChild(label);
}
- group.appendChild(input);
- }
+ group.appendChild(subgroup);
+ subgroup.className += ' input-group col-md-10';
+ subgroup.appendChild(input);
+ if (input.type === 'checkbox'){
+ label.style.fontWeight = 'bold';
+ }
+ }
+
if(description) group.appendChild(description);
@@ -6713,6 +6754,12 @@ JSONEditor.defaults.themes.bootstrap3 = JSONEditor.AbstractTheme.extend({
el.innerHTML = text;
return el;
},
+ getFormInputAppend: function(text) {
+ var el = document.createElement('div');
+ el.className = 'input-group-addon';
+ el.textContent = text;
+ return el;
+ },
getHeaderButtonHolder: function() {
var el = this.getButtonHolder();
el.style.marginLeft = '10px';
diff --git a/bin/copy_binaries_to_deploy.sh b/bin/copy_binaries_to_deploy.sh
index 82dc5032..6452c2c7 100755
--- a/bin/copy_binaries_to_deploy.sh
+++ b/bin/copy_binaries_to_deploy.sh
@@ -16,8 +16,6 @@ echo create $outfile
tar --create --verbose --gzip --absolute-names --show-transformed-names \
--file "$outfile" \
--transform "s:$builddir/bin/:hyperion/bin/:" \
- --transform "s:$repodir/effects/:hyperion/effects/:" \
- --transform "s:$repodir/config/:hyperion/config/:" \
--transform "s:$repodir/bin/hyperion.init.sh:hyperion/init.d/hyperion.init.sh:" \
--transform "s://:/:g" \
"$builddir/bin/hyperiond" \
@@ -25,6 +23,4 @@ tar --create --verbose --gzip --absolute-names --show-transformed-names \
"$builddir/bin/hyperion-v4l2" \
"$builddir/bin/gpio2spi" \
"$builddir/bin/dispmanx2png" \
- "$repodir/effects/"* \
"$repodir/bin/hyperion.init.sh" \
- "$repodir/config/hyperion.config.json"
diff --git a/cmake/debian/postinst b/cmake/debian/postinst
index f7e4c2e1..7431bb5c 100644
--- a/cmake/debian/postinst
+++ b/cmake/debian/postinst
@@ -20,8 +20,12 @@ install_file()
echo "--- hyperion ambient light postinstall ---"
echo "- install configuration template"
mkdir -p /etc/hyperion
-install_file /usr/share/hyperion/config/hyperion.config.json.default /etc/hyperion/hyperion.config.json
+if [ ! -e "/etc/hyperion/hyperion.config.json" ]
+then
+ echo "install default config to /etc/hyperion"
+ /usr/bin/hyperiond --export-config /etc/hyperion/hyperion.config.json
+fi
HYPERION_RUNNING=false
pgrep hyperiond > /dev/null 2>&1 && HYPERION_RUNNING=true
diff --git a/config/hyperion.config.json.commented b/config/hyperion.config.json.commented
index a8bed600..7a0b1a6c 100644
--- a/config/hyperion.config.json.commented
+++ b/config/hyperion.config.json.commented
@@ -168,7 +168,7 @@
/// * redSignalThreshold : Signal threshold for the red channel between 0.0 and 1.0 [default=0.0]
/// * greenSignalThreshold : Signal threshold for the green channel between 0.0 and 1.0 [default=0.0]
/// * blueSignalThreshold : Signal threshold for the blue channel between 0.0 and 1.0 [default=0.0]
- "grabber-v4l2" :
+ "grabberV4L2" :
[
{
"enable" : false,
@@ -364,7 +364,7 @@
[
"/storage/hyperion/effects",
"/usr/share/hyperion/effects"
- ]
+ ],
"disable" :
[
"Rainbow swirl",
diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default
index 41f9cbca..1747b422 100644
--- a/config/hyperion.config.json.default
+++ b/config/hyperion.config.json.default
@@ -96,7 +96,7 @@
"continuousOutput" : true
},
- "grabber-v4l2" :
+ "grabberV4L2" :
[
{
"enable" : false,
@@ -194,7 +194,7 @@
"webConfig" :
{
- "enable" : true,
+ "enable" : true
},
"effects" :
diff --git a/effects/rainbow-swirl-fast.json b/effects/rainbow-swirl-fast.json
index 88e8d79d..e3bec7ca 100644
--- a/effects/rainbow-swirl-fast.json
+++ b/effects/rainbow-swirl-fast.json
@@ -3,8 +3,9 @@
"script" : "rainbow-swirl.py",
"args" :
{
- "rotation-time" : 3.0,
- "brightness" : 1.0,
+ "rotation-time" : 4.0,
+ "center_x" : 0.5,
+ "center_y" : 0.5,
"reverse" : false
}
}
diff --git a/effects/rainbow-swirl.json b/effects/rainbow-swirl.json
index 43a80a8d..fb952d38 100644
--- a/effects/rainbow-swirl.json
+++ b/effects/rainbow-swirl.json
@@ -4,7 +4,8 @@
"args" :
{
"rotation-time" : 20.0,
- "brightness" : 1.0,
+ "center_x" : 0.5,
+ "center_y" : 0.5,
"reverse" : false
}
}
diff --git a/effects/rainbow-swirl.py b/effects/rainbow-swirl.py
index ec623aa1..6aeaaa56 100644
--- a/effects/rainbow-swirl.py
+++ b/effects/rainbow-swirl.py
@@ -1,39 +1,37 @@
-import hyperion
-import time
-import colorsys
+import hyperion, time
# Get the parameters
rotationTime = float(hyperion.args.get('rotation-time', 3.0))
-brightness = float(hyperion.args.get('brightness', 1.0))
-saturation = float(hyperion.args.get('saturation', 1.0))
-reverse = bool(hyperion.args.get('reverse', False))
+reverse = bool(hyperion.args.get('reverse', False))
+centerX = float(hyperion.args.get('center_x', 0.5))
+centerY = float(hyperion.args.get('center_y', 0.5))
-# Check parameters
-rotationTime = max(0.1, rotationTime)
-brightness = max(0.0, min(brightness, 1.0))
-saturation = max(0.0, min(saturation, 1.0))
+sleepTime = max(0.1, rotationTime) / 360
+angle = 0
+centerX = int(round(hyperion.imageWidth)*centerX)
+centerY = int(round(float(hyperion.imageHeight)*centerY))
+increment = -1 if reverse else 1
-# Initialize the led data
-ledData = bytearray()
-for i in range(hyperion.ledCount):
- hue = float(i)/hyperion.ledCount
- rgb = colorsys.hsv_to_rgb(hue, saturation, brightness)
- ledData += bytearray((int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2])))
+# table of stop colors for rainbow gradient, first is the position, next rgb, all values 0-255
+rainbowColors = bytearray([
+ 0 ,255,0 ,0,
+ 25 ,255,230,0,
+ 63 ,255,255,0,
+ 100,0 ,255,0,
+ 127,0 ,255,200,
+ 159,0 ,255,255,
+ 191,0 ,0 ,255,
+ 224,255,0 ,255,
+ 255,255,0 ,127,
+])
-# Calculate the sleep time and rotation increment
-increment = 3
-sleepTime = rotationTime / hyperion.ledCount
-while sleepTime < 0.05:
- increment *= 2
- sleepTime *= 2
-increment %= hyperion.ledCount
-
-# Switch direction if needed
-if reverse:
- increment = -increment
-
-# Start the write data loop
+# effect loop
while not hyperion.abort():
- hyperion.setColor(ledData)
- ledData = ledData[-increment:] + ledData[:-increment]
+ angle += increment
+ if angle > 360: angle=0
+ if angle < 0: angle=360
+
+ hyperion.imageCanonicalGradient(centerX, centerY, angle, rainbowColors)
+
+ hyperion.imageShow()
time.sleep(sleepTime)
diff --git a/include/commandline/Option.h b/include/commandline/Option.h
index d58bc4fe..722a002f 100644
--- a/include/commandline/Option.h
+++ b/include/commandline/Option.h
@@ -42,6 +42,7 @@ public:
QString value(Parser &parser);
std::string getStdString(Parser &parser);
std::wstring getStdWString(Parser &parser);
+ const char* getCString(Parser &parser);
};
}
diff --git a/include/commandline/Parser.h b/include/commandline/Parser.h
index a9876e87..3c2c7848 100644
--- a/include/commandline/Parser.h
+++ b/include/commandline/Parser.h
@@ -1,5 +1,4 @@
-#ifndef HYPERION_COMMANDLINEPARSER_H
-#define HYPERION_COMMANDLINEPARSER_H
+#pragma once
#include
#include
@@ -20,101 +19,126 @@ namespace commandline
class Parser : public QObject
{
protected:
- QHash _options;
- QString _errorText;
- /* No public inheritance because we need to modify a few methods */
- QCommandLineParser _parser;
+ QHash _options;
+ QString _errorText;
+ /* 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:
- bool parse(const QStringList &arguments);
- void process(const QStringList &arguments);
- void process(const QCoreApplication &app);
- QString errorText() const;
+ bool parse(const QStringList &arguments);
+ void process(const QStringList &arguments);
+ void process(const QCoreApplication &app);
+ QString errorText() const;
- template
- OptionT &add(
- const char shortOption,
- const QString longOption,
+ template
+ OptionT &add(
+ const char shortOption,
+ const QString longOption,
const QString description,
const QString default_,
Args ... args)
- {
- OptionT * option = new OptionT(
- _getNames(shortOption, longOption),
- _getDescription(description, default_),
- longOption,
- default_,
- args...);
- addOption(option);
- return *option;
- }
+ {
+ OptionT * option = new OptionT(
+ _getNames(shortOption, longOption),
+ _getDescription(description, default_),
+ longOption,
+ default_,
+ args...);
+ addOption(option);
+ return *option;
+ }
- /* gcc does not support default arguments for variadic templates which
- * makes this method necessary */
- template
- OptionT &add(
- const char shortOption,
+ /* gcc does not support default arguments for variadic templates which
+ * makes this method necessary */
+ template
+ OptionT &add(
+ const char shortOption,
const QString longOption,
const QString description,
const QString default_ = QString())
- {
- OptionT * option = new OptionT(
- _getNames(shortOption, longOption),
- _getDescription(description, default_),
- longOption,
- default_);
- addOption(option);
- return *option;
- }
+ {
+ OptionT * option = new OptionT(
+ _getNames(shortOption, longOption),
+ _getDescription(description, default_),
+ longOption,
+ default_);
+ addOption(option);
+ return *option;
+ }
- Parser(QString description=QString())
- {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
- { return _parser.applicationDescription(); }
- void clearPositionalArguments()
- { _parser.clearPositionalArguments(); }
- QString helpText() const
- { return _parser.helpText(); }
- bool isSet(const QString &name) const
- { return _parser.isSet(name); }
- bool isSet(const Option &option) const
- { return _parser.isSet(option); }
- bool isSet(const Option *option) const
- { return _parser.isSet(*option); }
- QStringList optionNames() const
- { return _parser.optionNames(); }
- QStringList positionalArguments() const
- { return _parser.positionalArguments(); }
- void setApplicationDescription(const QString &description)
- { _parser.setApplicationDescription(description); }
- void setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode)
- { _parser.setSingleDashWordOptionMode(singleDashWordOptionMode); }
- void showHelp(int exitCode = 0)
- { _parser.showHelp(exitCode); }
- QStringList unknownOptionNames() const
- { return _parser.unknownOptionNames(); }
- QString value(const QString &optionName) const
- { return _parser.value(optionName); }
- QString value(const Option &option) const
- { return _parser.value(option); }
- QStringList values(const QString &optionName) const
- { return _parser.values(optionName); }
- QStringList values(const Option &option) const
- { return _parser.values(option); }
+ Parser(QString description=QString())
+ {
+ 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
+ { return _parser.applicationDescription(); }
+
+ void clearPositionalArguments()
+ { _parser.clearPositionalArguments(); }
+
+ QString helpText() const
+ { return _parser.helpText(); }
+
+ bool isSet(const QString &name) const
+ { return _parser.isSet(name); }
+
+ bool isSet(const Option &option) const
+ { return _parser.isSet(option); }
+
+ bool isSet(const Option *option) const
+ { return _parser.isSet(*option); }
+
+ QStringList optionNames() const
+ { return _parser.optionNames(); }
+
+ QStringList positionalArguments() const
+ { return _parser.positionalArguments(); }
+
+ void setApplicationDescription(const QString &description)
+ { _parser.setApplicationDescription(description); }
+
+ void setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode)
+ { _parser.setSingleDashWordOptionMode(singleDashWordOptionMode); }
+
+ void showHelp(int exitCode = 0)
+ { _parser.showHelp(exitCode); }
+
+ QStringList unknownOptionNames() const
+ { return _parser.unknownOptionNames(); }
+
+ QString value(const QString &optionName) const
+ { return _parser.value(optionName); }
+
+ QString value(const Option &option) const
+ { return _parser.value(option); }
+
+ QStringList values(const QString &optionName) const
+ { return _parser.values(optionName); }
+
+ QStringList values(const Option &option) const
+ { return _parser.values(option); }
};
}
-
-#endif //HYPERION_COMMANDLINEPARSER_H
diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h
index d93096b1..9f706f60 100644
--- a/include/hyperion/Hyperion.h
+++ b/include/hyperion/Hyperion.h
@@ -7,6 +7,7 @@
// QT includes
#include
#include
+#include
// hyperion-utils includes
#include
@@ -85,7 +86,9 @@ public:
/// Returns the number of attached leds
///
unsigned getLedCount() const;
-
+
+ QSize getLedGridSize() const { return _ledGridSize; }
+
///
/// Returns the current priority
///
@@ -292,7 +295,8 @@ public:
static LinearColorSmoothing * createColorSmoothing(const Json::Value & smoothingConfig, LedDevice* leddevice);
static MessageForwarder * createMessageForwarder(const Json::Value & forwarderConfig);
-
+ static QSize getLedLayoutGridSize(const Json::Value& ledsConfig);
+
signals:
/// Signal which is emitted when a priority channel is actively cleared
/// This signal will not be emitted when a priority channel time out
@@ -390,4 +394,6 @@ private:
int _currentSourcePriority;
QByteArray _configHash;
+
+ QSize _ledGridSize;
};
diff --git a/include/utils/FileUtils.h b/include/utils/FileUtils.h
index 8d04dc1f..bda77bc4 100644
--- a/include/utils/FileUtils.h
+++ b/include/utils/FileUtils.h
@@ -1,8 +1,9 @@
+#pragma once
+
#include
namespace FileUtils {
std::string getBaseName( std::string sourceFile);
-
};
diff --git a/include/utils/Process.h b/include/utils/Process.h
index 3e76607d..dd1055c9 100644
--- a/include/utils/Process.h
+++ b/include/utils/Process.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include
namespace Process {
diff --git a/libsrc/commandline/Option.cpp b/libsrc/commandline/Option.cpp
index d8e733e8..abc7892a 100644
--- a/libsrc/commandline/Option.cpp
+++ b/libsrc/commandline/Option.cpp
@@ -24,3 +24,8 @@ std::wstring Option::getStdWString(Parser &parser)
return value(parser).toStdWString();
}
+const char* Option::getCString(Parser &parser)
+{
+ return value(parser).toLocal8Bit().constData();
+}
+
diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt
index 53714ee3..7ae723b4 100644
--- a/libsrc/effectengine/CMakeLists.txt
+++ b/libsrc/effectengine/CMakeLists.txt
@@ -48,6 +48,8 @@ add_library(effectengine
${EffectEngineSOURCES}
)
+qt5_use_modules(effectengine Core Gui)
+
target_link_libraries(effectengine
hyperion
jsoncpp
diff --git a/libsrc/effectengine/Effect.cpp b/libsrc/effectengine/Effect.cpp
index 405557d1..d5707e5d 100644
--- a/libsrc/effectengine/Effect.cpp
+++ b/libsrc/effectengine/Effect.cpp
@@ -8,16 +8,27 @@
// Qt includes
#include
#include
+#include
+#include
+#include
+#include
+#include
// effect engin eincludes
#include "Effect.h"
#include
+#include
// Python method table
PyMethodDef Effect::effectMethods[] = {
- {"setColor", Effect::wrapSetColor, METH_VARARGS, "Set a new color for the leds."},
- {"setImage", Effect::wrapSetImage, METH_VARARGS, "Set a new image to process and determine new led colors."},
- {"abort", Effect::wrapAbort, METH_NOARGS, "Check if the effect should abort execution."},
+ {"setColor", Effect::wrapSetColor, METH_VARARGS, "Set a new color for the leds."},
+ {"setImage", Effect::wrapSetImage, METH_VARARGS, "Set a new image to process and determine new led colors."},
+ {"abort", Effect::wrapAbort, METH_NOARGS, "Check if the effect should abort execution."},
+ {"imageShow", Effect::wrapImageShow, METH_NOARGS, "set current effect image to hyperion core."},
+ {"imageCanonicalGradient", Effect::wrapImageCanonicalGradient, METH_VARARGS, ""},
+ {"imageRadialGradient" , Effect::wrapImageRadialGradient, METH_VARARGS, ""},
+// {"imageSetPixel",Effect::wrapImageShow, METH_VARARGS, "set pixel color of image"},
+// {"imageGetPixel",Effect::wrapImageShow, METH_VARARGS, "get pixel color of image"},
{NULL, NULL, 0, NULL}
};
@@ -69,6 +80,12 @@ Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const
// disable the black border detector for effects
_imageProcessor->enableBlackBorderDetector(false);
+
+ // init effect image for image based effects, size is based on led layout
+ _imageSize = Hyperion::getInstance()->getLedGridSize();
+ _image = new QImage(_imageSize, QImage::Format_ARGB32_Premultiplied);
+ _image->fill(Qt::black);
+ _painter = new QPainter(_image);
// connect the finished signal
connect(this, SIGNAL(finished()), this, SLOT(effectFinished()));
@@ -77,6 +94,8 @@ Effect::Effect(PyThreadState * mainThreadState, int priority, int timeout, const
Effect::~Effect()
{
+ delete _painter;
+ delete _image;
}
void Effect::run()
@@ -96,6 +115,12 @@ void Effect::run()
// add ledCount variable to the interpreter
PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _imageProcessor->getLedCount()));
+ // add imageWidth variable to the interpreter
+ PyObject_SetAttrString(module, "imageWidth", Py_BuildValue("i", _imageSize.width()));
+
+ // add imageHeight variable to the interpreter
+ PyObject_SetAttrString(module, "imageHeight", Py_BuildValue("i", _imageSize.height()));
+
// add a args variable to the interpreter
PyObject_SetAttrString(module, "args", json2python(_args));
@@ -357,6 +382,207 @@ PyObject* Effect::wrapAbort(PyObject *self, PyObject *)
return Py_BuildValue("i", effect->_abortRequested ? 1 : 0);
}
+
+PyObject* Effect::wrapImageShow(PyObject *self, PyObject *args)
+{
+ Effect * effect = getEffect();
+
+ // determine the timeout
+ int timeout = effect->_timeout;
+ if (timeout > 0)
+ {
+ timeout = effect->_endTime - QDateTime::currentMSecsSinceEpoch();
+
+ // we are done if the time has passed
+ if (timeout <= 0)
+ {
+ return Py_BuildValue("");
+ }
+ }
+
+ int width = effect->_imageSize.width();
+ int height = effect->_imageSize.height();
+ QImage * qimage = effect->_image;
+
+ Image image(width, height);
+ QByteArray binaryImage;
+
+ for (int i = 0; i height(); ++i)
+ {
+ const QRgb * scanline = reinterpret_cast(qimage->scanLine(i));
+ for (int j = 0; j < qimage->width(); ++j)
+ {
+ binaryImage.append((char) qRed(scanline[j]));
+ binaryImage.append((char) qGreen(scanline[j]));
+ binaryImage.append((char) qBlue(scanline[j]));
+ }
+ }
+
+ memcpy(image.memptr(), binaryImage.data(), binaryImage.size());
+ effect->_imageProcessor->process(image, effect->_colors);
+ effect->setColors(effect->_priority, effect->_colors, timeout, false);
+
+ return Py_BuildValue("");
+}
+
+
+PyObject* Effect::wrapImageCanonicalGradient(PyObject *self, PyObject *args)
+{
+ Effect * effect = getEffect();
+
+ int argCount = PyTuple_Size(args);
+ PyObject * bytearray = nullptr;
+ int centerX, centerY, angle;
+ int startX = 0;
+ int startY = 0;
+ int width = effect->_imageSize.width();
+ int height = effect->_imageSize.height();
+
+ bool argsOK = false;
+
+ if ( argCount == 8 && PyArg_ParseTuple(args, "iiiiiiiO", &startX, &startY, &width, &height, ¢erX, ¢erY, &angle, &bytearray) )
+ {
+ argsOK = true;
+ }
+ if ( argCount == 4 && PyArg_ParseTuple(args, "iiiO", ¢erX, ¢erY, &angle, &bytearray) )
+ {
+ argsOK = true;
+ }
+ angle = std::max(std::min(angle,360),0);
+
+ if (argsOK)
+ {
+ if (PyByteArray_Check(bytearray))
+ {
+ int length = PyByteArray_Size(bytearray);
+ if (length % 4 == 0)
+ {
+
+ QPainter * painter = effect->_painter;
+ QRect myQRect(startX,startY,width,height);
+ QConicalGradient gradient(QPoint(centerX,centerY), angle );
+ char * data = PyByteArray_AS_STRING(bytearray);
+
+ for (int idx=0; idxfillRect(myQRect, gradient);
+
+ return Py_BuildValue("");
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Length of bytearray argument should multiple of 4");
+ return nullptr;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Argument 8 is not a bytearray");
+ return nullptr;
+ }
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
+PyObject* Effect::wrapImageRadialGradient(PyObject *self, PyObject *args)
+{
+ Effect * effect = getEffect();
+
+ int argCount = PyTuple_Size(args);
+ PyObject * bytearray = nullptr;
+ int centerX, centerY, radius, focalX, focalY, focalRadius;
+ int startX = 0;
+ int startY = 0;
+ int width = effect->_imageSize.width();
+ int height = effect->_imageSize.height();
+
+ bool argsOK = false;
+
+ if ( argCount == 11 && PyArg_ParseTuple(args, "iiiiiiiiiiO", &startX, &startY, &width, &height, ¢erX, ¢erY, &radius, &focalX, &focalY, &focalRadius, &bytearray) )
+ {
+ argsOK = true;
+ }
+ if ( argCount == 8 && PyArg_ParseTuple(args, "iiiiiiiO", &startX, &startY, &width, &height, ¢erX, ¢erY, &radius, &bytearray) )
+ {
+ argsOK = true;
+ focalX = centerX;
+ focalY = centerY;
+ focalRadius = radius;
+ }
+ if ( argCount == 7 && PyArg_ParseTuple(args, "iiiiiiO", ¢erX, ¢erY, &radius, &focalX, &focalY, &focalRadius, &bytearray) )
+ {
+ argsOK = true;
+ }
+ if ( argCount == 4 && PyArg_ParseTuple(args, "iiiO", ¢erX, ¢erY, &radius, &bytearray) )
+ {
+ argsOK = true;
+ focalX = centerX;
+ focalY = centerY;
+ focalRadius = radius;
+ }
+
+ if (argsOK)
+ {
+ if (PyByteArray_Check(bytearray))
+ {
+ int length = PyByteArray_Size(bytearray);
+ if (length % 4 == 0)
+ {
+
+ QPainter * painter = effect->_painter;
+ QRect myQRect(startX,startY,width,height);
+ QRadialGradient gradient(QPoint(centerX,centerY), std::max(radius,0) );
+ char * data = PyByteArray_AS_STRING(bytearray);
+
+ for (int idx=0; idxfillRect(myQRect, gradient);
+
+ return Py_BuildValue("");
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Length of bytearray argument should multiple of 4");
+ return nullptr;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Last argument is not a bytearray");
+ return nullptr;
+ }
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+
Effect * Effect::getEffect()
{
// extract the module from the runtime
diff --git a/libsrc/effectengine/Effect.h b/libsrc/effectengine/Effect.h
index 68c25518..12672f26 100644
--- a/libsrc/effectengine/Effect.h
+++ b/libsrc/effectengine/Effect.h
@@ -5,6 +5,9 @@
// Qt includes
#include
+#include
+#include
+#include
// Hyperion includes
#include
@@ -48,21 +51,25 @@ private:
PyObject * json2python(const Json::Value & json) const;
// Wrapper methods for Python interpreter extra buildin methods
- static PyMethodDef effectMethods[];
- static PyObject* wrapSetColor(PyObject *self, PyObject *args);
+ static PyMethodDef effectMethods[];
+ static PyObject* wrapSetColor(PyObject *self, PyObject *args);
static PyObject* wrapSetImage(PyObject *self, PyObject *args);
static PyObject* wrapAbort(PyObject *self, PyObject *args);
- static Effect * getEffect();
+ static PyObject* wrapImageShow(PyObject *self, PyObject *args);
+ static PyObject* wrapImageCanonicalGradient(PyObject *self, PyObject *args);
+ static PyObject* wrapImageRadialGradient(PyObject *self, PyObject *args);
+
+ static Effect * getEffect();
#if PY_MAJOR_VERSION >= 3
- static struct PyModuleDef moduleDef;
- static PyObject* PyInit_hyperion();
+ static struct PyModuleDef moduleDef;
+ static PyObject* PyInit_hyperion();
#else
- static void PyInit_hyperion();
+ static void PyInit_hyperion();
#endif
private:
- PyThreadState * _mainThreadState;
+ PyThreadState * _mainThreadState;
const int _priority;
@@ -84,5 +91,10 @@ private:
/// Buffer for colorData
std::vector _colors;
+
+ QSize _imageSize;
+
+ QImage * _image;
+ QPainter * _painter;
};
diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp
index 9ff8e867..a44942ca 100644
--- a/libsrc/hyperion/Hyperion.cpp
+++ b/libsrc/hyperion/Hyperion.cpp
@@ -423,6 +423,7 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig, const ColorOr
LedString ledString;
const std::string deviceOrderStr = colorOrderToString(deviceOrder);
int maxLedId = ledsConfig.size();
+
for (const Json::Value& ledConfig : ledsConfig)
{
Led led;
@@ -499,6 +500,51 @@ LedString Hyperion::createLedStringClone(const Json::Value& ledsConfig, const Co
return ledString;
}
+QSize Hyperion::getLedLayoutGridSize(const Json::Value& ledsConfig)
+{
+ std::vector midPointsX;
+ std::vector midPointsY;
+
+ for (const Json::Value& ledConfig : ledsConfig)
+ {
+ if ( ledConfig.get("clone",-1).asInt() < 0 )
+ {
+ const Json::Value& hscanConfig = ledConfig["hscan"];
+ const Json::Value& vscanConfig = ledConfig["vscan"];
+ double minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble()));
+ double maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble()));
+ double minY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble()));
+ double maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble()));
+ // Fix if the user swapped min and max
+ if (minX_frac > maxX_frac)
+ {
+ std::swap(minX_frac, maxX_frac);
+ }
+ if (minY_frac > maxY_frac)
+ {
+ std::swap(minY_frac, maxY_frac);
+ }
+
+ // calculate mid point and make grid calculation
+ midPointsX.push_back( int(1000.0*(minX_frac + maxX_frac) / 2.0) );
+ midPointsY.push_back( int(1000.0*(minY_frac + maxY_frac) / 2.0) );
+ }
+ }
+
+ // remove duplicates
+ std::sort(midPointsX.begin(), midPointsX.end());
+ midPointsX.erase(std::unique(midPointsX.begin(), midPointsX.end()), midPointsX.end());
+ std::sort(midPointsY.begin(), midPointsY.end());
+ midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
+
+ QSize gridSize( midPointsX.size(), midPointsY.size() );
+ Debug(Logger::getInstance("Core"), "led layout grid: %dx%d", gridSize.width(), gridSize.height());
+
+ return gridSize;
+}
+
+
+
LinearColorSmoothing * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig, LedDevice* leddevice)
{
Logger * log = Logger::getInstance("Core");
@@ -578,6 +624,7 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile)
, _hwLedCount(_ledString.leds().size())
, _sourceAutoSelectEnabled(true)
, _configHash()
+ , _ledGridSize(getLedLayoutGridSize(jsonConfig["leds"]))
{
registerPriority("Off", PriorityMuxer::LOWEST_PRIORITY);
diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json
index e10ae6a4..195bc739 100644
--- a/libsrc/hyperion/hyperion.schema.json
+++ b/libsrc/hyperion/hyperion.schema.json
@@ -30,6 +30,7 @@
"name" :
{
"type" : "string",
+ "title" : "Configuration name",
"required" : true,
"propertyOrder" : 1
},
@@ -48,6 +49,7 @@
"colorOrder" :
{
"type" : "string",
+ "title" : "RGB byte order",
"enum" : ["rgb", "bgr", "rbg", "brg", "gbr", "grb"],
"propertyOrder" : 3
}
@@ -397,6 +399,7 @@
"minimum" : 25,
"maximum": 600,
"default" : 200,
+ "append" : "ms",
"propertyOrder" : 3
},
"updateFrequency" :
@@ -406,6 +409,7 @@
"minimum" : 1.000,
"maximum" : 100.000,
"default" : 25.000,
+ "append" : "Hz",
"propertyOrder" : 4
},
"updateDelay" :
@@ -415,6 +419,7 @@
"minimum" : 0,
"maximum": 2048,
"default" : 0,
+ "append" : "ms",
"propertyOrder" : 5
},
"continuousOutput" :
@@ -427,12 +432,14 @@
},
"additionalProperties" : false
},
- "grabber-v4l2" :
+ "grabberV4L2" :
{
"type":"array",
+ "title" : "USB Grabber",
"items":
{
"type" : "object",
+ "title" : "USB Grabber",
"properties" :
{
"enable" :
@@ -469,6 +476,7 @@
"type" : "integer",
"title" : "Width",
"default" : -1,
+ "append" : "Pixel",
"propertyOrder" : 5
},
"height" :
@@ -476,6 +484,7 @@
"type" : "integer",
"title" : "Height",
"default" : -1,
+ "append" : "Pixel",
"propertyOrder" : 6
},
"frameDecimation" :
@@ -520,6 +529,7 @@
"title" : "Crop left",
"minimum" : 0,
"default" : 0,
+ "append" : "Pixel",
"propertyOrder" : 12
},
"cropRight" :
@@ -528,6 +538,7 @@
"title" : "Crop right",
"minimum" : 0,
"default" : 0,
+ "append" : "Pixel",
"propertyOrder" : 13
},
"cropTop" :
@@ -536,6 +547,7 @@
"title" : "Crop top",
"minimum" : 0,
"default" : 0,
+ "append" : "Pixel",
"propertyOrder" : 14
},
"cropBottom" :
@@ -544,6 +556,7 @@
"title" : "Crop bottom",
"minimum" : 0,
"default" : 0,
+ "append" : "Pixel",
"propertyOrder" : 15
},
"redSignalThreshold" :
@@ -553,6 +566,7 @@
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.1,
+ "append" : "%",
"propertyOrder" : 16
},
"greenSignalThreshold" :
@@ -562,6 +576,7 @@
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.1,
+ "append" : "%",
"propertyOrder" : 17
},
"blueSignalThreshold" :
@@ -571,6 +586,7 @@
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.1,
+ "append" : "%",
"propertyOrder" : 18
}
},
@@ -601,20 +617,23 @@
{
"type" : "integer",
"title" : "Width",
- "default" : 96
+ "default" : 96,
+ "append" : "Pixel"
},
"height" :
{
"type" : "integer",
"title" : "Height",
- "default" : 96
+ "default" : 96,
+ "append" : "Pixel"
},
"frequency_Hz" :
{
"type" : "integer",
"title" : "Frequency",
"minimum" : 0,
- "default" : 10
+ "default" : 10,
+ "append" : "Hz"
},
"priority" :
{
@@ -628,28 +647,32 @@
"type" : "integer",
"title" : "Crop left",
"minimum" : 0,
- "default" : 0
+ "default" : 0,
+ "append" : "Pixel"
},
"cropRight" :
{
"type" : "integer",
"title" : "Crop right",
"minimum" : 0,
- "default" : 0
+ "default" : 0,
+ "append" : "Pixel"
},
"cropTop" :
{
"type" : "integer",
"title" : "Crop top",
"minimum" : 0,
- "default" : 0
+ "default" : 0,
+ "append" : "Pixel"
},
"cropBottom" :
{
"type" : "integer",
"title" : "Crop bottom",
"minimum" : 0,
- "default" : 0
+ "default" : 0,
+ "append" : "Pixel"
},
"useXGetImage" :
{
@@ -707,6 +730,7 @@
"minimum" : 0.0,
"maximum" : 1.0,
"default" : 0.05,
+ "append" : "%",
"propertyOrder" : 2
},
"unknownFrameCnt" :
diff --git a/libsrc/hyperion/resource.qrc b/libsrc/hyperion/resource.qrc
index 4181fbe8..efc3930b 100644
--- a/libsrc/hyperion/resource.qrc
+++ b/libsrc/hyperion/resource.qrc
@@ -1,5 +1,6 @@
hyperion.schema.json
+ ../../config/hyperion.config.json.default
diff --git a/libsrc/leddevice/schemas/schema-adalight.json b/libsrc/leddevice/schemas/schema-adalight.json
index 4755a475..8dacc228 100644
--- a/libsrc/leddevice/schemas/schema-adalight.json
+++ b/libsrc/leddevice/schemas/schema-adalight.json
@@ -17,6 +17,7 @@
"type": "integer",
"title":"Delay after connect",
"default": 250,
+ "append" : "ms",
"propertyOrder" : 3
}
},
diff --git a/libsrc/leddevice/schemas/schema-adalightapa102.json b/libsrc/leddevice/schemas/schema-adalightapa102.json
index 4755a475..8dacc228 100644
--- a/libsrc/leddevice/schemas/schema-adalightapa102.json
+++ b/libsrc/leddevice/schemas/schema-adalightapa102.json
@@ -17,6 +17,7 @@
"type": "integer",
"title":"Delay after connect",
"default": 250,
+ "append" : "ms",
"propertyOrder" : 3
}
},
diff --git a/libsrc/leddevice/schemas/schema-atmo.json b/libsrc/leddevice/schemas/schema-atmo.json
index 4755a475..8dacc228 100644
--- a/libsrc/leddevice/schemas/schema-atmo.json
+++ b/libsrc/leddevice/schemas/schema-atmo.json
@@ -17,6 +17,7 @@
"type": "integer",
"title":"Delay after connect",
"default": 250,
+ "append" : "ms",
"propertyOrder" : 3
}
},
diff --git a/libsrc/leddevice/schemas/schema-philipshue.json b/libsrc/leddevice/schemas/schema-philipshue.json
index 8c48bafa..8b338e59 100644
--- a/libsrc/leddevice/schemas/schema-philipshue.json
+++ b/libsrc/leddevice/schemas/schema-philipshue.json
@@ -23,8 +23,9 @@
},
"transitiontime": {
"type": "integer",
- "title":"Transistion time (x100ms)",
+ "title":"Transistion time",
"default" : 1,
+ "append" : "x100ms",
"propertyOrder" : 4
},
"switchOffOnBlack": {
diff --git a/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp b/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp
index eea0dfa5..3eeea2ad 100644
--- a/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp
+++ b/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp
@@ -109,7 +109,7 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
else if (attribute == "id")
; // references have already been collected
else if (attribute == "title" || attribute == "description" || attribute == "default" || attribute == "format"
- || attribute == "defaultProperties" || attribute == "propertyOrder")
+ || attribute == "defaultProperties" || attribute == "propertyOrder" || attribute == "append")
; // nothing to do.
else
{
diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp
index cc91a63e..ab113efe 100644
--- a/src/hyperion-aml/hyperion-aml.cpp
+++ b/src/hyperion-aml/hyperion-aml.cpp
@@ -34,14 +34,14 @@ int main(int argc, char ** argv)
// create the option parser and initialize all parser
Parser parser("AmLogic capture application for Hyperion");
- IntOption & argFps = parser.add ('f', "framerate", "Capture frame rate [default: %1]", "10");
- IntOption & argWidth = parser.add (0x0, "width", "Width of the captured image [default: %1]", "160", 160, 4096);
- IntOption & argHeight = parser.add (0x0, "height", "Height of the captured image [default: %1]", "160", 160, 4096);
- BooleanOption & argScreenshot = parser.add (0x0, "screenshot", "Take a single screenshot, save it to file and quit");
- Option & argAddress = parser.add