var ledsCustomCfgInitialized = false; var finalLedArray = []; function validateText(){ e = isJsonString($("#ledconfig").val()); if (e.length != 0){ showInfoDialog("error", $.i18n('InfoDialog_leds_validfail_title'), e); return false } return true } function round(number) { var factor = Math.pow(10, 4); var tempNumber = number * factor; var roundedTempNumber = Math.round(tempNumber); return roundedTempNumber / factor; }; function createLedPreview(leds, origin){ if (origin == "classic"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originCL')); $('#leds_preview').css("padding-top", "56.25%"); } else if(origin == "text"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originTEXT')); $('#leds_preview').css("padding-top", "56.25%"); } else if(origin == "matrix"){ $('#previewcreator').html($.i18n('conf_leds_layout_preview_originMA')); $('#leds_preview').css("padding-top", "100%"); } $('#previewledcount').html($.i18n('conf_leds_layout_preview_totalleds', leds.length)); $('.st_helper').css("border", "8px solid grey"); canvas_height = $('#leds_preview').innerHeight(); canvas_width = $('#leds_preview').innerWidth(); leds_html = ""; for(var idx=0; idx<leds.length; idx++) { led = leds[idx]; led_id='ledc_'+[idx]; bgcolor = "background-color:hsl("+(idx*360/leds.length)+",100%,50%);"; 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>'; } $('#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"); } function createClassicLeds(){ //get values var ledstop = parseInt($("#ip_cl_top").val()); var ledsbottom = parseInt($("#ip_cl_bottom").val()); var ledsleft = parseInt($("#ip_cl_left").val()); var ledsright = parseInt($("#ip_cl_right").val()); var ledsglength = parseInt($("#ip_cl_glength").val()); 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); var Vmin = 0.0 + edgeVGap; var Vmax = 1.0 - edgeVGap; var Hmin = 0.0 + edgeHGap; var Hmax = 1.0 - edgeHGap; var Hdiff = Hmax-Hmin; var Vdiff = Vmax-Vmin; var ledArray = []; function createFinalArray(array){ finalLedArray = []; for(var i = 0; i<array.length; i++){ hmin = array[i].hscan.minimum; hmax = array[i].hscan.maximum; vmin = array[i].vscan.minimum; vmax = array[i].vscan.maximum; finalLedArray[i] = { "index" : i, "hscan": { "maximum" : hmax, "minimum" : hmin }, "vscan": { "maximum": vmax, "minimum": vmin}} } createLedPreview(finalLedArray, 'classic'); } function rotateArray(array, times){ if (times > "0"){ while( times-- ){ array.push(array.shift()) } return array; } else { while( times++ ){ array.unshift(array.pop()) } return array; } } function valScan(val) { if(val > 1) return val = 1; if(val < 0) return val = 0; return val; } function ovl(scan,val) { if(scan == "+") return valScan(val += overlap); 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 }} ); } function createTopLeds(){ step=(Hmax-Hmin)/ledstop; //if(cornerVGap != '0') // step=(Hmax-Hmin-(cornerHGap*2))/ledstop; vmin=Vmin; vmax=vmin+ledsHDepth; for (var i = 0; i<ledstop; i++){ hmin = ovl("-",(Hdiff/ledstop*[i])+edgeHGap); hmax = ovl("+",(Hdiff/ledstop*[i])+step+edgeHGap); createLedArray(hmin, hmax, vmin, vmax); } } function createLeftLeds(){ step=(Vmax-Vmin)/ledsleft; //if(cornerVGap != '0') // step=(Vmax-Vmin-(cornerVGap*2))/ledsleft; hmin=Hmin; hmax=hmin+ledsVDepth; for (var i = ledsleft-1; i>-1; --i){ vmin = ovl("-",(Vdiff/ledsleft*[i])+edgeVGap); vmax = ovl("+",(Vdiff/ledsleft*[i])+step+edgeVGap); createLedArray(hmin, hmax, vmin, vmax); } } function createRightLeds(){ step=(Vmax-Vmin)/ledsright; //if(cornerVGap != '0') // step=(Vmax-Vmin-(cornerVGap*2))/ledsright; hmax=Hmax; hmin=hmax-ledsVDepth; for (var i = 0; i<ledsright; i++){ vmin = ovl("-",(Vdiff/ledsright*[i])+edgeVGap); vmax = ovl("+",(Vdiff/ledsright*[i])+step+edgeVGap); createLedArray(hmin, hmax, vmin, vmax); } } function createBottomLeds(){ step=(Hmax-Hmin)/ledsbottom; //if(cornerVGap != '0') // step=(Hmax-Hmin-(cornerHGap*2))/ledsbottom; vmax=Vmax; vmin=vmax-ledsHDepth; for (var i = ledsbottom-1; i>-1; i--){ hmin = ovl("-",(Hdiff/ledsbottom*[i])+edgeHGap); hmax = ovl("+",(Hdiff/ledsbottom*[i])+step+edgeHGap); createLedArray(hmin, hmax, vmin, vmax); } } createLeftLeds(createBottomLeds(createRightLeds(createTopLeds()))); //check led gap pos if (ledsgpos+ledsglength > ledArray.length) { var mpos = Math.max(0,ledArray.length-ledsglength); $('#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); } function createMatrixLeds(){ // Big thank you to RanzQ (Juha Rantanen) from Github for this script // https://raw.githubusercontent.com/RanzQ/hyperion-audio-effects/master/matrix-config.js //get values var ledshoriz = parseInt($("#ip_ma_ledshoriz").val()); var ledsvert = parseInt($("#ip_ma_ledsvert").val()); var cabling = $("#ip_ma_cabling").val(); //var order = $("#ip_ma_order").val(); var start = $("#ip_ma_start").val(); var parallel = false var index = 0 var leds = [] var hblock = 1.0 / ledshoriz var vblock = 1.0 / ledsvert if (cabling == "parallel"){ parallel = true } /** * 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) { var hscanMin = x * hblock var hscanMax = (x + 1) * hblock var vscanMin = y * vblock var vscanMax = (y + 1) * vblock hscanMin = round(hscanMin); hscanMax = round(hscanMax); vscanMin = round(vscanMin); vscanMax = round(vscanMax); leds.push({ index: index, hscan: { minimum: hscanMin, maximum: hscanMax }, vscan: { minimum: vscanMin, maximum: vscanMax } }) } var startYX = start.split('-') var startX = startYX[1] === 'right' ? ledshoriz - 1 : 0 var startY = startYX[0] === 'bottom' ? ledsvert - 1 : 0 var endX = startX === 0 ? ledshoriz - 1 : 0 var endY = startY === 0 ? ledsvert - 1 : 0 var forward = startX < endX var downward = startY < endY var x, y 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++ } if (!parallel) { forward = !forward var tmp = startX startX = endX endX = tmp } } finalLedArray =[]; finalLedArray = leds createLedPreview(leds, 'matrix'); } $(document).ready(function() { // translate performTranslation(); //add intros if(showOptHelp) { createHintH("intro", $.i18n('conf_leds_device_intro'), "leddevice_intro"); 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 = serverConfig.ledConfig; //restore ledConfig for(key in slConfig) { if(typeof(slConfig[key]) === "boolean") $('#ip_cl_'+key).prop('checked', slConfig[key]); else $('#ip_cl_'+key).val(slConfig[key]); } function saveValues() { var ledConfig = {}; for(key in slConfig) { if(typeof(slConfig[key]) === "boolean") ledConfig[key] = $('#ip_cl_'+key).is(':checked'); else if(Number.isInteger(slConfig[key])) ledConfig[key] = parseInt($('#ip_cl_'+key).val()); else ledConfig[key] = $('#ip_cl_'+key).val(); } setTimeout(requestWriteConfig, 100, {ledConfig}); } // check access level and adjust ui if(storedAccess == "default") { $('#btn_ma_generate').toggle(false); $('#btn_cl_generate').toggle(false); $('#texfield_panel').toggle(false); $('#previewcreator').toggle(false); } else { $('#btn_ma_save').toggle(false); $('#btn_cl_save').toggle(false); } // bind change event to all inputs $('.ledCLconstr').bind("change", function() { createClassicLeds(); }); $('.ledMAconstr').bind("change", function() { createMatrixLeds(); }); // cl leds push to textfield and save values $('#btn_cl_generate').off().on("click", function() { if (finalLedArray != ""){ $("#ledconfig").text(JSON.stringify(finalLedArray, null, "\t")); $('#collapse1').collapse('hide'); $('#collapse4').collapse('show'); } }); // ma leds push to textfield and save values $('#btn_ma_generate').off().on("click", function() { if (finalLedArray != ""){ $("#ledconfig").text(JSON.stringify(finalLedArray, null, "\t")); $('#collapse2').collapse('hide'); $('#collapse4').collapse('show'); } }); // fill textfield with current led conf and copy to finalLedArray $("#ledconfig").text(JSON.stringify(serverConfig.leds, null, "\t")); finalLedArray = serverConfig.leds; // create and update editor var conf_editor = null; $("#leddevices").off().on("change", function() { generalOptions = serverSchema.properties.device; specificOptions = serverSchema.properties.alldevices[$(this).val()]; conf_editor = createJsonEditor('editor_container', { generalOptions : generalOptions, specificOptions : specificOptions, }); values_general = {}; values_specific = {}; isCurrentDevice = (serverInfo.info.ledDevices.active == $(this).val()); for(var key in serverConfig.device){ if (key != "type" && key in generalOptions.properties) values_general[key] = serverConfig.device[key]; }; conf_editor.getEditor("root.generalOptions").setValue( values_general ); if (isCurrentDevice) { specificOptions_val = conf_editor.getEditor("root.specificOptions").getValue() for(var key in specificOptions_val){ values_specific[key] = (key in serverConfig.device) ? serverConfig.device[key] : specificOptions_val[key]; }; 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); }); // create led device selection ledDevices = serverInfo.info.ledDevices.available devRPiSPI = ['apa102', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'ws2812spi']; devRPiPWM = ['ws281x']; devRPiGPIO = ['piblaster']; devNET = ['atmoorb', 'fadecandy', 'philipshue', 'tinkerforge', 'tpm2net', 'udpe131', 'udph801', 'udpraw']; devUSB = ['adalight', 'dmx', 'atmo', 'hyperionusbasp', 'lightpack', 'multilightpack', 'paintpack', 'rawhid', 'sedu', 'tpm2']; var optArr = [[]]; optArr[1]=[]; optArr[2]=[]; optArr[3]=[]; optArr[4]=[]; optArr[5]=[]; for (idx=0; idx<ledDevices.length; idx++) { if($.inArray(ledDevices[idx], devRPiSPI) != -1) optArr[0].push(ledDevices[idx]); else if($.inArray(ledDevices[idx], devRPiPWM) != -1) optArr[1].push(ledDevices[idx]); else if($.inArray(ledDevices[idx], devRPiGPIO) != -1) optArr[2].push(ledDevices[idx]); else if($.inArray(ledDevices[idx], devNET) != -1) optArr[3].push(ledDevices[idx]); else if($.inArray(ledDevices[idx], devUSB) != -1) optArr[4].push(ledDevices[idx]); 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'))); $("#leddevices").append(createSel(optArr[3], $.i18n('conf_leds_optgroup_network'))); $("#leddevices").append(createSel(optArr[4], $.i18n('conf_leds_optgroup_usb'))); $("#leddevices").append(createSel(optArr[5], $.i18n('conf_leds_optgroup_debug'))); $("#leddevices").val(serverInfo.info.ledDevices.active); $("#leddevices").trigger("change"); // validate textfield and update preview $("#leds_custom_updsim").off().on("click", function() { if (validateText()){ createLedPreview(JSON.parse($("#ledconfig").val()), 'text'); } }); // save led config and saveValues - passing textfield $("#btn_ma_save, #btn_cl_save").off().on("click", function() { requestWriteConfig({"leds" :finalLedArray}); saveValues(); }); // validate and save led config from textfield $("#leds_custom_save").off().on("click", function() { if (validateText()) { requestWriteConfig(JSON.parse('{"leds" :'+$("#ledconfig").val()+'}')); saveValues(); } }); // toggle led numbers $('#leds_prev_toggle_num').off().on("click", 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_leyout_checkp1'),$.i18n('conf_leds_leyout_checkp3'),$.i18n('conf_leds_leyout_checkp2'),$.i18n('conf_leds_leyout_checkp4')]; var ul = document.createElement("ul"); ul.className = "checklist" for(var i = 0; i<liList.length; i++) { var li = document.createElement("li"); li.innerHTML = liList[i]; ul.appendChild(li); } 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 if (target == "#menu_gencfg" && !ledsCustomCfgInitialized) { $('#leds_custom_updsim').trigger('click'); ledsCustomCfgInitialized = true; } }); // save led device config $("#btn_submit_controller").off().on("click", function(event) { ledDevice = $("#leddevices").val(); result = {device:{}}; general = conf_editor.getEditor("root.generalOptions").getValue(); specific = conf_editor.getEditor("root.specificOptions").getValue(); for(var key in general){ result.device[key] = general[key]; } for(var key in specific){ result.device[key] = specific[key]; } result.device.type=ledDevice; requestWriteConfig(result) }); removeOverlay(); });