Merge remote-tracking branch 'hyperion-project/master' into userauthapi

This commit is contained in:
brindosch 2019-08-30 00:15:31 +02:00
commit 1e4c29dacb
19 changed files with 826 additions and 694 deletions

View File

@ -501,6 +501,212 @@ of the input file used when generating it. This code is not
standalone and requires a support library to be linked with it. This
support library is itself covered by the above license.
======
Roboto
======
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==========
rpi_ws281x
==========
@ -537,4 +743,4 @@ Copyright (C) 2012-2013 Matthias Bolte <matthias@tinkerforge.com>
Copyright (C) 2011 Olaf Lüke <olaf@tinkerforge.com>
Redistribution and use in source and binary forms of this file,
with or without modification, are permitted.
with or without modification, are permitted.

View File

@ -24,12 +24,12 @@ function createLedPreview(leds, origin){
$('#previewcreator').html($.i18n('conf_leds_layout_preview_originMA'));
$('#leds_preview').css("padding-top", "100%");
}
$('#previewledcount').html($.i18n('conf_leds_layout_preview_totalleds', leds.length));
$('#previewledpower').html($.i18n('conf_leds_layout_preview_ledpower', ((leds.length * 0.06)*1.1).toFixed(1)));
$('.st_helper').css("border", "8px solid grey");
var canvas_height = $('#leds_preview').innerHeight();
var canvas_width = $('#leds_preview').innerWidth();
@ -39,17 +39,17 @@ function createLedPreview(leds, origin){
var led = leds[idx];
var led_id='ledc_'+[idx];
var bgcolor = "background-color:hsl("+(idx*360/leds.length)+",100%,50%);";
var pos = "left:"+(led.hscan.minimum * canvas_width)+"px;"+
"top:"+(led.vscan.minimum * canvas_height)+"px;"+
"width:"+((led.hscan.maximum-led.hscan.minimum) * (canvas_width-1))+"px;"+
"height:"+((led.vscan.maximum-led.vscan.minimum) * (canvas_height-1))+"px;";
leds_html += '<div id="'+led_id+'" class="led" style="'+bgcolor+pos+'" title="'+led.index+'"><span id="'+led_id+'_num" class="led_prev_num">'+led.index+'</span></div>';
var pos = "left:"+(led.h.min * canvas_width)+"px;"+
"top:"+(led.v.min * canvas_height)+"px;"+
"width:"+((led.h.max-led.h.min) * (canvas_width-1))+"px;"+
"height:"+((led.v.max-led.v.min) * (canvas_height-1))+"px;";
leds_html += '<div id="'+led_id+'" class="led" style="'+bgcolor+pos+'" title="'+idx+'"><span id="'+led_id+'_num" class="led_prev_num">'+idx+'</span></div>';
}
$('#leds_preview').html(leds_html);
$('#ledc_0').css({"background-color":"black","z-index":"12"});
$('#ledc_1').css({"background-color":"grey","z-index":"11"});
$('#ledc_2').css({"background-color":"#A9A9A9","z-index":"10"});
if($('#leds_prev_toggle_num').hasClass('btn-success'))
$('.led_prev_num').css("display", "inline");
@ -65,14 +65,14 @@ function createClassicLeds(){
var ledsgpos = parseInt($("#ip_cl_gpos").val());
var position = parseInt($("#ip_cl_position").val());
var reverse = $("#ip_cl_reverse").is(":checked");
//advanced values
var ledsVDepth = parseInt($("#ip_cl_vdepth").val())/100;
var ledsHDepth = parseInt($("#ip_cl_hdepth").val())/100;
var edgeVGap = parseInt($("#ip_cl_edgegap").val())/100/2;
//var cornerVGap = parseInt($("#ip_cl_cornergap").val())/100/2;
var overlap = $("#ip_cl_overlap").val()/4000;
//helper
var edgeHGap = edgeVGap/(16/9);
//var cornerHGap = cornerVGap/(16/9);
@ -83,15 +83,15 @@ function createClassicLeds(){
var Hdiff = Hmax-Hmin;
var Vdiff = Vmax-Vmin;
var ledArray = [];
function createFinalArray(array){
finalLedArray = [];
for(var i = 0; i<array.length; i++){
var hmin = array[i].hscan.minimum;
var hmax = array[i].hscan.maximum;
var vmin = array[i].vscan.minimum;
var vmax = array[i].vscan.maximum;
finalLedArray[i] = { "index" : i, "hscan": { "maximum" : hmax, "minimum" : hmin }, "vscan": { "maximum": vmax, "minimum": vmin}}
var hmin = array[i].h.min;
var hmax = array[i].h.max;
var vmin = array[i].v.min;
var vmax = array[i].v.max;
finalLedArray[i] = { "h": { "max" : hmax, "min" : hmin }, "v": { "max": vmax, "min": vmin}}
}
createLedPreview(finalLedArray, 'classic');
}
@ -111,7 +111,7 @@ function createClassicLeds(){
return array;
}
}
function valScan(val)
{
if(val > 1)
@ -120,7 +120,7 @@ function createClassicLeds(){
return 0;
return val;
}
function ovl(scan,val)
{
if(scan == "+")
@ -128,15 +128,15 @@ function createClassicLeds(){
else
return valScan(val -= overlap);
}
function createLedArray(hmin, hmax, vmin, vmax){
hmin = round(hmin);
hmax = round(hmax);
vmin = round(vmin);
vmax = round(vmax);
ledArray.push( { "hscan" : { "minimum" : hmin, "maximum" : hmax }, "vscan": { "minimum": vmin, "maximum": vmax }} );
ledArray.push( { "h" : { "min" : hmin, "max" : hmax }, "v": { "min": vmin, "max": vmax }} );
}
function createTopLeds(){
var step=(Hmax-Hmin)/ledstop;
//if(cornerVGap != '0')
@ -148,9 +148,9 @@ function createClassicLeds(){
var hmin = ovl("-",(Hdiff/ledstop*Number([i]))+edgeHGap);
var hmax = ovl("+",(Hdiff/ledstop*Number([i]))+step+edgeHGap);
createLedArray(hmin, hmax, vmin, vmax);
}
}
}
function createLeftLeds(){
var step=(Vmax-Vmin)/ledsleft;
//if(cornerVGap != '0')
@ -164,7 +164,7 @@ function createClassicLeds(){
createLedArray(hmin, hmax, vmin, vmax);
}
}
function createRightLeds(){
var step=(Vmax-Vmin)/ledsright;
//if(cornerVGap != '0')
@ -175,15 +175,15 @@ function createClassicLeds(){
for (var i = 0; i<ledsright; i++){
var vmin = ovl("-",(Vdiff/ledsright*Number([i]))+edgeVGap);
var vmax = ovl("+",(Vdiff/ledsright*Number([i]))+step+edgeVGap);
createLedArray(hmin, hmax, vmin, vmax);
createLedArray(hmin, hmax, vmin, vmax);
}
}
function createBottomLeds(){
var step=(Hmax-Hmin)/ledsbottom;
//if(cornerVGap != '0')
// step=(Hmax-Hmin-(cornerHGap*2))/ledsbottom;
var vmax=Vmax;
var vmin=vmax-ledsHDepth;
for (var i = ledsbottom-1; i>-1; i--){
@ -192,7 +192,7 @@ function createClassicLeds(){
createLedArray(hmin, hmax, vmin, vmax);
}
}
createTopLeds();
createRightLeds();
createBottomLeds();
@ -205,25 +205,25 @@ function createClassicLeds(){
$('#ip_cl_ledsgpos').val(mpos);
ledsgpos = mpos;
}
//check led gap length
if(ledsglength >= ledArray.length)
{
$('#ip_cl_ledsglength').val(ledArray.length-1);
ledsglength = ledArray.length-ledsglength-1;
}
if(ledsglength != 0){
ledArray.splice(ledsgpos, ledsglength);
}
if (position != 0){
rotateArray(ledArray, position);
}
if (reverse)
ledArray.reverse();
createFinalArray(ledArray);
}
@ -239,7 +239,6 @@ function createMatrixLeds(){
var start = $("#ip_ma_start").val();
var parallel = false
var index = 0
var leds = []
var hblock = 1.0 / ledshoriz
var vblock = 1.0 / ledsvert
@ -250,11 +249,10 @@ function createMatrixLeds(){
/**
* Adds led to the hyperion config led array
* @param {Number} index Index of the led
* @param {Number} x Horizontal position in matrix
* @param {Number} y Vertical position in matrix
*/
function addLed (index, x, y) {
function addLed (x, y) {
var hscanMin = x * hblock
var hscanMax = (x + 1) * hblock
var vscanMin = y * vblock
@ -264,16 +262,15 @@ function createMatrixLeds(){
hscanMax = round(hscanMax);
vscanMin = round(vscanMin);
vscanMax = round(vscanMax);
leds.push({
index: index,
hscan: {
minimum: hscanMin,
maximum: hscanMax
h: {
min: hscanMin,
max: hscanMax
},
vscan: {
minimum: vscanMin,
maximum: vscanMax
v: {
min: vscanMin,
max: vscanMax
}
})
}
@ -291,8 +288,7 @@ function createMatrixLeds(){
for (y = startY; downward && y <= endY || !downward && y >= endY; y += downward ? 1 : -1) {
for (x = startX; forward && x <= endX || !forward && x >= endX; x += forward ? 1 : -1) {
addLed(index, x, y)
index++
addLed(x, y)
}
if (!parallel) {
forward = !forward
@ -309,7 +305,7 @@ function createMatrixLeds(){
$(document).ready(function() {
// translate
performTranslation();
//add intros
if(window.showOptHelp)
{
@ -317,9 +313,9 @@ $(document).ready(function() {
createHintH("intro", $.i18n('conf_leds_layout_intro'), "layout_intro");
$('#led_vis_help').html('<div><div class="led_ex" style="background-color:black;margin-right:5px;margin-top:3px"></div><div style="display:inline-block;vertical-align:top">'+$.i18n('conf_leds_layout_preview_l1')+'</div></div><div class="led_ex" style="background-color:grey;margin-top:3px;margin-right:2px"></div><div class="led_ex" style="background-color: rgb(169, 169, 169);margin-right:5px;margin-top:3px;"></div><div style="display:inline-block;vertical-align:top">'+$.i18n('conf_leds_layout_preview_l2')+'</div>');
}
var slConfig = window.serverConfig.ledConfig;
//restore ledConfig
for(var key in slConfig)
{
@ -343,7 +339,7 @@ $(document).ready(function() {
}
setTimeout(requestWriteConfig, 100, {ledConfig});
}
// check access level and adjust ui
if(storedAccess == "default")
{
@ -357,10 +353,10 @@ $(document).ready(function() {
$('#btn_ma_save').toggle(false);
$('#btn_cl_save').toggle(false);
}
//Wiki link
$('#leds_wl').append('<p style="font-weight:bold">'+$.i18n('general_wiki_moreto',$.i18n('conf_leds_nav_label_ledlayout'))+buildWL("user/moretopics/ledarea","Wiki")+'</p>');
// bind change event to all inputs
$('.ledCLconstr').bind("change", function() {
valValue(this.id,this.value,this.min,this.max);
@ -373,7 +369,7 @@ $(document).ready(function() {
});
// v4 of json schema with diff required assignment - remove when hyperion schema moved to v4
var ledschema = {"items":{"additionalProperties":false,"required":["hscan","vscan","index"],"properties":{"clone":{"type":"integer"},"colorOrder":{"enum":["rgb","bgr","rbg","brg","gbr","grb"],"type":"string"},"hscan":{"additionalProperties":false,"properties":{"maximum":{"maximum":1,"minimum":0,"type":"number"},"minimum":{"maximum":1,"minimum":0,"type":"number"}},"type":"object"},"index":{"type":"integer"},"vscan":{"additionalProperties":false,"properties":{"maximum":{"maximum":1,"minimum":0,"type":"number"},"minimum":{"maximum":1,"minimum":0,"type":"number"}},"type":"object"}},"type":"object"},"type":"array"};
var ledschema = {"items":{"additionalProperties":false,"required":["h","v"],"properties":{"colorOrder":{"enum":["rgb","bgr","rbg","brg","gbr","grb"],"type":"string"},"h":{"additionalProperties":false,"properties":{"max":{"maximum":1,"minimum":0,"type":"number"},"min":{"maximum":1,"minimum":0,"type":"number"}},"type":"object"},"v":{"additionalProperties":false,"properties":{"max":{"maximum":1,"minimum":0,"type":"number"},"min":{"maximum":1,"minimum":0,"type":"number"}},"type":"object"}},"type":"object"},"type":"array"};
//create jsonace editor
var aceEdt = new JSONACEEditor(document.getElementById("aceedit"),{
mode: 'code',
@ -387,7 +383,7 @@ $(document).ready(function() {
{
success = false;
}
if(success)
{
$('#leds_custom_updsim').attr("disabled", false);
@ -400,7 +396,7 @@ $(document).ready(function() {
}
}
}, window.serverConfig.leds);
//TODO: HACK! No callback for schema validation - Add it!
setInterval(function(){
if($('#aceedit table').hasClass('jsoneditor-text-errors'))
@ -409,23 +405,23 @@ $(document).ready(function() {
$('#leds_custom_save').attr("disabled", true);
}
},1000);
$('.jsoneditor-menu').toggle();
// leds to finalLedArray
finalLedArray = window.serverConfig.leds;
// cl/ma leds push to textfield
$('#btn_cl_generate, #btn_ma_generate').off().on("click", function(e) {
if(e.currentTarget.id == "btn_cl_generate")
$('#collapse1').collapse('hide');
else
$('#collapse2').collapse('hide');
aceEdt.set(finalLedArray);
$('#collapse4').collapse('show');
});
// create and update editor
$("#leddevices").off().on("change", function() {
var generalOptions = window.serverSchema.properties.device;
@ -437,7 +433,7 @@ $(document).ready(function() {
generalOptions : generalOptions,
specificOptions : specificOptions,
});
var values_general = {};
var values_specific = {};
var isCurrentDevice = (window.serverInfo.ledDevices.active == $(this).val());
@ -457,10 +453,10 @@ $(document).ready(function() {
conf_editor.getEditor("root.specificOptions").setValue( values_specific );
};
// change save button state based on validation result
conf_editor.validate().length ? $('#btn_submit_controller').attr('disabled', true) : $('#btn_submit_controller').attr('disabled', false);
// led controller sepecific wizards
if($(this).val() == "philipshue")
{
@ -473,7 +469,7 @@ $(document).ready(function() {
$('#btn_led_device_wiz').off();
}
});
// create led device selection
var ledDevices = window.serverInfo.ledDevices.available;
var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'ws2812spi'];
@ -481,14 +477,14 @@ $(document).ready(function() {
var devRPiGPIO = ['piblaster'];
var devNET = ['atmoorb', 'fadecandy', 'philipshue', 'nanoleaf', 'tinkerforge', 'tpm2net', 'udpe131', 'udpartnet', 'udph801', 'udpraw'];
var devUSB = ['adalight', 'dmx', 'atmo', 'hyperionusbasp', 'lightpack', 'multilightpack', 'paintpack', 'rawhid', 'sedu', 'tpm2', 'karate'];
var optArr = [[]];
optArr[1]=[];
optArr[2]=[];
optArr[3]=[];
optArr[4]=[];
optArr[5]=[];
for (var idx=0; idx<ledDevices.length; idx++)
{
if($.inArray(ledDevices[idx], devRPiSPI) != -1)
@ -504,7 +500,7 @@ $(document).ready(function() {
else
optArr[5].push(ledDevices[idx]);
}
$("#leddevices").append(createSel(optArr[0], $.i18n('conf_leds_optgroup_RPiSPI')));
$("#leddevices").append(createSel(optArr[1], $.i18n('conf_leds_optgroup_RPiPWM')));
$("#leddevices").append(createSel(optArr[2], $.i18n('conf_leds_optgroup_RPiGPIO')));
@ -518,13 +514,13 @@ $(document).ready(function() {
$("#leds_custom_updsim").off().on("click", function() {
createLedPreview(aceEdt.get(), 'text');
});
// save led config and saveValues - passing textfield
$("#btn_ma_save, #btn_cl_save").off().on("click", function() {
requestWriteConfig({"leds" :finalLedArray});
saveValues();
});
// save led config from textfield
$("#leds_custom_save").off().on("click", function() {
requestWriteConfig(JSON.parse('{"leds" :'+aceEdt.getText()+'}'));
@ -536,13 +532,13 @@ $(document).ready(function() {
$('.led_prev_num').toggle();
toggleClass('#leds_prev_toggle_num', "btn-danger", "btn-success");
});
// open checklist
$('#leds_prev_checklist').off().on("click", function() {
var liList = [$.i18n('conf_leds_layout_checkp1'),$.i18n('conf_leds_layout_checkp3'),$.i18n('conf_leds_layout_checkp2'),$.i18n('conf_leds_layout_checkp4')];
var ul = document.createElement("ul");
ul.className = "checklist"
for(var i = 0; i<liList.length; i++)
{
var li = document.createElement("li");
@ -551,7 +547,7 @@ $(document).ready(function() {
}
showInfoDialog('checklist', "", ul);
});
// nav
$('#leds_cfg_nav a[data-toggle="tab"]').off().on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href") // activated tab
@ -561,13 +557,13 @@ $(document).ready(function() {
ledsCustomCfgInitialized = true;
}
});
// save led device config
$("#btn_submit_controller").off().on("click", function(event) {
var ledDevice = $("#leddevices").val();
var result = {device:{}};
var general = conf_editor.getEditor("root.generalOptions").getValue();
var specific = conf_editor.getEditor("root.specificOptions").getValue();
for(var key in general){

View File

@ -22,7 +22,7 @@ $(document).ready(function() {
for(var idx=0; idx<leds.length; idx++)
{
var led = leds[idx];
twoDPaths.push( build2DPath(led.hscan.minimum * canvas_width, led.vscan.minimum * canvas_height, (led.hscan.maximum-led.hscan.minimum) * canvas_width, (led.vscan.maximum-led.vscan.minimum) * canvas_height, 5) );
twoDPaths.push( build2DPath(led.h.min * canvas_width, led.v.min * canvas_height, (led.h.max-led.h.min) * canvas_width, (led.v.max-led.v.min) * canvas_height, 5) );
}
}
@ -131,18 +131,23 @@ $(document).ready(function() {
return;
var useColor = false;
var cPos = 0;
ledsCanvasNodeCtx.clear();
if(typeof colors != "undefined")
useColor = true;
// check size of ledcolors with leds length
if(colors && colors.length/3 < leds.length)
return;
for(var idx=0; idx<leds.length; idx++)
{
var led = leds[idx];
// can be used as fallback when Path2D is not available
//roundRect(ledsCanvasNodeCtx, led.hscan.minimum * canvas_width, led.vscan.minimum * canvas_height, (led.hscan.maximum-led.hscan.minimum) * canvas_width, (led.vscan.maximum-led.vscan.minimum) * canvas_height, 4, true, colors[idx])
//ledsCanvasNodeCtx.fillRect(led.hscan.minimum * canvas_width, led.vscan.minimum * canvas_height, (led.hscan.maximum-led.hscan.minimum) * canvas_width, (led.vscan.maximum-led.vscan.minimum) * canvas_height);
ledsCanvasNodeCtx.fillStyle = (useColor) ? "rgba("+colors[idx].red+","+colors[idx].green+","+colors[idx].blue+",0.9)" : "hsl("+(idx*360/leds.length)+",100%,50%)";
//roundRect(ledsCanvasNodeCtx, led.h.min * canvas_width, led.v.min * canvas_height, (led.h.max-led.h.min) * canvas_width, (led.v.max-led.v.min) * canvas_height, 4, true, colors[idx])
//ledsCanvasNodeCtx.fillRect(led.h.min * canvas_width, led.v.min * canvas_height, (led.h.max-led.h.min) * canvas_width, (led.v.max-led.v.min) * canvas_height);
ledsCanvasNodeCtx.fillStyle = (useColor) ? "rgba("+colors[cPos]+","+colors[cPos+1]+","+colors[cPos+2]+",0.9)" : "hsl("+(idx*360/leds.length)+",100%,50%)";
ledsCanvasNodeCtx.fill(twoDPaths[idx]);
ledsCanvasNodeCtx.stroke(twoDPaths[idx]);
@ -150,8 +155,11 @@ $(document).ready(function() {
{
ledsCanvasNodeCtx.fillStyle = "blue";
ledsCanvasNodeCtx.textAlign = "center";
ledsCanvasNodeCtx.fillText(idx, (led.hscan.minimum * canvas_width) + ( ((led.hscan.maximum-led.hscan.minimum) * canvas_width) / 2), (led.vscan.minimum * canvas_height) + ( ((led.vscan.maximum-led.vscan.minimum) * canvas_height) / 2));
ledsCanvasNodeCtx.fillText(idx, (led.h.min * canvas_width) + ( ((led.h.max-led.h.min) * canvas_width) / 2), (led.v.min * canvas_height) + ( ((led.v.max-led.v.min) * canvas_height) / 2));
}
// increment colorsPosition
cPos += 3;
}
}

View File

@ -518,11 +518,11 @@ $('#btn_wizard_colorcalibration').off().on('click', startWizardCC);
var hueIPs = [];
var hueIPsinc = 0;
var lightIDs = null;
var huePosTop = {hscan: {maximum: 0.85,minimum: 0.15},index: 0,vscan: {maximum: 0.2,minimum: 0}};
var huePosBottom = {hscan: {maximum: 0.85,minimum: 0.15},index: 2,vscan: {maximum: 1,minimum: 0.8}};
var huePosLeft = {hscan: {maximum: 0.15,minimum: 0},index: 1,vscan: {maximum: 0.85,minimum: 0.15}};
var huePosRight = {hscan: {maximum: 1,minimum: 0.85},index: 3,vscan: {maximum: 0.85,minimum: 0.15}};
var huePosEntire = {hscan: {maximum: 1.0,minimum: 0.0},index: 0,vscan: {maximum: 1.0,minimum: 0.0}};
var huePosTop = {h: {max: 0.85, min: 0.15}, v: {max: 0.2, min: 0}};
var huePosBottom = {h: {max: 0.85, min: 0.15}, v: {max: 1, min: 0.8}};
var huePosLeft = {h: {max: 0.15, min: 0}, v: {max: 0.85, min: 0.15}};
var huePosRight = {h: {max: 1, min: 0.85}, v: {max: 0.85, min: 0.15}};
var huePosEntire = {h: {max: 1.0, min: 0.0}, v: {max: 1.0, min: 0.0}};
function startWizardPhilipsHue()
{
@ -620,9 +620,9 @@ function checkBridgeResult(reply){
}
};
function assignHuePos(id, pos, inc)
{
var i = null;
function assignHuePos(id, pos)
{
var i = null;
if(pos == "top")
i = huePosTop;
@ -635,9 +635,8 @@ function assignHuePos(id, pos, inc)
else
i = huePosEntire;
i.index = inc;
return i;
}
return i;
}
function identHueId(id, off)
{
@ -706,23 +705,14 @@ function beginWizardHue()
checkHueBridge(checkUserResult,$('#user').val() ? $('#user').val() : "newdeveloper");
});
$('#wiz_hue_create_user').off().on('click',function() {
createHueUser();
});
$('#btn_wiz_save').off().on("click", function(){
var hueLedConfig = [];
var finalLightIds = [];
//create hue led config
var incC = 0;
for(var key in lightIDs)
{
if($('#hue_'+key).val() != "disabled")
//create hue led config
for(var key in lightIDs)
{
hueLedConfig.push(assignHuePos(key, $('#hue_'+key).val(), incC));
finalLightIds.push(parseInt(key));
incC++;
if($('#hue_'+key).val() != "disabled")
{
hueLedConfig.push(assignHuePos(key, $('#hue_'+key).val()));
finalLightIds.push(parseInt(key));
}
}
}
@ -774,17 +764,17 @@ function createHueUser()
connectionRetries--;
$("#connectionTime").html(connectionRetries);
if(connectionRetries == 0)
if(connectionRetries == 0)
{
abortConnection(UserInterval);
}
else
{
if (typeof r[0].error != 'undefined')
if (typeof r[0].error != 'undefined')
{
console.log(connectionRetries+": link not pressed");
}
if (typeof r[0].success != 'undefined')
if (typeof r[0].success != 'undefined')
{
$('#wizp1').toggle(false);
$('#wizp2').toggle(true);

View File

@ -343,299 +343,271 @@
/// The configuration for each individual led. This contains the specification of the area
/// averaged of an input image for each led to determine its color. Each item in the list
/// contains the following fields:
/// * index: The index of the led. This determines its location in the string of leds; zero
/// being the first led.
/// * hscan: The fractional part of the image along the horizontal used for the averaging
/// (minimum and maximum inclusive)
/// * vscan: The fractional part of the image along the vertical used for the averaging
/// (minimum and maximum inclusive)
/// * h: The fractional part of the image along the horizontal used for the averaging
/// (min and max inclusive)
/// * v: The fractional part of the image along the vertical used for the averaging
/// (min and max inclusive)
"leds":
"leds":
[
{
"hscan": {
"maximum": 0.125,
"minimum": 0
"h": {
"max": 0.125,
"min": 0
},
"index": 0,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.25,
"minimum": 0.125
"h": {
"max": 0.25,
"min": 0.125
},
"index": 1,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.375,
"minimum": 0.25
"h": {
"max": 0.375,
"min": 0.25
},
"index": 2,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.5,
"minimum": 0.375
"h": {
"max": 0.5,
"min": 0.375
},
"index": 3,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.625,
"minimum": 0.5
"h": {
"max": 0.625,
"min": 0.5
},
"index": 4,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.75,
"minimum": 0.625
"h": {
"max": 0.75,
"min": 0.625
},
"index": 5,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.875,
"minimum": 0.75
"h": {
"max": 0.875,
"min": 0.75
},
"index": 6,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.875
"h": {
"max": 1,
"min": 0.875
},
"index": 7,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 8,
"vscan": {
"maximum": 0.2,
"minimum": 0
"v": {
"max": 0.2,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 9,
"vscan": {
"maximum": 0.4,
"minimum": 0.2
"v": {
"max": 0.4,
"min": 0.2
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 10,
"vscan": {
"maximum": 0.6,
"minimum": 0.4
"v": {
"max": 0.6,
"min": 0.4
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 11,
"vscan": {
"maximum": 0.8,
"minimum": 0.6
"v": {
"max": 0.8,
"min": 0.6
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 12,
"vscan": {
"maximum": 1,
"minimum": 0.8
"v": {
"max": 1,
"min": 0.8
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.875
"h": {
"max": 1,
"min": 0.875
},
"index": 13,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.875,
"minimum": 0.75
"h": {
"max": 0.875,
"min": 0.75
},
"index": 14,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.75,
"minimum": 0.625
"h": {
"max": 0.75,
"min": 0.625
},
"index": 15,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.625,
"minimum": 0.5
"h": {
"max": 0.625,
"min": 0.5
},
"index": 16,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.5,
"minimum": 0.375
"h": {
"max": 0.5,
"min": 0.375
},
"index": 17,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.375,
"minimum": 0.25
"h": {
"max": 0.375,
"min": 0.25
},
"index": 18,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.25,
"minimum": 0.125
"h": {
"max": 0.25,
"min": 0.125
},
"index": 19,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.125,
"minimum": 0
"h": {
"max": 0.125,
"min": 0
},
"index": 20,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 21,
"vscan": {
"maximum": 1,
"minimum": 0.8
"v": {
"max": 1,
"min": 0.8
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 22,
"vscan": {
"maximum": 0.8,
"minimum": 0.6
"v": {
"max": 0.8,
"min": 0.6
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 23,
"vscan": {
"maximum": 0.6,
"minimum": 0.4
"v": {
"max": 0.6,
"min": 0.4
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 24,
"vscan": {
"maximum": 0.4,
"minimum": 0.2
"v": {
"max": 0.4,
"min": 0.2
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 25,
"vscan": {
"maximum": 0.2,
"minimum": 0
"v": {
"max": 0.2,
"min": 0
}
}
]

View File

@ -204,289 +204,263 @@
"leds":
[
{
"hscan": {
"maximum": 0.125,
"minimum": 0
"h": {
"max": 0.125,
"min": 0
},
"index": 0,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.25,
"minimum": 0.125
"h": {
"max": 0.25,
"min": 0.125
},
"index": 1,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.375,
"minimum": 0.25
"h": {
"max": 0.375,
"min": 0.25
},
"index": 2,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.5,
"minimum": 0.375
"h": {
"max": 0.5,
"min": 0.375
},
"index": 3,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.625,
"minimum": 0.5
"h": {
"max": 0.625,
"min": 0.5
},
"index": 4,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.75,
"minimum": 0.625
"h": {
"max": 0.75,
"min": 0.625
},
"index": 5,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 0.875,
"minimum": 0.75
"h": {
"max": 0.875,
"min": 0.75
},
"index": 6,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.875
"h": {
"max": 1,
"min": 0.875
},
"index": 7,
"vscan": {
"maximum": 0.08,
"minimum": 0
"v": {
"max": 0.08,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 8,
"vscan": {
"maximum": 0.2,
"minimum": 0
"v": {
"max": 0.2,
"min": 0
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 9,
"vscan": {
"maximum": 0.4,
"minimum": 0.2
"v": {
"max": 0.4,
"min": 0.2
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 10,
"vscan": {
"maximum": 0.6,
"minimum": 0.4
"v": {
"max": 0.6,
"min": 0.4
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 11,
"vscan": {
"maximum": 0.8,
"minimum": 0.6
"v": {
"max": 0.8,
"min": 0.6
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.95
"h": {
"max": 1,
"min": 0.95
},
"index": 12,
"vscan": {
"maximum": 1,
"minimum": 0.8
"v": {
"max": 1,
"min": 0.8
}
},
{
"hscan": {
"maximum": 1,
"minimum": 0.875
"h": {
"max": 1,
"min": 0.875
},
"index": 13,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.875,
"minimum": 0.75
"h": {
"max": 0.875,
"min": 0.75
},
"index": 14,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.75,
"minimum": 0.625
"h": {
"max": 0.75,
"min": 0.625
},
"index": 15,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.625,
"minimum": 0.5
"h": {
"max": 0.625,
"min": 0.5
},
"index": 16,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.5,
"minimum": 0.375
"h": {
"max": 0.5,
"min": 0.375
},
"index": 17,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.375,
"minimum": 0.25
"h": {
"max": 0.375,
"min": 0.25
},
"index": 18,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.25,
"minimum": 0.125
"h": {
"max": 0.25,
"min": 0.125
},
"index": 19,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.125,
"minimum": 0
"h": {
"max": 0.125,
"min": 0
},
"index": 20,
"vscan": {
"maximum": 1,
"minimum": 0.92
"v": {
"max": 1,
"min": 0.92
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 21,
"vscan": {
"maximum": 1,
"minimum": 0.8
"v": {
"max": 1,
"min": 0.8
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 22,
"vscan": {
"maximum": 0.8,
"minimum": 0.6
"v": {
"max": 0.8,
"min": 0.6
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 23,
"vscan": {
"maximum": 0.6,
"minimum": 0.4
"v": {
"max": 0.6,
"min": 0.4
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 24,
"vscan": {
"maximum": 0.4,
"minimum": 0.2
"v": {
"max": 0.4,
"min": 0.2
}
},
{
"hscan": {
"maximum": 0.05,
"minimum": 0
"h": {
"max": 0.05,
"min": 0
},
"index": 25,
"vscan": {
"maximum": 0.2,
"minimum": 0
"v": {
"max": 0.2,
"min": 0
}
}
]

View File

@ -2,21 +2,17 @@
// hyperion includes
#include <utils/Logger.h>
#include <utils/jsonschema/QJsonSchemaChecker.h>
#include <utils/Components.h>
#include <hyperion/Hyperion.h>
#include <hyperion/HyperionIManager.h>
// qt includes
#include <QJsonObject>
#include <QMutex>
#include <QString>
// HyperionInstanceManager
#include <hyperion/HyperionIManager.h>
class QTimer;
class JsonCB;
class AuthManager;
class HyperionIManager;
class JsonAPI : public QObject
{
@ -43,15 +39,20 @@ public:
public slots:
///
/// @brief is called whenever the current Hyperion instance pushes new led raw values (if enabled)
/// @param ledColors The current ledColors
/// @brief Is called whenever the current Hyperion instance pushes new led raw values (if enabled)
/// @param ledColors The current led colors
///
void streamLedcolorsUpdate(const std::vector<ColorRgb>& ledColors);
/// push images whenever hyperion emits (if enabled)
///
/// @brief Push images whenever hyperion emits (if enabled)
/// @param image The current image
///
void setImage(const Image<ColorRgb> & image);
/// process and push new log messages from logger (if enabled)
///
/// @brief Process and push new log messages from logger (if enabled)
///
void incommingLogMessage(const Logger::T_LOG_MESSAGE&);
private slots:
@ -133,17 +134,23 @@ private:
/// flag to determine state of log streaming
bool _streaming_logging_activated;
/// mutex to determine state of image streaming
QMutex _image_stream_mutex;
/// timer for live video refresh
QTimer* _imageStreamTimer;
/// mutex to determine state of led streaming
QMutex _led_stream_mutex;
/// image stream connection handle
QMetaObject::Connection _imageStreamConnection;
/// timeout for live video refresh
volatile qint64 _image_stream_timeout;
/// the current streaming image
Image<ColorRgb> _currentImage;
/// timeout for led color refresh
volatile qint64 _led_stream_timeout;
/// timer for led color refresh
QTimer* _ledStreamTimer;
/// led stream connection handle
QMetaObject::Connection _ledStreamConnection;
/// the current streaming led values
std::vector<ColorRgb> _currentLedValues;
///
/// @brief Handle the switches of Hyperion instances

View File

@ -489,9 +489,6 @@ private:
/// The specifiation of the led frame construction and picture integration
LedString _ledString;
/// specifiation of cloned leds
LedString _ledStringClone;
/// Image Processor
ImageProcessor* _imageProcessor;

View File

@ -88,9 +88,6 @@ inline ColorOrder stringToColorOrder(const QString & order)
///
struct Led
{
/// The index of the led
unsigned index;
/// The minimum vertical scan line included for this leds color
double minX_frac;
/// The maximum vertical scan line included for this leds color
@ -99,8 +96,6 @@ struct Led
double minY_frac;
/// The maximum horizontal scan line included for this leds color
double maxY_frac;
/// id to clone
int clone;
/// the color order
ColorOrder colorOrder;
};

View File

@ -245,6 +245,17 @@ public:
return (ssize_t) _width * _height * sizeof(Pixel_T);
}
/// Clear the image
//
void clear()
{
_width = 1;
_height = 1;
_pixels = new Pixel_T[2];
_endOfPixels = _pixels + 1;
memset(_pixels, 0, _width * _height * sizeof(Pixel_T));
}
private:
///

View File

@ -192,86 +192,32 @@ namespace hyperion {
{
LedString ledString;
const QString deviceOrderStr = colorOrderToString(deviceOrder);
int maxLedId = ledConfigArray.size();
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& index = ledConfigArray[i].toObject();
Led led;
led.index = index["index"].toInt();
led.clone = index["clone"].toInt(-1);
if ( led.clone < -1 || led.clone >= maxLedId )
const QJsonObject& hscanConfig = ledConfigArray[i].toObject()["h"].toObject();
const QJsonObject& vscanConfig = ledConfigArray[i].toObject()["v"].toObject();
led.minX_frac = qMax(0.0, qMin(1.0, hscanConfig["min"].toDouble()));
led.maxX_frac = qMax(0.0, qMin(1.0, hscanConfig["max"].toDouble()));
led.minY_frac = qMax(0.0, qMin(1.0, vscanConfig["min"].toDouble()));
led.maxY_frac = qMax(0.0, qMin(1.0, vscanConfig["max"].toDouble()));
// Fix if the user swapped min and max
if (led.minX_frac > led.maxX_frac)
{
//Warning(_log, "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone);
led.clone = -1;
std::swap(led.minX_frac, led.maxX_frac);
}
if (led.minY_frac > led.maxY_frac)
{
std::swap(led.minY_frac, led.maxY_frac);
}
if ( led.clone < 0 )
{
const QJsonObject& hscanConfig = ledConfigArray[i].toObject()["hscan"].toObject();
const QJsonObject& vscanConfig = ledConfigArray[i].toObject()["vscan"].toObject();
led.minX_frac = qMax(0.0, qMin(1.0, hscanConfig["minimum"].toDouble()));
led.maxX_frac = qMax(0.0, qMin(1.0, hscanConfig["maximum"].toDouble()));
led.minY_frac = qMax(0.0, qMin(1.0, vscanConfig["minimum"].toDouble()));
led.maxY_frac = qMax(0.0, qMin(1.0, vscanConfig["maximum"].toDouble()));
// Fix if the user swapped min and max
if (led.minX_frac > led.maxX_frac)
{
std::swap(led.minX_frac, led.maxX_frac);
}
if (led.minY_frac > led.maxY_frac)
{
std::swap(led.minY_frac, led.maxY_frac);
}
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(index["colorOrder"].toString(deviceOrderStr));
ledString.leds().push_back(led);
}
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(index["colorOrder"].toString(deviceOrderStr));
ledString.leds().push_back(led);
}
// Make sure the leds are sorted (on their indices)
std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; });
return ledString;
}
LedString createLedStringClone(const QJsonArray& ledConfigArray, const ColorOrder deviceOrder)
{
LedString ledString;
const QString deviceOrderStr = colorOrderToString(deviceOrder);
int maxLedId = ledConfigArray.size();
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& index = ledConfigArray[i].toObject();
Led led;
led.index = index["index"].toInt();
led.clone = index["clone"].toInt(-1);
if ( led.clone < -1 || led.clone >= maxLedId )
{
//Warning(_log, "LED %d: clone index of %d is out of range, clone ignored", led.index, led.clone);
led.clone = -1;
}
if ( led.clone >= 0 )
{
//Debug(_log, "LED %d: clone from led %d", led.index, led.clone);
led.minX_frac = 0;
led.maxX_frac = 0;
led.minY_frac = 0;
led.maxY_frac = 0;
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(index["colorOrder"].toString(deviceOrderStr));
ledString.leds().push_back(led);
}
}
// Make sure the leds are sorted (on their indices)
std::sort(ledString.leds().begin(), ledString.leds().end(), [](const Led& lhs, const Led& rhs){ return lhs.index < rhs.index; });
return ledString;
}
@ -282,30 +228,26 @@ namespace hyperion {
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& index = ledConfigArray[i].toObject();
if (index["clone"].toInt(-1) < 0 )
const QJsonObject& hscanConfig = ledConfigArray[i].toObject()["h"].toObject();
const QJsonObject& vscanConfig = ledConfigArray[i].toObject()["v"].toObject();
double minX_frac = qMax(0.0, qMin(1.0, hscanConfig["min"].toDouble()));
double maxX_frac = qMax(0.0, qMin(1.0, hscanConfig["max"].toDouble()));
double minY_frac = qMax(0.0, qMin(1.0, vscanConfig["min"].toDouble()));
double maxY_frac = qMax(0.0, qMin(1.0, vscanConfig["max"].toDouble()));
// Fix if the user swapped min and max
if (minX_frac > maxX_frac)
{
const QJsonObject& hscanConfig = ledConfigArray[i].toObject()["hscan"].toObject();
const QJsonObject& vscanConfig = ledConfigArray[i].toObject()["vscan"].toObject();
double minX_frac = qMax(0.0, qMin(1.0, hscanConfig["minimum"].toDouble()));
double maxX_frac = qMax(0.0, qMin(1.0, hscanConfig["maximum"].toDouble()));
double minY_frac = qMax(0.0, qMin(1.0, vscanConfig["minimum"].toDouble()));
double maxY_frac = qMax(0.0, qMin(1.0, vscanConfig["maximum"].toDouble()));
// 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) );
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
@ -315,7 +257,7 @@ namespace hyperion {
midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
QSize gridSize( midPointsX.size(), midPointsY.size() );
//Debug(_log, "led layout grid: %dx%d", gridSize.width(), gridSize.height());
//Debug(_log, "LED layout grid size: %dx%d", gridSize.width(), gridSize.height());
return gridSize;
}

View File

@ -19,7 +19,9 @@
"type" : "bool"
},
"interval": {
"type" : "integer"
"type" : "integer",
"required" : false,
"minimum": 50
}
},

View File

@ -12,17 +12,16 @@
#include <QImage>
#include <QBuffer>
#include <QByteArray>
#include <QDateTime>
#include <QHostInfo>
#include <QMutexLocker>
#include <QTimer>
// hyperion includes
#include <utils/jsonschema/QJsonFactory.h>
#include <utils/SysInfo.h>
#include <HyperionConfig.h>
#include <utils/ColorSys.h>
#include <leddevice/LedDeviceWrapper.h>
#include <hyperion/GrabberWrapper.h>
#include <utils/jsonschema/QJsonFactory.h>
#include <utils/jsonschema/QJsonSchemaChecker.h>
#include <HyperionConfig.h>
#include <utils/SysInfo.h>
#include <utils/ColorSys.h>
#include <utils/Process.h>
#include <utils/JsonUtils.h>
@ -53,8 +52,8 @@ JsonAPI::JsonAPI(QString peerAddress, Logger* log, const bool& localConnection,
, _hyperion(nullptr)
, _jsonCB(new JsonCB(this))
, _streaming_logging_activated(false)
, _image_stream_timeout(0)
, _led_stream_timeout(0)
, _imageStreamTimer(new QTimer(this))
, _ledStreamTimer(new QTimer(this))
{
Q_INIT_RESOURCE(JSONRPC_schemas);
@ -1024,28 +1023,68 @@ void JsonAPI::handleLedColorsCommand(const QJsonObject& message, const QString &
// create result
QString subcommand = message["subcommand"].toString("");
// max 20 Hz (50ms) interval for streaming (default: 10 Hz (100ms))
qint64 streaming_interval = qMax(message["interval"].toInt(100), 50);
if (subcommand == "ledstream-start")
{
_streaming_leds_reply["success"] = true;
_streaming_leds_reply["command"] = command+"-ledstream-update";
_streaming_leds_reply["tan"] = tan;
connect(_hyperion, &Hyperion::rawLedColors, this, &JsonAPI::streamLedcolorsUpdate, Qt::UniqueConnection);
connect(_hyperion, &Hyperion::rawLedColors, this, [=](const std::vector<ColorRgb>& ledValues)
{
_currentLedValues = ledValues;
// necessary because Qt::UniqueConnection for lambdas does not work until 5.9
// see: https://bugreports.qt.io/browse/QTBUG-52438
if (!_ledStreamConnection)
_ledStreamConnection = connect(_ledStreamTimer, &QTimer::timeout, this, [=]()
{
emit streamLedcolorsUpdate(_currentLedValues);
}, Qt::UniqueConnection);
// start the timer
if (!_ledStreamTimer->isActive() || _ledStreamTimer->interval() != streaming_interval)
_ledStreamTimer->start(streaming_interval);
}, Qt::UniqueConnection);
}
else if (subcommand == "ledstream-stop")
{
disconnect(_hyperion, &Hyperion::rawLedColors, this, &JsonAPI::streamLedcolorsUpdate);
disconnect(_hyperion, &Hyperion::rawLedColors, this, 0);
_ledStreamTimer->stop();
disconnect(_ledStreamConnection);
}
else if (subcommand == "imagestream-start")
{
_streaming_image_reply["success"] = true;
_streaming_image_reply["command"] = command+"-imagestream-update";
_streaming_image_reply["tan"] = tan;
connect(_hyperion, &Hyperion::currentImage, this, &JsonAPI::setImage, Qt::UniqueConnection);
connect(_hyperion, &Hyperion::currentImage, this, [=](const Image<ColorRgb>& image)
{
_currentImage = image;
// necessary because Qt::UniqueConnection for lambdas does not work until 5.9
// see: https://bugreports.qt.io/browse/QTBUG-52438
if (!_imageStreamConnection)
_imageStreamConnection = connect(_imageStreamTimer, &QTimer::timeout, this, [=]()
{
emit setImage(_currentImage);
}, Qt::UniqueConnection);
// start timer
if (!_imageStreamTimer->isActive() || _imageStreamTimer->interval() != streaming_interval)
_imageStreamTimer->start(streaming_interval);
}, Qt::UniqueConnection);
_hyperion->update();
}
else if (subcommand == "imagestream-stop")
{
disconnect(_hyperion, &Hyperion::currentImage, this, &JsonAPI::setImage);
disconnect(_hyperion, &Hyperion::currentImage, this, 0);
_imageStreamTimer->stop();
disconnect(_imageStreamConnection);
}
else
{
@ -1485,52 +1524,35 @@ void JsonAPI::sendErrorReply(const QString &error, const QString &command, const
emit callbackMessage(reply);
}
void JsonAPI::streamLedcolorsUpdate(const std::vector<ColorRgb>& ledColors)
{
QMutexLocker lock(&_led_stream_mutex);
if ( (_led_stream_timeout+100) < QDateTime::currentMSecsSinceEpoch() )
QJsonObject result;
QJsonArray leds;
for(const auto & color : ledColors)
{
_led_stream_timeout = QDateTime::currentMSecsSinceEpoch();
QJsonObject result;
QJsonArray leds;
for(auto color = ledColors.begin(); color != ledColors.end(); ++color)
{
QJsonObject item;
item["index"] = int(color - ledColors.begin());
item["red"] = color->red;
item["green"] = color->green;
item["blue"] = color->blue;
leds.append(item);
}
result["leds"] = leds;
_streaming_leds_reply["result"] = result;
// send the result
emit callbackMessage(_streaming_leds_reply);
leds << QJsonValue(color.red) << QJsonValue(color.green) << QJsonValue(color.blue);
}
result["leds"] = leds;
_streaming_leds_reply["result"] = result;
// send the result
emit callbackMessage(_streaming_leds_reply);
}
void JsonAPI::setImage(const Image<ColorRgb> & image)
{
QMutexLocker lock(&_image_stream_mutex);
if ( (_image_stream_timeout+100) < QDateTime::currentMSecsSinceEpoch() )
{
_image_stream_timeout = QDateTime::currentMSecsSinceEpoch();
QImage jpgImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
jpgImage.save(&buffer, "jpg");
QImage jpgImage((const uint8_t *) image.memptr(), image.width(), image.height(), 3*image.width(), QImage::Format_RGB888);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
jpgImage.save(&buffer, "jpg");
QJsonObject result;
result["image"] = "data:image/jpg;base64,"+QString(ba.toBase64());
_streaming_image_reply["result"] = result;
emit callbackMessage(_streaming_image_reply);
}
QJsonObject result;
result["image"] = "data:image/jpg;base64,"+QString(ba.toBase64());
_streaming_image_reply["result"] = result;
emit callbackMessage(_streaming_image_reply);
}
void JsonAPI::incommingLogMessage(const Logger::T_LOG_MESSAGE &msg)

View File

@ -617,8 +617,16 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
}
// set the settings
fmt.fmt.pix.width = max_width;
fmt.fmt.pix.height = max_height;
if (max_width != 0 || max_height != 0)
{
fmt.fmt.pix.width = max_width;
fmt.fmt.pix.height = max_height;
}
else
{
fmt.fmt.pix.width = _width;
fmt.fmt.pix.height = _height;
}
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
{

View File

@ -46,7 +46,6 @@ Hyperion::Hyperion(const quint8& instance)
, _settingsManager(new SettingsManager(instance, this))
, _componentRegister(this)
, _ledString(hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
, _ledStringClone(hyperion::createLedStringClone(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
, _imageProcessor(new ImageProcessor(_ledString, this))
, _muxer(_ledString.leds().size())
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(_ledString.leds().size(), getSetting(settings::COLOR).object()))
@ -87,10 +86,6 @@ void Hyperion::start()
{
_ledStringColorOrder.push_back(led.colorOrder);
}
for (Led& led : _ledStringClone.leds())
{
_ledStringColorOrder.insert(_ledStringColorOrder.begin() + led.index, led.colorOrder);
}
// connect Hyperion::update with Muxer visible priority changes as muxer updates independent
connect(&_muxer, &PriorityMuxer::visiblePriorityChanged, this, &Hyperion::update);
@ -202,9 +197,8 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
// stop and cache all running effects, as effects depend heavily on ledlayout
_effectEngine->cacheRunningEffects();
// ledstring, clone, img processor, muxer, ledGridSize (eff engine image based effects), _ledBuffer and ByteOrder of ledstring
// ledstring, img processor, muxer, ledGridSize (eff engine image based effects), _ledBuffer and ByteOrder of ledstring
_ledString = hyperion::createLedString(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
_ledStringClone = hyperion::createLedStringClone(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
_imageProcessor->setLedString(_ledString);
_muxer.updateLedColorsLength(_ledString.leds().size());
_ledGridSize = hyperion::getLedLayoutGridSize(leds);
@ -217,10 +211,6 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
{
_ledStringColorOrder.push_back(led.colorOrder);
}
for (Led& led : _ledStringClone.leds())
{
_ledStringColorOrder.insert(_ledStringColorOrder.begin() + led.index, led.colorOrder);
}
// handle hwLedCount update
_hwLedCount = qMax(unsigned(getSetting(settings::DEVICE).object()["hardwareLedCount"].toInt(getLedCount())), getLedCount());
@ -244,7 +234,6 @@ void Hyperion::handleSettingsUpdate(const settings::type& type, const QJsonDocum
if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb"))
{
_ledString = hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
_ledStringClone = hyperion::createLedStringClone(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
_imageProcessor->setLedString(_ledString);
}
@ -368,6 +357,9 @@ void Hyperion::setColor(const int priority, const ColorRgb &color, const int tim
// create led vector from single color
std::vector<ColorRgb> ledColors(_ledString.leds().size(), color);
if (getPriorityInfo(priority).componentId != hyperion::COMP_COLOR)
clear(priority);
// register color
registerInput(priority, hyperion::COMP_COLOR, origin);
@ -539,12 +531,6 @@ void Hyperion::update()
_raw2ledAdjustment->applyAdjustment(_ledBuffer);
// insert cloned leds into buffer
for (Led& led : _ledStringClone.leds())
{
_ledBuffer.insert(_ledBuffer.begin() + led.index, _ledBuffer.at(led.clone));
}
int i = 0;
for (ColorRgb& color : _ledBuffer)
{

View File

@ -72,7 +72,7 @@ int LinearColorSmoothing::write(const std::vector<ColorRgb> &ledValues)
_previousTime = QDateTime::currentMSecsSinceEpoch();
_previousValues = ledValues;
_timer->start();
QMetaObject::invokeMethod(_timer, "start", Qt::QueuedConnection, Q_ARG(int, _updateInterval));
}
else
{
@ -182,7 +182,7 @@ void LinearColorSmoothing::setEnable(bool enable)
{
if (!enable)
{
_timer->stop();
QMetaObject::invokeMethod(_timer, "stop", Qt::QueuedConnection);
_previousValues.clear();
}
// update comp register
@ -218,10 +218,9 @@ bool LinearColorSmoothing::selectConfig(unsigned cfg, const bool& force)
if (_cfgList[cfg].updateInterval != _updateInterval)
{
_timer->stop();
QMetaObject::invokeMethod(_timer, "stop", Qt::QueuedConnection);
_updateInterval = _cfgList[cfg].updateInterval;
_timer->setInterval(_updateInterval);
_timer->start();
QMetaObject::invokeMethod(_timer, "start", Qt::QueuedConnection, Q_ARG(int, _updateInterval));
}
_currentConfigId = cfg;
//DebugIf( enabled() && !_pause, _log, "set smoothing cfg: %d, interval: %d ms, settlingTime: %d ms, updateDelay: %d frames", _currentConfigId, _updateInterval, _settlingTime, _outputDelay );

View File

@ -185,6 +185,7 @@ bool PriorityMuxer::setInput(const int priority, const std::vector<ColorRgb>& le
// update input
input.timeoutTime_ms = timeout_ms;
input.ledColors = ledColors;
input.image.clear();
// emit active change
if(activeChange)
@ -224,6 +225,7 @@ bool PriorityMuxer::setInputImage(const int priority, const Image<ColorRgb>& ima
// update input
input.timeoutTime_ms = timeout_ms;
input.image = image;
input.ledColors.clear();
// emit active change
if(activeChange)

View File

@ -8,23 +8,13 @@
"required" : true,
"properties":
{
"index":
{
"type":"integer",
"required":true,
"default" : 0
},
"clone":
{
"type":"integer"
},
"hscan":
"h":
{
"type":"object",
"required" : true,
"properties":
{
"minimum":
"min":
{
"type":"number",
"minimum" : 0,
@ -32,7 +22,7 @@
"required":true,
"default" : 0
},
"maximum":
"max":
{
"type":"number",
"minimum" : 0,
@ -43,13 +33,13 @@
},
"additionalProperties" : false
},
"vscan":
"v":
{
"type":"object",
"required" : true,
"properties":
{
"minimum":
"min":
{
"type":"number",
"minimum" : 0,
@ -57,7 +47,7 @@
"required":true,
"default" : 0
},
"maximum":
"max":
{
"type":"number",
"minimum" : 0,

View File

@ -1,5 +1,6 @@
#include <list>
#include <unistd.h>
#include <QPixmap>
#include <QWindow>
@ -128,7 +129,31 @@ void SysTray::closeEvent(QCloseEvent *event)
void SysTray::settings()
{
// Hide error messages when opening webbrowser
int out_pipe[2];
int saved_stdout;
int saved_stderr;
// saving stdout and stderr file descriptor
saved_stdout = ::dup( STDOUT_FILENO );
saved_stderr = ::dup( STDERR_FILENO );
if(::pipe(out_pipe) == 0)
{
// redirecting stdout to pipe
::dup2(out_pipe[1], STDOUT_FILENO);
::close(out_pipe[1]);
// redirecting stderr to stdout
::dup2(STDOUT_FILENO, STDERR_FILENO);
}
QDesktopServices::openUrl(QUrl("http://localhost:"+QString::number(_webPort)+"/", QUrl::TolerantMode));
// restoring stdout
::dup2(saved_stdout, STDOUT_FILENO);
// restoring stderr
::dup2(saved_stderr, STDERR_FILENO);
}
void SysTray::setEffect()