mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
* - New Media Foundation grabber
- JsonAPI available grabber fix
- commented json config removed
* Added libjpeg-turbo to dependencies
* Fix OSX build
Removed Azure Pipelines from build scripts
* Remove Platform from Dashboard
* Correct Grabber Namings
* Grabber UI improvements, generic JSONEditor Selection Update
* Active grabber fix
* Stop Framebuffer grabber on failure
* - Image format NV12 and I420 added
- Flip mode
- Scaling factor for MJPEG
- VSCode (compile before run)
- CI (push) dependency libjpeg-turbo added
* Refactor MediaFoundation (Part 1)
* Remove QDebug output
* Added image flipping ability to MF Grabber
* fix issue 1160
* -Reload MF Grabber only once per WebUI update
- Cleanup
* Improvements
* - Set 'Software Frame Decimation' begin to 0
- Removed grabber specific device name from Log
- Keep pixel format when switching resolution
- Display 'Flip mode' correct in Log
- BGR24 images always flipped
* Refactor MediaFoundation (Part 2)
* Refactor V4L2 grabber (part 1) (#62)
* Media Foundation grabber adapted to V4L2 change
* Enable Media Foundation grabber on windows
* Have fps as int, fix height typo
* Added video standards to JsonAPI output
* Error handling in source reader improved
* Fix "Frame to small" error
* Discovery VideoSources and Dynamically Update Editor
* Hide all element when no video grabber discovered, upate naming
* Do not show unsupported grabbers
* Copy Log to Clipboard
* Update Grabber schema and Defaults
* Update access levels and validate crop ranges
* Height and width in Qt grabber corrected
* Correct formatting
* Untabify
* Global component states across instances
* Components divided on the dashboard
* refactor
* Fix Merge-issues
* Database migration aligning with updated grabber model
* Align Grabber.js with new utility functions
* Allow editor-validation for enum-lists
* Handle "Show Explainations scenario" correctly
* Grabber - Ensure save is only possible on valid content
* Dashboard update + fix GlobalSignal connection
* Ensure default database is populated with current release
* Correct grabber4L2 access level
* Display Signal detection area in preview
* Write Hyperion version into default config on compiling.
* Create defaultconfig.json dynamically
* WebUI changes
* Correct grabber config look-ups
* Refactor i18n language loading
* Fix en.json
* Split global capture from instance capture config
* Update grabber default values
* Standalone grabber: Add --debug switch
* Enhance showInputOptionsForKey for multiple keys
* Add grabber instance link to system grabber config
* Only show signal detection area, if grabber is enabled
* Always show Active element on grabber page
* Remote control - Only display gabber status, if global grabber is enabled
* WebUI optimization (thx to @mkcologne)
Start Grabber only when global settings are enabled
Fixed an issue in the WebUI preview
* V4L2/MF changes
* Jsoneditor, Correct translation for default values
* Refactor LED-Device handling in UI and make element naming consistent
* MF Discovery extended
* Fix LGTM finding
* Support Grabber Bri, Hue, Sat and Con in UI, plus their defaults
* Concider Access level for item filtering
* Concider Access level for item filtering
* Revert "Concider Access level for item filtering"
This reverts commit 5b0ce3c0f2
.
* Disable fpsSoftwareDecimation for framegrabber, as not supported yet
* JSON-Editor- Add updated schema for validation on dynamic elements
* added V4L2 color IDs
* LGTM findings fix
* destroy SR callback only on exit
* Grabber.js - Hide elements not supported by platform
* Fixed freezing start effect
* Grabber UI - Hardware controls - Show current values and allow to reset to defaults
* Grabber - Discovery - Add current values to properties
* Small things
* Clean-up Effects and have ENDLESS consistently defined
* Fix on/off/on priority during startup, by initializing _prevVisComp in line with background priority
* Add missing translation mappings
* DirectX Grabber reactivated/ QT Grabber size decimation fixed
* typo in push-master workflow
* Use PreciseTimer for Grabber to ensure stable FPS timing
* Set default Screencapture rate consistently
* Fix libjpeg-turbo download
* Remove Zero character from file
* docker-compile Add PLATFORM parameter, only copy output file after successful compile
* Framebuffer, Dispmanx, OSX, AML Grabber discovery, various clean-up and consistencies across grabbers
* Fix merge problem - on docker-compile Add PLATFORM parameter, only copy output file after successful compile
* Fix definition
* OSXFRameGrabber - Revert cast
* Clean-ups nach Feedback
* Disable certain libraries when building armlogic via standard stretch image as developer
* Add CEC availability to ServerInfo to have it platform independent
* Grabber UI - Fix problem that crop values are not populated when refining editor rage
* Preserve value when updating json-editor range
* LEDVisualisation - Clear image when source changes
* Fix - Preserve value when updating json-editor range
* LEDVisualisation - Clear image when no component is active
* Allow to have password handled by Password-Manager (#1263)
* Update default signal detection area to green assuming rainbow grabber
* LED Visualisation - Handle empty priority update
* Fix yuv420 in v4l2 grabber
* V4L2-Grabber discovery - Only report grabbers with valid video input information
* Grabber - Update static variables to have them working in release build
* LED Visualisation - ClearImage when no priorities
* LED Visualisation - Fix Logo resizing issue
* LED Visualisation - Have nearly black background and negative logo
Co-authored-by: LordGrey <lordgrey.emmel@gmail.com>
Co-authored-by: LordGrey <48840279+Lord-Grey@users.noreply.github.com>
330 lines
12 KiB
JavaScript
330 lines
12 KiB
JavaScript
$(document).ready(function () {
|
|
var modalOpened = false;
|
|
var ledsim_width = 540;
|
|
var ledsim_height = 489;
|
|
var dialog;
|
|
var leds;
|
|
var grabberConfig;
|
|
var lC = false;
|
|
var imageCanvasNodeCtx;
|
|
var ledsCanvasNodeCtx;
|
|
var canvas_height;
|
|
var canvas_width;
|
|
var twoDPaths = [];
|
|
var toggleLeds = false;
|
|
var toggleLedsNum = false;
|
|
var toggleSigDetectArea = false;
|
|
|
|
var activeComponent = "";
|
|
|
|
const image = new Image()
|
|
image.src = "img/hyperion/logo_negativ.png",
|
|
|
|
/// add prototype for simple canvas clear() method
|
|
CanvasRenderingContext2D.prototype.clear = function () {
|
|
this.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
|
};
|
|
|
|
function create2dPaths() {
|
|
twoDPaths = [];
|
|
for (var idx = 0; idx < leds.length; idx++) {
|
|
var led = leds[idx];
|
|
twoDPaths.push(build2DPath(led.hmin * canvas_width, led.vmin * canvas_height, (led.hmax - led.hmin) * canvas_width, (led.vmax - led.vmin) * canvas_height, 5));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draws a rounded rectangle into a new Path2D object, returns the created path.
|
|
* If you omit the last three params, it will draw a rectangle
|
|
* outline with a 5 pixel border radius
|
|
* @param {Number} x The top left x coordinate
|
|
* @param {Number} y The top left y coordinate
|
|
* @param {Number} width The width of the rectangle
|
|
* @param {Number} height The height of the rectangle
|
|
* @param {Number} [radius = 5] The corner radius; It can also be an object
|
|
* to specify different radii for corners
|
|
* @param {Number} [radius.tl = 0] Top left
|
|
* @param {Number} [radius.tr = 0] Top right
|
|
* @param {Number} [radius.br = 0] Bottom right
|
|
* @param {Number} [radius.bl = 0] Bottom left
|
|
* @return {Path2D} The final path
|
|
*/
|
|
function build2DPath(x, y, width, height, radius) {
|
|
if (typeof radius == 'number') {
|
|
radius = { tl: radius, tr: radius, br: radius, bl: radius };
|
|
} else {
|
|
var defaultRadius = { tl: 0, tr: 0, br: 0, bl: 0 };
|
|
for (var side in defaultRadius) {
|
|
radius[side] = radius[side] || defaultRadius[side];
|
|
}
|
|
}
|
|
|
|
var path = new Path2D();
|
|
|
|
path.moveTo(x + radius.tl, y);
|
|
path.lineTo(x + width - radius.tr, y);
|
|
path.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
|
|
path.lineTo(x + width, y + height - radius.br);
|
|
path.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
|
|
path.lineTo(x + radius.bl, y + height);
|
|
path.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
|
|
path.lineTo(x, y + radius.tl);
|
|
path.quadraticCurveTo(x, y, x + radius.tl, y);
|
|
|
|
return path;
|
|
}
|
|
|
|
$(window.hyperion).one("ready", function () {
|
|
leds = window.serverConfig.leds;
|
|
grabberConfig = window.serverConfig.grabberV4L2;
|
|
|
|
if (window.showOptHelp) {
|
|
createHint('intro', $.i18n('main_ledsim_text'), 'ledsim_text');
|
|
$('#ledsim_text').css({ 'margin': '10px 15px 0px 15px' });
|
|
$('#ledsim_text .bs-callout').css("margin", "0px")
|
|
}
|
|
|
|
if (getStorage('ledsim_width') != null) {
|
|
ledsim_width = getStorage('ledsim_width');
|
|
ledsim_height = getStorage('ledsim_height');
|
|
}
|
|
|
|
dialog = $("#ledsim_dialog").dialog({
|
|
uiLibrary: 'bootstrap',
|
|
resizable: true,
|
|
modal: false,
|
|
minWidth: 250,
|
|
width: ledsim_width,
|
|
minHeight: 350,
|
|
height: ledsim_height,
|
|
closeOnEscape: true,
|
|
autoOpen: false,
|
|
title: $.i18n('main_ledsim_title'),
|
|
resize: function (e) {
|
|
updateLedLayout();
|
|
},
|
|
opened: function (e) {
|
|
if (!lC) {
|
|
updateLedLayout();
|
|
lC = true;
|
|
}
|
|
modalOpened = true;
|
|
requestLedColorsStart();
|
|
|
|
setClassByBool('#leds_toggle_live_video', window.imageStreamActive, "btn-danger", "btn-success");
|
|
if ($('#leds_toggle_live_video').hasClass('btn-success'))
|
|
requestLedImageStart();
|
|
},
|
|
closed: function (e) {
|
|
modalOpened = false;
|
|
lC = false;
|
|
},
|
|
resizeStop: function (e) {
|
|
setStorage("ledsim_width", $("#ledsim_dialog").outerWidth());
|
|
setStorage("ledsim_height", $("#ledsim_dialog").outerHeight());
|
|
}
|
|
});
|
|
// apply new serverinfos
|
|
$(window.hyperion).on("cmd-config-getconfig", function (event) {
|
|
leds = event.response.info.leds;
|
|
grabberConfig = event.response.info.grabberV4L2;
|
|
updateLedLayout();
|
|
});
|
|
});
|
|
|
|
function printLedsToCanvas(colors) {
|
|
|
|
if (grabberConfig.enable && grabberConfig.signalDetection && toggleSigDetectArea && storedAccess === 'expert') {
|
|
|
|
sigDetectAreaCanvasNodeCtx.setLineDash([5, 5]);
|
|
sigDetectAreaCanvasNodeCtx.stroke(build2DPath(grabberConfig.sDHOffsetMin * canvas_width,
|
|
grabberConfig.sDVOffsetMin * canvas_height,
|
|
(grabberConfig.sDHOffsetMax - grabberConfig.sDHOffsetMin) * canvas_width,
|
|
(grabberConfig.sDVOffsetMax - grabberConfig.sDVOffsetMin) * canvas_height,
|
|
5));
|
|
}
|
|
|
|
// toggle leds, do not print
|
|
if (toggleLeds)
|
|
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.hmin * canvas_width, led.vmin * canvas_height, (led.hmax-led.hmin) * canvas_width, (led.vmax-led.vmin) * canvas_height, 4, true, colors[idx])
|
|
//ledsCanvasNodeCtx.fillRect(led.hmin * canvas_width, led.vmin * canvas_height, (led.hmax-led.hmin) * canvas_width, (led.vmax-led.vmin) * canvas_height);
|
|
|
|
ledsCanvasNodeCtx.fillStyle = (useColor) ? "rgba(" + colors[cPos] + "," + colors[cPos + 1] + "," + colors[cPos + 2] + ",0.75)" : "hsla(" + (idx * 360 / leds.length) + ",100%,50%,0.75)";
|
|
ledsCanvasNodeCtx.fill(twoDPaths[idx]);
|
|
ledsCanvasNodeCtx.strokeStyle = '#323232';
|
|
ledsCanvasNodeCtx.stroke(twoDPaths[idx]);
|
|
|
|
if (toggleLedsNum) {
|
|
//ledsCanvasNodeCtx.shadowOffsetX = 1;
|
|
//ledsCanvasNodeCtx.shadowOffsetY = 1;
|
|
//ledsCanvasNodeCtx.shadowColor = "black";
|
|
//ledsCanvasNodeCtx.shadowBlur = 4;
|
|
ledsCanvasNodeCtx.fillStyle = "white";
|
|
ledsCanvasNodeCtx.textAlign = "center";
|
|
ledsCanvasNodeCtx.fillText(((led.name) ? led.name : idx), (led.hmin * canvas_width) + (((led.hmax - led.hmin) * canvas_width) / 2), (led.vmin * canvas_height) + (((led.vmax - led.vmin) * canvas_height) / 2));
|
|
}
|
|
|
|
// increment colorsPosition
|
|
cPos += 3;
|
|
}
|
|
}
|
|
|
|
function updateLedLayout() {
|
|
if (grabberConfig.enable && grabberConfig.signalDetection && storedAccess === 'expert') {
|
|
$("#sigDetectArea_toggle").show();
|
|
} else {
|
|
$("#sigDetectArea_toggle").hide();
|
|
}
|
|
|
|
//calculate body size
|
|
canvas_height = $('#ledsim_dialog').outerHeight() - $('#ledsim_text').outerHeight() - $('[data-role=footer]').outerHeight() - $('[data-role=header]').outerHeight() - 40;
|
|
canvas_width = $('#ledsim_dialog').outerWidth() - 30;
|
|
|
|
$('#leds_canvas').html("");
|
|
var leds_html = '<canvas id="image_preview_canv" width="' + canvas_width + '" height="' + canvas_height + '" style="position: absolute; left: 0; top: 0; z-index: 99998;"></canvas>';
|
|
leds_html += '<canvas id="leds_preview_canv" width="' + canvas_width + '" height="' + canvas_height + '" style="position: absolute; left: 0; top: 0; z-index: 99999;"></canvas>';
|
|
leds_html += '<canvas id="grab_preview_canv" width="' + canvas_width + '" height="' + canvas_height + '" style="position: absolute; left: 0; top: 0; z-index: 99999;"></canvas>';
|
|
|
|
$('#leds_canvas').html(leds_html);
|
|
|
|
imageCanvasNodeCtx = document.getElementById("image_preview_canv").getContext("2d");
|
|
ledsCanvasNodeCtx = document.getElementById("leds_preview_canv").getContext("2d");
|
|
sigDetectAreaCanvasNodeCtx = document.getElementById("grab_preview_canv").getContext("2d");
|
|
create2dPaths();
|
|
printLedsToCanvas();
|
|
resetImage();
|
|
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
$('#leds_toggle_num').off().on("click", function () {
|
|
toggleLedsNum = !toggleLedsNum
|
|
toggleClass('#leds_toggle_num', "btn-danger", "btn-success");
|
|
});
|
|
// ------------------------------------------------------------------
|
|
|
|
$('#leds_toggle').off().on("click", function () {
|
|
toggleLeds = !toggleLeds
|
|
ledsCanvasNodeCtx.clear();
|
|
toggleClass('#leds_toggle', "btn-success", "btn-danger");
|
|
|
|
if (!toggleLeds) {
|
|
$("#leds_toggle_num").show();
|
|
} else {
|
|
$("#leds_toggle_num").hide();
|
|
}
|
|
});
|
|
|
|
// ------------------------------------------------------------------
|
|
$('#leds_toggle_live_video').off().on("click", function () {
|
|
setClassByBool('#leds_toggle_live_video', window.imageStreamActive, "btn-success", "btn-danger");
|
|
if (window.imageStreamActive) {
|
|
requestLedImageStop();
|
|
resetImage();
|
|
}
|
|
else {
|
|
requestLedImageStart();
|
|
}
|
|
});
|
|
|
|
$('#sigDetectArea_toggle').off().on("click", function () {
|
|
toggleSigDetectArea = !toggleSigDetectArea
|
|
sigDetectAreaCanvasNodeCtx.clear();
|
|
toggleClass('#sigDetectArea_toggle', "btn-success", "btn-danger");
|
|
});
|
|
|
|
// ------------------------------------------------------------------
|
|
$(window.hyperion).on("cmd-ledcolors-ledstream-update", function (event) {
|
|
if (!modalOpened) {
|
|
requestLedColorsStop();
|
|
}
|
|
else {
|
|
printLedsToCanvas(event.response.result.leds)
|
|
}
|
|
});
|
|
|
|
// ------------------------------------------------------------------
|
|
$(window.hyperion).on("cmd-ledcolors-imagestream-update", function (event) {
|
|
//console.log("cmd-ledcolors-imagestream-update", event.response);
|
|
setClassByBool('#leds_toggle_live_video', window.imageStreamActive, "btn-danger", "btn-success");
|
|
if (!modalOpened) {
|
|
if ($('#leds_prev_toggle_live_video').length > 0)
|
|
return;
|
|
requestLedImageStop();
|
|
}
|
|
else {
|
|
var imageData = (event.response.result.image);
|
|
|
|
var image = new Image();
|
|
image.onload = function () {
|
|
imageCanvasNodeCtx.drawImage(image, 0, 0, canvas_width, canvas_height);
|
|
};
|
|
image.src = imageData;
|
|
}
|
|
});
|
|
|
|
$("#btn_open_ledsim").off().on("click", function (event) {
|
|
dialog.open();
|
|
});
|
|
|
|
// ------------------------------------------------------------------
|
|
$(window.hyperion).on("cmd-settings-update", function (event) {
|
|
|
|
var obj = event.response.data
|
|
if (obj.leds || obj.grabberV4L2) {
|
|
//console.log("ledsim: cmd-settings-update", event.response.data);
|
|
Object.getOwnPropertyNames(obj).forEach(function (val, idx, array) {
|
|
window.serverInfo[val] = obj[val];
|
|
});
|
|
leds = window.serverConfig.leds;
|
|
grabberConfig = window.serverConfig.grabberV4L2;
|
|
updateLedLayout();
|
|
}
|
|
});
|
|
|
|
$(window.hyperion).on("cmd-priorities-update", function (event) {
|
|
//console.log("cmd-priorities-update", event.response.data);
|
|
|
|
var prios = event.response.data.priorities;
|
|
if (prios.length > 0)
|
|
{
|
|
//Clear image when new input
|
|
if (prios[0].componentId !== activeComponent) {
|
|
resetImage();
|
|
activeComponent = prios[0].componentId;
|
|
}
|
|
else if (!prios[0].active) {
|
|
resetImage();
|
|
}
|
|
}
|
|
else {
|
|
resetImage();
|
|
}
|
|
|
|
});
|
|
|
|
function resetImage() {
|
|
if (typeof imageCanvasNodeCtx !== "undefined") {
|
|
|
|
imageCanvasNodeCtx.fillStyle = "#1c1c1c"; //90% gray
|
|
imageCanvasNodeCtx.fillRect(0, 0, canvas_width, canvas_height);
|
|
imageCanvasNodeCtx.drawImage(image, canvas_width / 2 - image.width / 2, canvas_height / 2 - image.height / 2, image.width, image.height);
|
|
}
|
|
}
|
|
});
|