hyperion.ng/assets/webconfig/js/ui_utils.js

1395 lines
46 KiB
JavaScript
Raw Normal View History

var prevTag;
function removeOverlay() {
$("#loading_overlay").removeClass("overlay");
}
function reload() {
location.reload();
}
function storageComp() {
if (typeof (Storage) !== "undefined")
return true;
return false;
}
function getStorage(item) {
if (storageComp()) {
return localStorage.getItem(item);
}
return null;
}
function setStorage(item, value) {
if (storageComp()) {
localStorage.setItem(item, value);
}
}
function removeStorage(item) {
if (storageComp()) {
localStorage.removeItem(item);
}
}
function debugMessage(msg) {
if (window.debugMessagesActive) {
console.log(msg);
}
}
function validateDuration(d) {
if (typeof d === "undefined" || d < 0)
return ENDLESS;
else
return d *= 1000;
}
function getHashtag() {
if (getStorage('lasthashtag') != null)
return getStorage('lasthashtag');
else {
var tag = document.URL;
tag = tag.substr(tag.indexOf("#") + 1);
if (tag == "" || typeof tag === "undefined" || tag.startsWith("http"))
tag = "dashboard"
return tag;
}
}
function loadContent(event, forceRefresh) {
var tag;
var lastSelectedInstance = getStorage('lastSelectedInstance');
if (lastSelectedInstance && (lastSelectedInstance != window.currentHyperionInstance)) {
if (window.serverInfo.instance[lastSelectedInstance] && window.serverInfo.instance[lastSelectedInstance].running) {
instanceSwitch(lastSelectedInstance);
} else {
removeStorage('lastSelectedInstance');
}
}
if (typeof event != "undefined") {
tag = event.currentTarget.hash;
tag = tag.substr(tag.indexOf("#") + 1);
setStorage('lasthashtag', tag);
}
else
tag = getHashtag();
if (forceRefresh || prevTag != tag) {
prevTag = tag;
$("#page-content").off();
$("#page-content").load("/content/" + tag + ".html", function (response, status, xhr) {
if (status == "error") {
tag = 'dashboard';
console.log("Could not find page:", prevTag, ", Redirecting to:", tag);
setStorage('lasthashtag', tag);
$("#page-content").load("/content/" + tag + ".html", function (response, status, xhr) {
if (status == "error") {
$("#page-content").html('<h3>' + encode_utf8(tag) + '<br/>' + $.i18n('info_404') + '</h3>');
removeOverlay();
}
});
}
updateUiOnInstance(window.currentHyperionInstance);
});
}
}
function getInstanceNameByIndex(index) {
var instData = window.serverInfo.instance
for (var key in instData) {
if (instData[key].instance == index)
return instData[key].friendly_name;
}
return "unknown"
}
function updateHyperionInstanceListing() {
if (window.serverInfo.instance) {
var data = window.serverInfo.instance.filter(entry => entry.running);
$('#hyp_inst_listing').html("");
for (var key in data) {
var currInstMarker = (data[key].instance == window.currentHyperionInstance) ? "component-on" : "";
var html = '<li id="hyperioninstance_' + data[key].instance + '"> \
<a> \
<div> \
<i class="fa fa-circle fa-fw '+ currInstMarker + '"></i> \
<span>'+ data[key].friendly_name + '</span> \
</div> \
</a> \
</li> '
if (data.length - 1 > key)
html += '<li class="divider"></li>'
$('#hyp_inst_listing').append(html);
$('#hyperioninstance_' + data[key].instance).off().on("click", function (e) {
var inst = e.currentTarget.id.split("_")[1]
instanceSwitch(inst)
});
}
}
}
function initLanguageSelection() {
// Initialise language selection list with languages supported
for (var i = 0; i < availLang.length; i++) {
$("#language-select").append('<option value="' + i + '" selected="">' + availLangText[i] + '</option>');
}
var langLocale = storedLang;
//Test, if language is supported by hyperion
var langIdx = availLang.indexOf(langLocale);
if (langIdx > -1) {
langText = availLangText[langIdx];
} else {
// If language is not supported by hyperion, try fallback language
langLocale = $.i18n().options.fallbackLocale.substring(0, 2);
langIdx = availLang.indexOf(langLocale);
if (langIdx > -1) {
langText = availLangText[langIdx];
} else {
langLocale = 'en';
langIdx = availLang.indexOf(langLocale);
if (langIdx > -1) {
langText = availLangText[langIdx];
}
}
}
$('#language-select').prop('title', langText);
$("#language-select").val(langIdx);
$("#language-select").selectpicker("refresh");
}
function updateUiOnInstance(inst) {
window.currentHyperionInstance = inst;
window.currentHyperionInstanceName = getInstanceNameByIndex(inst);
$("#active_instance_friendly_name").text(getInstanceNameByIndex(inst));
if (window.serverInfo.instance.filter(entry => entry.running).length > 1) {
$('#btn_hypinstanceswitch').toggle(true);
$('#active_instance_dropdown').prop('disabled', false);
$('#active_instance_dropdown').css('cursor', 'pointer');
$("#active_instance_dropdown").css("pointer-events", "auto");
} else {
$('#btn_hypinstanceswitch').toggle(false);
$('#active_instance_dropdown').prop('disabled', true);
$("#active_instance_dropdown").css('cursor', 'default');
$("#active_instance_dropdown").css("pointer-events", "none");
}
}
function instanceSwitch(inst) {
requestInstanceSwitch(inst)
window.currentHyperionInstance = inst;
window.currentHyperionInstanceName = getInstanceNameByIndex(inst);
setStorage('lastSelectedInstance', inst)
}
function loadContentTo(containerId, fileName) {
$(containerId).load("/content/" + fileName + ".html");
}
function toggleClass(obj, class1, class2) {
if ($(obj).hasClass(class1)) {
$(obj).removeClass(class1);
$(obj).addClass(class2);
}
else {
$(obj).removeClass(class2);
$(obj).addClass(class1);
}
}
function setClassByBool(obj, enable, class1, class2) {
if (enable) {
$(obj).removeClass(class1);
$(obj).addClass(class2);
}
else {
$(obj).removeClass(class2);
$(obj).addClass(class1);
}
}
function showInfoDialog(type, header, message) {
if (type == "success") {
$('#id_body').html('<i style="margin-bottom:20px" class="fa fa-check modal-icon-check">');
if (header == "")
$('#id_body').append('<h4 style="font-weight:bold;text-transform:uppercase;">' + $.i18n('infoDialog_general_success_title') + '</h4>');
$('#id_footer').html('<button type="button" class="btn btn-success" data-dismiss="modal">' + $.i18n('general_btn_ok') + '</button>');
}
else if (type == "warning") {
$('#id_body').html('<i style="margin-bottom:20px" class="fa fa-warning modal-icon-warning">');
if (header == "")
$('#id_body').append('<h4 style="font-weight:bold;text-transform:uppercase;">' + $.i18n('infoDialog_general_warning_title') + '</h4>');
$('#id_footer').html('<button type="button" class="btn btn-warning" data-dismiss="modal">' + $.i18n('general_btn_ok') + '</button>');
}
else if (type == "error") {
$('#id_body').html('<i style="margin-bottom:20px" class="fa fa-warning modal-icon-error">');
if (header == "")
$('#id_body').append('<h4 style="font-weight:bold;text-transform:uppercase;">' + $.i18n('infoDialog_general_error_title') + '</h4>');
$('#id_footer').html('<button type="button" class="btn btn-danger" data-dismiss="modal">' + $.i18n('general_btn_ok') + '</button>');
}
else if (type == "select") {
$('#id_body').html('<img style="margin-bottom:20px" id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_footer').html('<button type="button" id="id_btn_saveset" class="btn btn-primary" data-dismiss="modal"><i class="fa fa-fw fa-save"></i>' + $.i18n('general_btn_saveandreload') + '</button>');
$('#id_footer').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "iswitch") {
$('#id_body').html('<img style="margin-bottom:20px" id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_footer').html('<button type="button" id="id_btn_saveset" class="btn btn-primary" data-dismiss="modal"><i class="fa fa-fw fa-exchange"></i>' + $.i18n('general_btn_iswitch') + '</button>');
$('#id_footer').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "uilock") {
$('#id_body').html('<img id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_footer').html('<b>' + $.i18n('InfoDialog_nowrite_foottext') + '</b>');
}
else if (type == "import") {
$('#id_body').html('<i style="margin-bottom:20px" class="fa fa-warning modal-icon-warning">');
$('#id_footer').html('<button type="button" id="id_btn_import" class="btn btn-warning" data-dismiss="modal"><i class="fa fa-fw fa-save"></i>' + $.i18n('general_btn_saverestart') + '</button>');
$('#id_footer').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "delInst") {
$('#id_body').html('<i style="margin-bottom:20px" class="fa fa-remove modal-icon-warning">');
$('#id_footer').html('<button type="button" id="id_btn_yes" class="btn btn-warning" data-dismiss="modal"><i class="fa fa-fw fa-trash"></i>' + $.i18n('general_btn_yes') + '</button>');
$('#id_footer').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "renInst") {
$('#id_body_rename').html('<i style="margin-bottom:20px" class="fa fa-pencil modal-icon-edit"><br>');
$('#id_body_rename').append('<h4>' + header + '</h4>');
$('#id_body_rename').append('<input class="form-control" id="renInst_name" type="text" value="' + message + '">');
$('#id_footer_rename').html('<button type="button" id="id_btn_ok" class="btn btn-success" data-dismiss-modal="#modal_dialog_rename" disabled><i class="fa fa-fw fa-save"></i>' + $.i18n('general_btn_ok') + '</button>');
$('#id_footer_rename').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "changePassword") {
$('#id_body_rename').html('<i style="margin-bottom:20px" class="fa fa-key modal-icon-edit"><br>');
$('#id_body_rename').append('<h4>' + header + '</h4><br>');
$('#id_body_rename').append('<div class="row"><div class="col-md-4"><p class="text-left">' + $.i18n('infoDialog_username_text') +
'</p></div><div class="col-md-8"><input class="form-control" id="username" type="text" value="Hyperion" disabled></div></div><br>');
$('#id_body_rename').append('<div class="row"><div class="col-md-4"><p class="text-left">' + $.i18n('infoDialog_password_current_text') +
'</p></div><div class="col-md-8"><input class="form-control" id="current-password" placeholder="Old" type="password" autocomplete="current-password"></div></div><br>');
$('#id_body_rename').append('<div class="row"><div class="col-md-4"><p class="text-left">' + $.i18n('infoDialog_password_new_text') +
'</p></div><div class="col-md-8"><input class="form-control" id="new-password" placeholder="New" type="password" autocomplete="new-password"></div></div>');
$('#id_body_rename').append('<div class="bs-callout bs-callout-info"><span>' + $.i18n('infoDialog_password_minimum_length') + '</span></div>');
$('#id_footer_rename').html('<button type="button" id="id_btn_ok" class="btn btn-success" data-dismiss-modal="#modal_dialog_rename" disabled><i class="fa fa-fw fa-save"></i>' + $.i18n('general_btn_ok') + '</button></div>');
$('#id_footer_rename').append('<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
}
else if (type == "checklist") {
$('#id_body').html('<img style="margin-bottom:20px" id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_body').append('<h4 style="font-weight:bold;text-transform:uppercase;">' + $.i18n('infoDialog_checklist_title') + '</h4>');
$('#id_body').append(header);
$('#id_footer').html('<button type="button" class="btn btn-primary" data-dismiss="modal">' + $.i18n('general_btn_ok') + '</button>');
}
else if (type == "newToken") {
$('#id_body').html('<img style="margin-bottom:20px" id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_footer').html('<button type="button" class="btn btn-primary" data-dismiss="modal">' + $.i18n('general_btn_ok') + '</button>');
}
else if (type == "grantToken") {
$('#id_body').html('<img style="margin-bottom:20px" id="id_logo" src="img/hyperion/logo_positiv.png" alt="Redefine ambient light!">');
$('#id_footer').html('<button type="button" class="btn btn-primary" data-dismiss="modal" id="tok_grant_acc">' + $.i18n('general_btn_grantAccess') + '</button>');
$('#id_footer').append('<button type="button" class="btn btn-danger" data-dismiss="modal" id="tok_deny_acc">' + $.i18n('general_btn_denyAccess') + '</button>');
}
if (type != "renInst") {
$('#id_body').append('<h4 style="font-weight:bold;text-transform:uppercase;">' + header + '</h4>');
$('#id_body').append(message);
}
if (type == "select" || type == "iswitch")
$('#id_body').append('<select id="id_select" class="form-control" style="margin-top:10px;width:auto;"></select>');
if (getStorage("darkMode") == "on")
$('#id_logo').attr("src", 'img/hyperion/logo_negativ.png');
$(type == "renInst" || type == "changePassword" ? "#modal_dialog_rename" : "#modal_dialog").modal({
backdrop: "static",
keyboard: false,
show: true
});
$(document).on('click', '[data-dismiss-modal]', function () {
var target = $(this).attr('data-dismiss-modal');
$.find(target).modal('hide');
});
}
function createHintH(type, text, container) {
type = String(type);
if (type == "intro")
tclass = "introd";
$('#' + container).prepend('<div class="' + tclass + '"><h4 style="font-size:16px">' + text + '</h4><hr/></div>');
}
function createHint(type, text, container, buttonid, buttontxt) {
var fe, tclass;
if (type == "intro") {
fe = '';
tclass = "intro-hint";
}
else if (type == "info") {
fe = '<div style="font-size:25px;text-align:center"><i class="fa fa-info"></i></div><div style="text-align:center;font-size:13px">Information</div>';
tclass = "info-hint";
}
else if (type == "wizard") {
fe = '<div style="font-size:25px;text-align:center"><i class="fa fa-magic"></i></div><div style="text-align:center;font-size:13px">Information</div>';
tclass = "wizard-hint";
}
else if (type == "warning") {
fe = '<div style="font-size:25px;text-align:center"><i class="fa fa-info"></i></div><div style="text-align:center;font-size:13px">Information</div>';
tclass = "warning-hint";
}
if (buttonid)
buttonid = '<p><button id="' + buttonid + '" class="btn btn-wizard" style="margin-top:15px;">' + text + '</button></p>';
else
buttonid = "";
if (type == "intro")
$('#' + container).prepend('<div class="bs-callout bs-callout-primary" style="margin-top:0px"><h4>' + $.i18n("conf_helptable_expl") + '</h4>' + text + '</div>');
else if (type == "wizard")
$('#' + container).prepend('<div class="bs-callout bs-callout-wizard" style="margin-top:0px"><h4>' + $.i18n("wiz_wizavail") + '</h4>' + $.i18n('wiz_guideyou', text) + buttonid + '</div>');
else {
createTable('', 'htb', container, true, tclass);
$('#' + container + ' .htb').append(createTableRow([fe, text], false, true));
}
}
function createEffHint(title, text) {
return '<div class="bs-callout bs-callout-primary" style="margin-top:0px"><h4>' + title + '</h4>' + text + '</div>';
}
function valValue(id, value, min, max) {
if (typeof max === 'undefined' || max == "")
max = 999999;
if (Number(value) > Number(max)) {
$('#' + id).val(max);
showInfoDialog("warning", "", $.i18n('edt_msg_error_maximum_incl', max));
return max;
}
else if (Number(value) < Number(min)) {
$('#' + id).val(min);
showInfoDialog("warning", "", $.i18n('edt_msg_error_minimum_incl', min));
return min;
}
return value;
}
function readImg(input, cb) {
if (input.files && input.files[0]) {
var reader = new FileReader();
// inject fileName property
reader.fileName = input.files[0].name
reader.onload = function (e) {
cb(e.target.result, e.target.fileName);
}
reader.readAsDataURL(input.files[0]);
}
}
function isJsonString(str) {
try {
JSON.parse(str);
}
catch (e) {
return e;
}
return "";
}
const getObjectProperty = (obj, path) => path.split(".").reduce((o, key) => o && typeof o[key] !== 'undefined' ? o[key] : undefined, obj);
const setObjectProperty = (object, path, value) => {
const parts = path.split('.');
const limit = parts.length - 1;
for (let i = 0; i < limit; ++i) {
const key = parts[i];
if (key === "__proto__" || key === "constructor") continue;
object = object[key] ?? (object[key] = {});
}
const key = parts[limit];
object[key] = value;
};
function getLongPropertiesPath(path) {
if (path) {
var path = path.replace('root.', '');
const parts = path.split('.');
parts.forEach(function (part, index) {
this[index] += ".properties";
}, parts);
path = parts.join('.') + '.';
}
return path;
}
function createJsonEditor(container, schema, setconfig, usePanel, arrayre) {
$('#' + container).off();
$('#' + container).html("");
if (typeof arrayre === 'undefined')
arrayre = true;
var editor = new JSONEditor(document.getElementById(container),
{
theme: 'bootstrap3',
iconlib: "fontawesome4",
disable_collapse: 'true',
form_name_root: 'sa',
disable_edit_json: true,
disable_properties: true,
disable_array_reorder: arrayre,
no_additional_properties: true,
disable_array_delete_all_rows: true,
disable_array_delete_last_row: true,
access: storedAccess,
schema: {
title: '',
properties: schema
}
});
if (usePanel) {
$('#' + container + ' .well').first().removeClass('well well-sm');
$('#' + container + ' h4').first().remove();
$('#' + container + ' .well').first().removeClass('well well-sm');
}
if (setconfig) {
for (var key in editor.root.editors) {
editor.getEditor("root." + key).setValue(Object.assign({}, editor.getEditor("root." + key).value, window.serverConfig[key]));
}
}
return editor;
}
function updateJsonEditorSelection(rootEditor, path, key, addElements, newEnumVals, newTitelVals, newDefaultVal, addSelect, addCustom, addCustomAsFirst, customText) {
var editor = rootEditor.getEditor(path);
var orginalProperties = editor.schema.properties[key];
var orginalWatchFunctions = rootEditor.watchlist[path + "." + key];
rootEditor.unwatch(path + "." + key);
var newSchema = [];
newSchema[key] =
{
"type": "string",
"enum": [],
"required": true,
"options": { "enum_titles": [], "infoText": "" },
"propertyOrder": 1
};
//Add additional elements to overwrite defaults
for (var item in addElements) {
newSchema[key][item] = addElements[item];
}
if (orginalProperties) {
if (orginalProperties["title"]) {
newSchema[key]["title"] = orginalProperties["title"];
}
if (orginalProperties["options"] && orginalProperties["options"]["infoText"]) {
newSchema[key]["options"]["infoText"] = orginalProperties["options"]["infoText"];
}
if (orginalProperties["propertyOrder"]) {
newSchema[key]["propertyOrder"] = orginalProperties["propertyOrder"];
}
}
if (addCustom) {
if (newTitelVals.length === 0) {
newTitelVals = [...newEnumVals];
}
if (!!!customText) {
customText = "edt_conf_enum_custom";
}
if (addCustomAsFirst) {
newEnumVals.unshift("CUSTOM");
newTitelVals.unshift(customText);
} else {
newEnumVals.push("CUSTOM");
newTitelVals.push(customText);
}
if (newSchema[key].options.infoText) {
var customInfoText = newSchema[key].options.infoText + "_custom";
newSchema[key].options.infoText = customInfoText;
}
}
if (addSelect) {
newEnumVals.unshift("SELECT");
newTitelVals.unshift("edt_conf_enum_please_select");
newDefaultVal = "SELECT";
}
if (newEnumVals) {
newSchema[key]["enum"] = newEnumVals;
}
if (newTitelVals) {
newSchema[key]["options"]["enum_titles"] = newTitelVals;
}
if (newDefaultVal) {
newSchema[key]["default"] = newDefaultVal;
}
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
editor.addObjectProperty(key);
if (orginalWatchFunctions) {
for (var i = 0; i < orginalWatchFunctions.length; i++) {
rootEditor.watch(path + "." + key, orginalWatchFunctions[i]);
}
}
rootEditor.notifyWatchers(path + "." + key);
}
function updateJsonEditorMultiSelection(rootEditor, path, key, addElements, newEnumVals, newTitelVals, newDefaultVal) {
var editor = rootEditor.getEditor(path);
var orginalProperties = editor.schema.properties[key];
var orginalWatchFunctions = rootEditor.watchlist[path + "." + key];
rootEditor.unwatch(path + "." + key);
var newSchema = [];
newSchema[key] =
{
"type": "array",
"format": "select",
"items": {
"type": "string",
"enum": [],
"options": { "enum_titles": [] },
},
"options": { "infoText": "" },
"default": [],
"propertyOrder": 1
};
//Add additional elements to overwrite defaults
for (var item in addElements) {
newSchema[key][item] = addElements[item];
}
if (orginalProperties) {
if (orginalProperties["title"]) {
newSchema[key]["title"] = orginalProperties["title"];
}
if (orginalProperties["options"] && orginalProperties["options"]["infoText"]) {
newSchema[key]["options"]["infoText"] = orginalProperties["options"]["infoText"];
}
if (orginalProperties["propertyOrder"]) {
newSchema[key]["propertyOrder"] = orginalProperties["propertyOrder"];
}
}
if (newEnumVals) {
newSchema[key]["items"]["enum"] = newEnumVals;
}
if (newTitelVals) {
newSchema[key]["items"]["options"]["enum_titles"] = newTitelVals;
}
if (newDefaultVal) {
newSchema[key]["default"] = newDefaultVal;
}
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
editor.addObjectProperty(key);
if (orginalWatchFunctions) {
for (var i = 0; i < orginalWatchFunctions.length; i++) {
rootEditor.watch(path + "." + key, orginalWatchFunctions[i]);
}
}
rootEditor.notifyWatchers(path + "." + key);
}
function updateJsonEditorRange(rootEditor, path, key, minimum, maximum, defaultValue, step, clear) {
var editor = rootEditor.getEditor(path);
//Preserve current value when updating range
var currentValue = rootEditor.getEditor(path + "." + key).getValue();
var orginalProperties = editor.schema.properties[key];
var newSchema = [];
newSchema[key] = orginalProperties;
if (clear) {
delete newSchema[key]["minimum"];
delete newSchema[key]["maximum"];
delete newSchema[key]["default"];
delete newSchema[key]["step"];
}
if (typeof minimum !== "undefined") {
newSchema[key]["minimum"] = minimum;
}
if (typeof maximum !== "undefined") {
newSchema[key]["maximum"] = maximum;
}
if (typeof defaultValue !== "undefined") {
newSchema[key]["default"] = defaultValue;
currentValue = defaultValue;
}
if (typeof step !== "undefined") {
newSchema[key]["step"] = step;
}
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
editor.addObjectProperty(key);
// Restore current (new default) value for new range
rootEditor.getEditor(path + "." + key).setValue(currentValue);
}
function addJsonEditorHostValidation() {
JSONEditor.defaults.custom_validators.push(function (schema, value, path) {
var errors = [];
if (!jQuery.isEmptyObject(value)) {
switch (schema.format) {
case "hostname_or_ip":
if (!isValidHostnameOrIP(value)) {
errors.push({
path: path,
property: 'format',
message: $.i18n('edt_msgcust_error_hostname_ip')
});
}
break;
case "hostname_or_ip4":
if (!isValidHostnameOrIP4(value)) {
errors.push({
path: path,
property: 'format',
message: $.i18n('edt_msgcust_error_hostname_ip4')
});
}
break;
//Remove, when new json-editor 2.x is used
case "ipv4":
if (!isValidIPv4(value)) {
errors.push({
path: path,
property: 'format',
message: $.i18n('edt_msg_error_ipv4')
});
}
break;
case "ipv6":
if (!isValidIPv6(value)) {
errors.push({
path: path,
property: 'format',
message: $.i18n('edt_msg_error_ipv6')
});
}
break;
case "hostname":
if (!isValidHostname(value)) {
errors.push({
path: path,
property: 'format',
message: $.i18n('edt_msg_error_hostname')
});
}
break;
default:
}
}
return errors;
});
}
function buildWL(link, linkt, cl) {
var baseLink = "https://docs.hyperion-project.org/";
var lang;
if (typeof linkt == "undefined")
linkt = "Placeholder";
if (storedLang == "de" || navigator.locale == "de")
lang = "de";
else
lang = "en";
if (cl === true) {
linkt = $.i18n(linkt);
return '<div class="bs-callout bs-callout-primary"><h4>' + linkt + '</h4>' + $.i18n('general_wiki_moreto', linkt) + ': <a href="' + baseLink + lang + '/' + link + '" target="_blank">' + linkt + '<a></div>'
}
else
return ': <a href="' + baseLink + lang + '/' + link + '" target="_blank">' + linkt + '<a>';
}
function rgbToHex(rgb) {
if (rgb.length == 3) {
return "#" +
("0" + parseInt(rgb[0], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2], 10).toString(16)).slice(-2);
}
else
debugMessage('rgbToHex: Given rgb is no array or has wrong length');
}
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : {
r: 0,
g: 0,
b: 0
};
}
/*
Show a notification
@param type Valid types are "info","success","warning","danger"
@param message The message to show
@param title A title (optional)
@param addhtml Add custom html to the notification end
*/
function showNotification(type, message, title = "", addhtml = "") {
if (title == "") {
switch (type) {
case "info":
title = $.i18n('infoDialog_general_info_title');
break;
case "success":
title = $.i18n('infoDialog_general_success_title');
break;
case "warning":
title = $.i18n('infoDialog_general_warning_title');
break;
case "danger":
title = $.i18n('infoDialog_general_error_title');
break;
}
}
$.notify({
// options
title: title,
message: message
}, {
// settings
type: type,
animate: {
enter: 'animate__animated animate__fadeInDown',
exit: 'animate__animated animate__fadeOutUp'
},
placement: {
align: 'center'
},
mouse_over: 'pause',
template: '<div data-notify="container" class="bg-w col-md-6 bs-callout bs-callout-{0}" role="alert">' +
'<button type="button" aria-hidden="true" class="close" data-notify="dismiss">×</button>' +
'<span data-notify="icon"></span> ' +
'<h4 data-notify="title">{1}</h4> ' +
'<span data-notify="message">{2}</span>' +
addhtml +
'<div class="progress" data-notify="progressbar">' +
'<div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>' +
'</div>' +
'<a href="{3}" target="{4}" data-notify="url"></a>' +
'</div>'
});
}
function createCP(id, color, cb) {
if (Array.isArray(color))
color = rgbToHex(color);
else if (color == "undefined")
color = "#AA3399";
if (color.startsWith("#")) {
$('#' + id).colorpicker({
format: 'rgb',
customClass: 'colorpicker-2x',
color: color,
sliders: {
saturation: {
maxLeft: 200,
maxTop: 200
},
hue: {
maxTop: 200
},
}
});
$('#' + id).colorpicker().on('changeColor', function (e) {
var rgb = e.color.toRGB();
var hex = e.color.toHex();
cb(rgb, hex, e);
});
}
else
debugMessage('createCP: Given color is not legit');
}
// Creates a table with thead and tbody ids
// @param string hid : a class for thead
// @param string bid : a class for tbody
// @param string cont : a container id to html() the table
// @param string bless: if true the table is borderless
function createTable(hid, bid, cont, bless, tclass) {
var table = document.createElement('table');
var thead = document.createElement('thead');
var tbody = document.createElement('tbody');
table.className = "table";
if (bless === true)
table.className += " borderless";
if (typeof tclass !== "undefined")
table.className += " " + tclass;
table.style.marginBottom = "0px";
if (hid != "")
thead.className = hid;
tbody.className = bid;
if (hid != "")
table.appendChild(thead);
table.appendChild(tbody);
$('#' + cont).append(table);
}
// Creates a table row <tr>
// @param array list :innerHTML content for <td>/<th>
// @param bool head :if null or false it's body
// @param bool align :if null or false no alignment
//
// @return : <tr> with <td> or <th> as child(s)
function createTableRow(list, head, align) {
var row = document.createElement('tr');
for (var i = 0; i < list.length; i++) {
if (head === true)
var el = document.createElement('th');
else
var el = document.createElement('td');
if (align)
el.style.verticalAlign = "middle";
var purifyConfig = {
ADD_TAGS: ['button'],
ADD_ATTR: ['onclick']
};
el.innerHTML = DOMPurify.sanitize(list[i], purifyConfig);
row.appendChild(el);
}
return row;
}
function createRow(id) {
var el = document.createElement('div');
el.className = "row";
el.setAttribute('id', id);
return el;
}
function createOptPanel(phicon, phead, bodyid, footerid, css, panelId) {
phead = '<i class="fa ' + phicon + ' fa-fw"></i>' + phead;
var pfooter = document.createElement('button');
pfooter.className = "btn btn-primary";
pfooter.setAttribute("id", footerid);
pfooter.innerHTML = '<i class="fa fa-fw fa-save"></i>' + $.i18n('general_button_savesettings');
return createPanel(phead, "", pfooter, "panel-default", bodyid, css, panelId);
}
function compareTwoValues(key1, key2, order = 'asc') {
return function innerSort(a, b) {
if (!a.hasOwnProperty(key1) || !b.hasOwnProperty(key1)) {
// property key1 doesn't exist on either object
return 0;
}
const varA1 = (typeof a[key1] === 'string')
? a[key1].toUpperCase() : a[key1];
const varB1 = (typeof b[key1] === 'string')
? b[key1].toUpperCase() : b[key1];
let comparison = 0;
if (varA1 > varB1) {
comparison = 1;
} else {
if (varA1 < varB1) {
comparison = -1;
} else {
if (!a.hasOwnProperty(key2) || !b.hasOwnProperty(key2)) {
// property key2 doesn't exist on either object
return 0;
}
const varA2 = (typeof a[key2] === 'string')
? a[key2].toUpperCase() : a[key2];
const varB2 = (typeof b[key1] === 'string')
? b[key2].toUpperCase() : b[key2];
if (varA2 > varB2) {
comparison = 1;
} else {
comparison = -1;
}
}
}
return (
(order === 'desc') ? (comparison * -1) : comparison
);
};
}
function sortProperties(list) {
for (var key in list) {
list[key].key = key;
}
list = $.map(list, function (value, index) {
return [value];
});
return list.sort(function (a, b) {
return a.propertyOrder - b.propertyOrder;
});
}
function createHelpTable(list, phead, panelId) {
var table = document.createElement('table');
var thead = document.createElement('thead');
var tbody = document.createElement('tbody');
list = sortProperties(list);
phead = '<i class="fa fa-fw fa-info-circle"></i>' + phead + ' ' + $.i18n("conf_helptable_expl");
table.className = 'table table-hover borderless';
thead.appendChild(createTableRow([$.i18n('conf_helptable_option'), $.i18n('conf_helptable_expl')], true, false));
for (var key in list) {
if (list[key].access != 'system') {
// break one iteration (in the loop), if the schema has the entry hidden=true
if ("options" in list[key] && "hidden" in list[key].options && (list[key].options.hidden))
continue;
if ("access" in list[key] && ((list[key].access == "advanced" && storedAccess == "default") || (list[key].access == "expert" && storedAccess != "expert")))
continue;
var text = list[key].title.replace('title', 'expl');
tbody.appendChild(createTableRow([$.i18n(list[key].title), $.i18n(text)], false, false));
if (list[key].items && list[key].items.properties) {
var ilist = sortProperties(list[key].items.properties);
for (var ikey in ilist) {
// break one iteration (in the loop), if the schema has the entry hidden=true
if ("options" in ilist[ikey] && "hidden" in ilist[ikey].options && (ilist[ikey].options.hidden))
continue;
if ("access" in ilist[ikey] && ((ilist[ikey].access == "advanced" && storedAccess == "default") || (ilist[ikey].access == "expert" && storedAccess != "expert")))
continue;
var itext = ilist[ikey].title.replace('title', 'expl');
tbody.appendChild(createTableRow([$.i18n(ilist[ikey].title), $.i18n(itext)], false, false));
}
}
}
}
table.appendChild(thead);
table.appendChild(tbody);
return createPanel(phead, table, undefined, undefined, undefined, undefined, panelId);
}
function createPanel(head, body, footer, type, bodyid, css, panelId) {
var cont = document.createElement('div');
var p = document.createElement('div');
var phead = document.createElement('div');
var pbody = document.createElement('div');
var pfooter = document.createElement('div');
cont.className = "col-lg-6";
if (typeof type == 'undefined')
type = 'panel-default';
p.className = 'panel ' + type;
if (typeof panelId != 'undefined') {
p.setAttribute("id", panelId);
}
phead.className = 'panel-heading ' + css;
pbody.className = 'panel-body';
pfooter.className = 'panel-footer';
phead.innerHTML = head;
if (typeof bodyid != 'undefined') {
pfooter.style.textAlign = 'right';
pbody.setAttribute("id", bodyid);
}
if (typeof body != 'undefined' && body != "")
pbody.appendChild(body);
if (typeof footer != 'undefined')
pfooter.appendChild(footer);
p.appendChild(phead);
p.appendChild(pbody);
if (typeof footer != 'undefined') {
pfooter.style.textAlign = "right";
p.appendChild(pfooter);
}
cont.appendChild(p);
return cont;
}
function createSelGroup(group) {
var el = document.createElement('optgroup');
el.setAttribute('label', group);
return el;
}
function createSelOpt(opt, title) {
var el = document.createElement('option');
el.setAttribute('value', opt);
if (typeof title == 'undefined')
el.innerHTML = opt;
else
el.innerHTML = title;
return el;
}
function createSel(array, group, split) {
if (array.length != 0) {
var el = createSelGroup(group);
for (var i = 0; i < array.length; i++) {
var opt;
if (split) {
opt = array[i].split(":")
opt = createSelOpt(opt[0], opt[1])
}
else
opt = createSelOpt(array[i])
el.appendChild(opt);
}
return el;
}
}
function performTranslation() {
$('[data-i18n]').i18n();
}
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function getReleases(callback) {
$.ajax({
url: window.gitHubReleaseApiUrl,
method: 'get',
error: function (XMLHttpRequest, textStatus, errorThrown) {
callback(false);
},
success: function (releases) {
window.gitHubVersionList = releases;
var highestRelease = {
tag_name: '0.0.0'
};
var highestAlphaRelease = {
tag_name: '0.0.0'
};
var highestBetaRelease = {
tag_name: '0.0.0'
};
var highestRcRelease = {
tag_name: '0.0.0'
};
for (var i in releases) {
//drafts will be ignored
if (releases[i].draft)
continue;
if (releases[i].tag_name.includes('alpha')) {
if (sem = semverLite.gt(releases[i].tag_name, highestAlphaRelease.tag_name))
highestAlphaRelease = releases[i];
}
else if (releases[i].tag_name.includes('beta')) {
if (sem = semverLite.gt(releases[i].tag_name, highestBetaRelease.tag_name))
highestBetaRelease = releases[i];
}
else if (releases[i].tag_name.includes('rc')) {
if (semverLite.gt(releases[i].tag_name, highestRcRelease.tag_name))
highestRcRelease = releases[i];
}
else {
if (semverLite.gt(releases[i].tag_name, highestRelease.tag_name))
highestRelease = releases[i];
}
}
window.latestStableVersion = highestRelease;
window.latestBetaVersion = highestBetaRelease;
window.latestAlphaVersion = highestAlphaRelease;
window.latestRcVersion = highestRcRelease;
if (window.serverConfig.general.watchedVersionBranch == "Beta" && semverLite.gt(highestBetaRelease.tag_name, highestRelease.tag_name))
window.latestVersion = highestBetaRelease;
else
window.latestVersion = highestRelease;
if (window.serverConfig.general.watchedVersionBranch == "Alpha" && semverLite.gt(highestAlphaRelease.tag_name, highestBetaRelease.tag_name))
window.latestVersion = highestAlphaRelease;
if (window.serverConfig.general.watchedVersionBranch == "Alpha" && semverLite.lt(highestAlphaRelease.tag_name, highestBetaRelease.tag_name))
window.latestVersion = highestBetaRelease;
//next two if statements are only necessary if we don't have a beta or stable release. We need one alpha release at least
if (window.latestVersion.tag_name == '0.0.0' && highestBetaRelease.tag_name != '0.0.0')
window.latestVersion = highestBetaRelease;
if (window.latestVersion.tag_name == '0.0.0' && highestAlphaRelease.tag_name != '0.0.0')
window.latestVersion = highestAlphaRelease;
callback(true);
}
});
}
function getSystemInfo() {
var sys = window.sysInfo.system;
var shy = window.sysInfo.hyperion;
var info = "Hyperion Server:\n";
info += '- Build: ' + shy.build + '\n';
info += '- Build time: ' + shy.time + '\n';
info += '- Git Remote: ' + shy.gitremote + '\n';
info += '- Version: ' + shy.version + '\n';
info += '- UI Lang: ' + storedLang + ' (BrowserLang: ' + navigator.language + ')\n';
info += '- UI Access: ' + storedAccess + '\n';
//info += '- Log lvl: ' + window.serverConfig.logger.level + '\n';
info += '- Avail Screen Cap.: ' + window.serverInfo.grabbers.screen.available + '\n';
info += '- Avail Video Cap.: ' + window.serverInfo.grabbers.video.available + '\n';
Audio Grabber Feature (#1570) * Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Custom Effects - Clean-ups and Enhancements (#1163) * Cleanup EffectFileHandler * Support Custom Effect Schemas and align EffectFileHandler * Change back to colon prefix for system effects * WebSockets - Fix error in handling fragmented frames * Correct missing colon updates * Update json with image file location for custom gif effects * Image effect deletion - considere full filename is stored in JSON * Correct selection lists indentions Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Commented setVideoMode from AudioGrabber. Linux Threading changes. Implementing new API Continuing to implement audio into new APIs Fixed Audio Grabber for DirectSound on Windows Fixed UI for Audio Grabber Configuration Default AUDIO to off unless specified. fixed missing #ifdef for audio grabber. Added logic to calculate a dynamic multiplier from the signal input. Updating linux api for discovering devices. Fixed HTML/JS issues with view. Fixed NPE in Windows. Disabled setting thread priority in linux. updated the schema options check to pass through hidden states and commented the change. Updated grabber start conditions Updated Audio grabber to instantiate similar to video grabber Updated windows grabber to set "started" flag to false when shutting down. Removed "tryStart" to prevent enabling audio capture unnecessarily. Fixing instance audio grabber device configuration Added configurable resolution Reduced tolerance to 5% Fixed issue where grabber failed for additional instances when "start" was called multiple times. Fixed resolution calculation Change averaging algorithm to prevent overflowing the sum. Updated logic to stop audio grabber when disabled. Fix integer casting and rounding. Restart grabber on configuration change. Fix missing include/grabber/AudioGrabber. Disable tolerance. Added configurable tolerance. Fixed tolerance algorithm. reset multiplier on configuration change. Line Endings Proposed change and questions/request to fix implementing more of LordGrey's suggestions. Fix mode for snd_pcm_open. Latest ALSA uses SND_PCM_NONBLOCK instead of SND_PCM_OPEN_NONBLOCK defaulted multiplier to 0 "auto" defaulted tolerance to 20% changed 100 to 100.0 for pixel value percentage calculation to fix value from being 0. missed a 100 as a double so precision isn't lost during math operation. Fix Windows grabber and further cleanups Enable Audio grabbing in standard build Remove empty methods Fix audio capture priority setting Remove unused code Clean-up default config Allow additional json-editor attributes Allow multiple effects and resetting to defaults Correct default values Allow to build for Qt < 5.14 Update CodeQL build dependency Update build dependencies Remove effect1 placeholder * Renamed uvMeter to VU Meter (Volume Unit) - Fixed issues flagged by code scanning bot. * Moved stop call into destructor of implementing class. * Removed commented linux audio channel configuration logic. --------- Co-authored-by: Michael Rochelle <michael@j2inn.com>
2023-02-19 09:36:39 +01:00
info += '- Avail Audio Cap.: ' + window.serverInfo.grabbers.audio.available + '\n';
info += '- Avail Services: ' + window.serverInfo.services + '\n';
info += '- Config path: ' + shy.rootPath + '\n';
info += '- Database: ' + (shy.readOnlyMode ? "ready-only" : "read/write") + '\n';
info += '\n';
info += 'Hyperion Server OS:\n';
info += '- Distribution: ' + sys.prettyName + '\n';
info += '- Architecture: ' + sys.architecture + '\n';
if (sys.cpuModelName)
info += '- CPU Model: ' + sys.cpuModelName + '\n';
if (sys.cpuModelType)
info += '- CPU Type: ' + sys.cpuModelType + '\n';
if (sys.cpuRevision)
info += '- CPU Revision: ' + sys.cpuRevision + '\n';
if (sys.cpuHardware)
info += '- CPU Hardware: ' + sys.cpuHardware + '\n';
info += '- Kernel: ' + sys.kernelType + ' (' + sys.kernelVersion + ' (WS: ' + sys.wordSize + '))\n';
info += '- Root/Admin: ' + sys.isUserAdmin + '\n';
info += '- Qt Version: ' + sys.qtVersion + '\n';
if (jQuery.inArray("effectengine", window.serverInfo.services) !== -1) {
info += '- Python Version: ' + sys.pyVersion + '\n';
}
info += '- Browser: ' + navigator.userAgent;
return info;
}
function handleDarkMode() {
$("<link/>", {
rel: "stylesheet",
type: "text/css",
href: "../css/darkMode.css"
}).appendTo("head");
setStorage("darkMode", "on");
$('#btn_darkmode_icon').removeClass('fa fa-moon-o');
$('#btn_darkmode_icon').addClass('mdi mdi-white-balance-sunny');
$('#navbar_brand_logo').attr("src", 'img/hyperion/logo_negativ.png');
}
function isAccessLevelCompliant(accessLevel) {
var isOK = true;
if (accessLevel) {
if (accessLevel === 'system') {
isOK = false;
}
else if (accessLevel === 'advanced' && storedAccess === 'default') {
isOK = false;
}
else if (accessLevel === 'expert' && storedAccess !== 'expert') {
isOK = false;
}
}
return isOK
}
function showInputOptions(path, elements, state) {
if (!path.startsWith("root.")) {
path = ["root", path].join('.');
}
for (var i = 0; i < elements.length; i++) {
$('[data-schemapath="' + path + '.' + elements[i] + '"]').toggle(state);
}
}
function showInputOptionForItem(editor, path, item, state) {
//Get access level for full path and item
var accessLevel = getObjectProperty(editor.schema.properties, getLongPropertiesPath(path) + item + ".access");
// Enable element only, if access level compliant
if (!state || isAccessLevelCompliant(accessLevel)) {
if (!path) {
debugger;
path = editor.path;
}
showInputOptions(path, [item], state);
}
}
function showInputOptionsForKey(editor, item, showForKeys, state) {
var elements = [];
var keysToshow = [];
if (Array.isArray(showForKeys)) {
keysToshow = showForKeys;
} else {
if (typeof showForKeys === 'string') {
keysToshow.push(showForKeys);
} else {
return;
}
}
Audio Grabber Feature (#1570) * Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Custom Effects - Clean-ups and Enhancements (#1163) * Cleanup EffectFileHandler * Support Custom Effect Schemas and align EffectFileHandler * Change back to colon prefix for system effects * WebSockets - Fix error in handling fragmented frames * Correct missing colon updates * Update json with image file location for custom gif effects * Image effect deletion - considere full filename is stored in JSON * Correct selection lists indentions Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Commented setVideoMode from AudioGrabber. Linux Threading changes. Implementing new API Continuing to implement audio into new APIs Fixed Audio Grabber for DirectSound on Windows Fixed UI for Audio Grabber Configuration Default AUDIO to off unless specified. fixed missing #ifdef for audio grabber. Added logic to calculate a dynamic multiplier from the signal input. Updating linux api for discovering devices. Fixed HTML/JS issues with view. Fixed NPE in Windows. Disabled setting thread priority in linux. updated the schema options check to pass through hidden states and commented the change. Updated grabber start conditions Updated Audio grabber to instantiate similar to video grabber Updated windows grabber to set "started" flag to false when shutting down. Removed "tryStart" to prevent enabling audio capture unnecessarily. Fixing instance audio grabber device configuration Added configurable resolution Reduced tolerance to 5% Fixed issue where grabber failed for additional instances when "start" was called multiple times. Fixed resolution calculation Change averaging algorithm to prevent overflowing the sum. Updated logic to stop audio grabber when disabled. Fix integer casting and rounding. Restart grabber on configuration change. Fix missing include/grabber/AudioGrabber. Disable tolerance. Added configurable tolerance. Fixed tolerance algorithm. reset multiplier on configuration change. Line Endings Proposed change and questions/request to fix implementing more of LordGrey's suggestions. Fix mode for snd_pcm_open. Latest ALSA uses SND_PCM_NONBLOCK instead of SND_PCM_OPEN_NONBLOCK defaulted multiplier to 0 "auto" defaulted tolerance to 20% changed 100 to 100.0 for pixel value percentage calculation to fix value from being 0. missed a 100 as a double so precision isn't lost during math operation. Fix Windows grabber and further cleanups Enable Audio grabbing in standard build Remove empty methods Fix audio capture priority setting Remove unused code Clean-up default config Allow additional json-editor attributes Allow multiple effects and resetting to defaults Correct default values Allow to build for Qt < 5.14 Update CodeQL build dependency Update build dependencies Remove effect1 placeholder * Renamed uvMeter to VU Meter (Volume Unit) - Fixed issues flagged by code scanning bot. * Moved stop call into destructor of implementing class. * Removed commented linux audio channel configuration logic. --------- Co-authored-by: Michael Rochelle <michael@j2inn.com>
2023-02-19 09:36:39 +01:00
for (let key in editor.schema.properties[item].properties) {
if ($.inArray(key, keysToshow) === -1) {
Audio Grabber Feature (#1570) * Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Custom Effects - Clean-ups and Enhancements (#1163) * Cleanup EffectFileHandler * Support Custom Effect Schemas and align EffectFileHandler * Change back to colon prefix for system effects * WebSockets - Fix error in handling fragmented frames * Correct missing colon updates * Update json with image file location for custom gif effects * Image effect deletion - considere full filename is stored in JSON * Correct selection lists indentions Creating Audio Grabber Creating Audio Grabber Creating Audio Grabber. Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer. Got Windows DirectSound Implementation working. Hardcoded basic VU Meter. Begin working on linux audio grabber implementation. Finished Linux Draft Implementation. Minor Mods to windows implementation. Windows: - Free memory used by device id. - Prevent starting audio if the grabber is disabled - More debug logging Linux: - Prevent starting audio if the grabber is disabled Added strings to english Removed "custom" from device selection Made hard-coded visualizer values configurable. wrote values to imageData with BGR priority to enable configurable values to be set in RGB format. created logic to support "Automatic" to enable the API to select the default device. Add language key for audio in "Remote Control" section. Removed audio configuration for number of channels. This was causing an error with some devices. Fixed logic to update capture while its active. Optimizing code . UI Tweaks Destructuring. Fixed build error on linux. Commented setVideoMode from AudioGrabber. Linux Threading changes. Implementing new API Continuing to implement audio into new APIs Fixed Audio Grabber for DirectSound on Windows Fixed UI for Audio Grabber Configuration Default AUDIO to off unless specified. fixed missing #ifdef for audio grabber. Added logic to calculate a dynamic multiplier from the signal input. Updating linux api for discovering devices. Fixed HTML/JS issues with view. Fixed NPE in Windows. Disabled setting thread priority in linux. updated the schema options check to pass through hidden states and commented the change. Updated grabber start conditions Updated Audio grabber to instantiate similar to video grabber Updated windows grabber to set "started" flag to false when shutting down. Removed "tryStart" to prevent enabling audio capture unnecessarily. Fixing instance audio grabber device configuration Added configurable resolution Reduced tolerance to 5% Fixed issue where grabber failed for additional instances when "start" was called multiple times. Fixed resolution calculation Change averaging algorithm to prevent overflowing the sum. Updated logic to stop audio grabber when disabled. Fix integer casting and rounding. Restart grabber on configuration change. Fix missing include/grabber/AudioGrabber. Disable tolerance. Added configurable tolerance. Fixed tolerance algorithm. reset multiplier on configuration change. Line Endings Proposed change and questions/request to fix implementing more of LordGrey's suggestions. Fix mode for snd_pcm_open. Latest ALSA uses SND_PCM_NONBLOCK instead of SND_PCM_OPEN_NONBLOCK defaulted multiplier to 0 "auto" defaulted tolerance to 20% changed 100 to 100.0 for pixel value percentage calculation to fix value from being 0. missed a 100 as a double so precision isn't lost during math operation. Fix Windows grabber and further cleanups Enable Audio grabbing in standard build Remove empty methods Fix audio capture priority setting Remove unused code Clean-up default config Allow additional json-editor attributes Allow multiple effects and resetting to defaults Correct default values Allow to build for Qt < 5.14 Update CodeQL build dependency Update build dependencies Remove effect1 placeholder * Renamed uvMeter to VU Meter (Volume Unit) - Fixed issues flagged by code scanning bot. * Moved stop call into destructor of implementing class. * Removed commented linux audio channel configuration logic. --------- Co-authored-by: Michael Rochelle <michael@j2inn.com>
2023-02-19 09:36:39 +01:00
const accessLevel = editor.schema.properties[item].properties[key].access;
var hidden = false;
if (editor.schema.properties[item].properties[key].options) {
hidden = editor.schema.properties[item].properties[key].options.hidden;
if (typeof hidden === 'undefined') {
hidden = false;
}
}
//Always disable all elements, but only enable elements, if access level compliant
if (!state || isAccessLevelCompliant(accessLevel)) {
if (!hidden) {
elements.push(key);
}
}
}
}
showInputOptions(item, elements, state);
}
function encodeHTML(s) {
return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}
function isValidIPv4(value) {
const parts = value.split('.')
if (parts.length !== 4) {
return false;
}
for (let part of parts) {
if (isNaN(part) || part < 0 || part > 255) {
return false;
}
}
return true;
}
function isValidIPv6(value) {
if (value.match(
'^(?:(?:(?:[a-fA-F0-9]{1,4}:){6}|(?=(?:[a-fA-F0-9]{0,4}:){2,6}(?:[0-9]{1,3}.){3}[0-9]{1,3}$)(([0-9a-fA-F]{1,4}:){1,5}|:)((:[0-9a-fA-F]{1,4}){1,5}:|:)|::(?:[a-fA-F0-9]{1,4}:){5})(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])|(?:[a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}|(?=(?:[a-fA-F0-9]{0,4}:){0,7}[a-fA-F0-9]{0,4}$)(([0-9a-fA-F]{1,4}:){1,7}|:)((:[0-9a-fA-F]{1,4}){1,7}|:)|(?:[a-fA-F0-9]{1,4}:){7}:|:(:[a-fA-F0-9]{1,4}){7})$'
))
return true;
else
return false;
}
function isValidHostname(value) {
if (value.match(
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$'
))
return true;
else
return false;
}
function isValidServicename(value) {
if (value.match(
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9 -]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$'
))
return true;
else
return false;
}
function isValidHostnameOrIP4(value) {
return (isValidHostname(value) || isValidIPv4(value));
}
function isValidHostnameOrIP(value) {
return (isValidHostnameOrIP4(value) || isValidIPv6(value) || isValidServicename(value));
}