mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Details coming soon.
This commit is contained in:
parent
e3be03ea73
commit
d762aa2f3e
@ -416,6 +416,7 @@
|
|||||||
"edt_conf_enum_PAL" : "PAL",
|
"edt_conf_enum_PAL" : "PAL",
|
||||||
"edt_conf_enum_NTSC" : "NTSC",
|
"edt_conf_enum_NTSC" : "NTSC",
|
||||||
"edt_conf_enum_SECAM" : "SECAM",
|
"edt_conf_enum_SECAM" : "SECAM",
|
||||||
|
"edt_conf_enum_NO_CHANGE" : "Auto",
|
||||||
"edt_conf_enum_logsilent" : "Stille",
|
"edt_conf_enum_logsilent" : "Stille",
|
||||||
"edt_conf_enum_logwarn" : "Warnung",
|
"edt_conf_enum_logwarn" : "Warnung",
|
||||||
"edt_conf_enum_logverbose" : "Ausführlich",
|
"edt_conf_enum_logverbose" : "Ausführlich",
|
||||||
@ -486,14 +487,8 @@
|
|||||||
"edt_conf_v4l2_input_expl" : "Der Eingang des Pfades.",
|
"edt_conf_v4l2_input_expl" : "Der Eingang des Pfades.",
|
||||||
"edt_conf_v4l2_standard_title" : "Videoformat",
|
"edt_conf_v4l2_standard_title" : "Videoformat",
|
||||||
"edt_conf_v4l2_standard_expl" : "Wähle das passende Videoformat deiner Region.",
|
"edt_conf_v4l2_standard_expl" : "Wähle das passende Videoformat deiner Region.",
|
||||||
"edt_conf_v4l2_width_title" : "Breite",
|
"edt_conf_v4l2_sizeDecimation_title" : "Bildverkleinerung Faktor",
|
||||||
"edt_conf_v4l2_width_expl" : "Die Breite des Bildes. (-1 = Automatische Breitenbestimmung)",
|
"edt_conf_v4l2_sizeDecimation_expl" : "Der Faktor der Bildverkleinerung ausgehend der von der ursprünglichen Größe, 1 bedeutet keine Änderung (originales Bild).",
|
||||||
"edt_conf_v4l2_height_title" : "Höhe",
|
|
||||||
"edt_conf_v4l2_height_expl" : "Die Höhes des Bildes. (-1 = Automatische Höhenbestimmung)",
|
|
||||||
"edt_conf_v4l2_frameDecimation_title" : "Bildverkleinerung",
|
|
||||||
"edt_conf_v4l2_frameDecimation_expl" : "Der Faktor der Bildverkleinerung",
|
|
||||||
"edt_conf_v4l2_sizeDecimation_title" : "Größenänderung",
|
|
||||||
"edt_conf_v4l2_sizeDecimation_expl" : "Der Faktor der Größenänderung",
|
|
||||||
"edt_conf_v4l2_cropLeft_title" : "Entferne links",
|
"edt_conf_v4l2_cropLeft_title" : "Entferne links",
|
||||||
"edt_conf_v4l2_cropLeft_expl" : "Anzahl der Pixel auf der linken Seite die vom Bild entfernt werden.",
|
"edt_conf_v4l2_cropLeft_expl" : "Anzahl der Pixel auf der linken Seite die vom Bild entfernt werden.",
|
||||||
"edt_conf_v4l2_cropRight_title" : "Entferne rechts",
|
"edt_conf_v4l2_cropRight_title" : "Entferne rechts",
|
||||||
@ -503,7 +498,7 @@
|
|||||||
"edt_conf_v4l2_cropBottom_title" : "Entferne unten",
|
"edt_conf_v4l2_cropBottom_title" : "Entferne unten",
|
||||||
"edt_conf_v4l2_cropBottom_expl" : "Anzahl der Pixel auf der unteren Seite die vom Bild entfernt werden.",
|
"edt_conf_v4l2_cropBottom_expl" : "Anzahl der Pixel auf der unteren Seite die vom Bild entfernt werden.",
|
||||||
"edt_conf_v4l2_signalDetection_title" : "Signal Erkennung",
|
"edt_conf_v4l2_signalDetection_title" : "Signal Erkennung",
|
||||||
"edt_conf_v4l2_signalDetection_expl" : "Wenn aktiviert, wird die USB Aufnahme temporär bei \"kein Signal\" abgeschalten. Das Bild muss dazu 4 Sekunden lang unter die Schwellwerte fallen.",
|
"edt_conf_v4l2_signalDetection_expl" : "Wenn aktiviert, wird die USB Aufnahme temporär bei \"kein Signal\" abgeschalten.",
|
||||||
"edt_conf_v4l2_redSignalThreshold_title" : "Rote Signalschwelle",
|
"edt_conf_v4l2_redSignalThreshold_title" : "Rote Signalschwelle",
|
||||||
"edt_conf_v4l2_redSignalThreshold_expl" : "Je höher die rote Schwelle je eher wird abgeschalten bei entsprechendem rot-Anteil.",
|
"edt_conf_v4l2_redSignalThreshold_expl" : "Je höher die rote Schwelle je eher wird abgeschalten bei entsprechendem rot-Anteil.",
|
||||||
"edt_conf_v4l2_greenSignalThreshold_title" : "Grüne Signalschwelle",
|
"edt_conf_v4l2_greenSignalThreshold_title" : "Grüne Signalschwelle",
|
||||||
@ -523,16 +518,12 @@
|
|||||||
"edt_conf_fg_type_expl" : "Art der Plattform Aufnahme, standard ist 'auto'",
|
"edt_conf_fg_type_expl" : "Art der Plattform Aufnahme, standard ist 'auto'",
|
||||||
"edt_conf_fg_frequency_Hz_title" : "Aufnahmefrequenz",
|
"edt_conf_fg_frequency_Hz_title" : "Aufnahmefrequenz",
|
||||||
"edt_conf_fg_frequency_Hz_expl" : "Wie schnell neue Bilder aufgenommen werden.",
|
"edt_conf_fg_frequency_Hz_expl" : "Wie schnell neue Bilder aufgenommen werden.",
|
||||||
"edt_conf_fg_horizontalPixelDecimation_title" : "Horizontale Pixelreduzierung",
|
|
||||||
"edt_conf_fg_horizontalPixelDecimation_expl" : "Horizontale Pixelreduzierung (Faktor)",
|
|
||||||
"edt_conf_fg_useXGetImage_title" : "Nutze XGetImage",
|
|
||||||
"edt_conf_fg_useXGetImage_expl" : "XGetImage für aktuelle X11 desktops",
|
|
||||||
"edt_conf_fg_width_title" : "Breite",
|
"edt_conf_fg_width_title" : "Breite",
|
||||||
"edt_conf_fg_width_expl" : "Verkleinere Bild auf dieser Breite, da das Rohmaterial viel Leistung benötigen würde.",
|
"edt_conf_fg_width_expl" : "Verkleinere Bild auf dieser Breite, da das Rohmaterial viel Leistung benötigen würde.",
|
||||||
"edt_conf_fg_height_title" : "Höhe",
|
"edt_conf_fg_height_title" : "Höhe",
|
||||||
"edt_conf_fg_height_expl" : "Verkleinere Bild auf dieser Höhe, da das Rohmaterial viel Leistung benötigen würde.",
|
"edt_conf_fg_height_expl" : "Verkleinere Bild auf dieser Höhe, da das Rohmaterial viel Leistung benötigen würde.",
|
||||||
"edt_conf_fg_verticalPixelDecimation_title" : "Vertikale Pixelreduzierung",
|
"edt_conf_fg_pixelDecimation_title" : "Bildverkleinerung Faktor",
|
||||||
"edt_conf_fg_verticalPixelDecimation_expl" : "Vertikale Pixelreduzierung (Faktor)",
|
"edt_conf_fg_pixelDecimation_expl" : "Bildverkleinerung (Faktor) ausgehend von der original Größe. 1 für unveränderte/originale Größe.",
|
||||||
"edt_conf_fg_device_title" : "Device",
|
"edt_conf_fg_device_title" : "Device",
|
||||||
"edt_conf_fg_display_title" : "Display",
|
"edt_conf_fg_display_title" : "Display",
|
||||||
"edt_conf_fg_display_expl" : "Gebe an von welchem Desktop aufgenommen werden soll. (Multi Monitor Setup)",
|
"edt_conf_fg_display_expl" : "Gebe an von welchem Desktop aufgenommen werden soll. (Multi Monitor Setup)",
|
||||||
|
@ -417,6 +417,7 @@
|
|||||||
"edt_conf_enum_PAL" : "PAL",
|
"edt_conf_enum_PAL" : "PAL",
|
||||||
"edt_conf_enum_NTSC" : "NTSC",
|
"edt_conf_enum_NTSC" : "NTSC",
|
||||||
"edt_conf_enum_SECAM" : "SECAM",
|
"edt_conf_enum_SECAM" : "SECAM",
|
||||||
|
"edt_conf_enum_NO_CHANGE" : "Auto",
|
||||||
"edt_conf_enum_logsilent" : "Silent",
|
"edt_conf_enum_logsilent" : "Silent",
|
||||||
"edt_conf_enum_logwarn" : "Warning",
|
"edt_conf_enum_logwarn" : "Warning",
|
||||||
"edt_conf_enum_logverbose" : "Verbose",
|
"edt_conf_enum_logverbose" : "Verbose",
|
||||||
@ -504,7 +505,7 @@
|
|||||||
"edt_conf_v4l2_cropBottom_title" : "Crop bottom",
|
"edt_conf_v4l2_cropBottom_title" : "Crop bottom",
|
||||||
"edt_conf_v4l2_cropBottom_expl" : "Count of pixels on the bottom side that are removed from the picture.",
|
"edt_conf_v4l2_cropBottom_expl" : "Count of pixels on the bottom side that are removed from the picture.",
|
||||||
"edt_conf_v4l2_signalDetection_title" : "Signal detection",
|
"edt_conf_v4l2_signalDetection_title" : "Signal detection",
|
||||||
"edt_conf_v4l2_signalDetection_expl" : "If enabled, usb capture will be temporarily disabled when no signal was found. This will happen when the picture fall below the threshold value for a period of 4 seconds.",
|
"edt_conf_v4l2_signalDetection_expl" : "If enabled, usb capture will be temporarily disabled when no signal was found.",
|
||||||
"edt_conf_v4l2_redSignalThreshold_title" : "Red signal threshold",
|
"edt_conf_v4l2_redSignalThreshold_title" : "Red signal threshold",
|
||||||
"edt_conf_v4l2_redSignalThreshold_expl" : "Darkens low red values (recognized as black)",
|
"edt_conf_v4l2_redSignalThreshold_expl" : "Darkens low red values (recognized as black)",
|
||||||
"edt_conf_v4l2_greenSignalThreshold_title" : "Green signal threshold",
|
"edt_conf_v4l2_greenSignalThreshold_title" : "Green signal threshold",
|
||||||
@ -524,16 +525,12 @@
|
|||||||
"edt_conf_fg_type_expl" : "Type of platform capture, default is 'auto'",
|
"edt_conf_fg_type_expl" : "Type of platform capture, default is 'auto'",
|
||||||
"edt_conf_fg_frequency_Hz_title" : "Capture frequency",
|
"edt_conf_fg_frequency_Hz_title" : "Capture frequency",
|
||||||
"edt_conf_fg_frequency_Hz_expl" : "How fast new pictures are captured",
|
"edt_conf_fg_frequency_Hz_expl" : "How fast new pictures are captured",
|
||||||
"edt_conf_fg_horizontalPixelDecimation_title" : "Horizontal pixel decimation",
|
|
||||||
"edt_conf_fg_horizontalPixelDecimation_expl" : "Horizontal pixel decimation (factor)",
|
|
||||||
"edt_conf_fg_width_title" : "Width",
|
"edt_conf_fg_width_title" : "Width",
|
||||||
"edt_conf_fg_width_expl" : "Shrink picture to this width, as raw picture needs a lot of cpu time.",
|
"edt_conf_fg_width_expl" : "Shrink picture to this width, as raw picture needs a lot of cpu time.",
|
||||||
"edt_conf_fg_height_title" : "Height",
|
"edt_conf_fg_height_title" : "Height",
|
||||||
"edt_conf_fg_height_expl" : "Shrink picture to this height, as raw picture needs a lot of cpu time.",
|
"edt_conf_fg_height_expl" : "Shrink picture to this height, as raw picture needs a lot of cpu time.",
|
||||||
"edt_conf_fg_useXGetImage_title" : "Use XGetImage",
|
"edt_conf_fg_pixelDecimation_title" : "Picture decimation",
|
||||||
"edt_conf_fg_useXGetImage_expl" : "XGetImage for newer X11 desktops",
|
"edt_conf_fg_pixelDecimation_expl" : "Reduce picture size (factor) based on original size. A factor of 1 means no change",
|
||||||
"edt_conf_fg_verticalPixelDecimation_title" : "Vertical pixel decimation",
|
|
||||||
"edt_conf_fg_verticalPixelDecimation_expl" : "Vertical pixel decimation (factor)",
|
|
||||||
"edt_conf_fg_device_title" : "Device",
|
"edt_conf_fg_device_title" : "Device",
|
||||||
"edt_conf_fg_display_title" : "Display",
|
"edt_conf_fg_display_title" : "Display",
|
||||||
"edt_conf_fg_display_expl" : "Select which desktop should be captured (multi monitor setup)",
|
"edt_conf_fg_display_expl" : "Select which desktop should be captured (multi monitor setup)",
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
<script src="js/lib/bootstrap-colorpicker.min.js"></script>
|
<script src="js/lib/bootstrap-colorpicker.min.js"></script>
|
||||||
<link href="css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
<link href="css/bootstrap-colorpicker.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- BS Notfiy -->
|
||||||
|
<script src="js/lib/bootstrap-notify.min.js"></script>
|
||||||
|
|
||||||
<!-- JSONEditor -->
|
<!-- JSONEditor -->
|
||||||
<script src="js/lib/jsoneditor.js"></script>
|
<script src="js/lib/jsoneditor.js"></script>
|
||||||
|
|
||||||
|
@ -50,17 +50,18 @@ $(document).ready( function() {
|
|||||||
|
|
||||||
function updateComponents()
|
function updateComponents()
|
||||||
{
|
{
|
||||||
var components = serverInfo.components;
|
var components = comps;
|
||||||
components_html = "";
|
components_html = "";
|
||||||
for ( idx=0; idx<components.length;idx++)
|
for ( idx=0; idx<components.length;idx++)
|
||||||
{
|
{
|
||||||
|
if(components[idx].name != "ALL")
|
||||||
components_html += '<tr><td>'+$.i18n('general_comp_'+components[idx].name)+'</td><td><i class="fa fa-circle component-'+(components[idx].enabled?"on":"off")+'"></i></td></tr>';
|
components_html += '<tr><td>'+$.i18n('general_comp_'+components[idx].name)+'</td><td><i class="fa fa-circle component-'+(components[idx].enabled?"on":"off")+'"></i></td></tr>';
|
||||||
}
|
}
|
||||||
$("#tab_components").html(components_html);
|
$("#tab_components").html(components_html);
|
||||||
|
|
||||||
//info
|
//info
|
||||||
$('#dash_statush').html(serverInfo.hyperion.off? '<span style="color:red">'+$.i18n('general_btn_off')+'</span>':'<span style="color:green">'+$.i18n('general_btn_on')+'</span>');
|
$('#dash_statush').html(serverInfo.hyperion.enabled ? '<span style="color:green">'+$.i18n('general_btn_on')+'</span>' : '<span style="color:red">'+$.i18n('general_btn_off')+'</span>');
|
||||||
$('#btn_hsc').html(serverInfo.hyperion.off? '<button class="btn btn-sm btn-success" onClick="requestSetComponentState(\'ALL\',true)">'+$.i18n('dashboard_infobox_label_enableh')+'</button>' : '<button class="btn btn-sm btn-danger" onClick="requestSetComponentState(\'ALL\',false)">'+$.i18n('dashboard_infobox_label_disableh')+'</button>');
|
$('#btn_hsc').html(serverInfo.hyperion.enabled ? '<button class="btn btn-sm btn-danger" onClick="requestSetComponentState(\'ALL\',false)">'+$.i18n('dashboard_infobox_label_disableh')+'</button>' : '<button class="btn btn-sm btn-success" onClick="requestSetComponentState(\'ALL\',true)">'+$.i18n('dashboard_infobox_label_enableh')+'</button>');
|
||||||
}
|
}
|
||||||
|
|
||||||
// add more info
|
// add more info
|
||||||
@ -103,7 +104,7 @@ $(document).ready( function() {
|
|||||||
|
|
||||||
//interval update
|
//interval update
|
||||||
updateComponents();
|
updateComponents();
|
||||||
$(hyperion).on("cmd-serverinfo",updateComponents);
|
$(hyperion).on("components-updated",updateComponents);
|
||||||
|
|
||||||
if(showOptHelp)
|
if(showOptHelp)
|
||||||
createHintH("intro", $.i18n('dashboard_label_intro'), "dash_intro");
|
createHintH("intro", $.i18n('dashboard_label_intro'), "dash_intro");
|
||||||
|
@ -121,7 +121,10 @@ $(document).ready( function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//interval update
|
//interval update
|
||||||
$(hyperion).on("cmd-serverinfo",updateEffectlist);
|
$(hyperion).on("cmd-effects-update", function(event){
|
||||||
|
serverInfo.effects = event.response.data.effects
|
||||||
|
updateEffectlist();
|
||||||
|
});
|
||||||
|
|
||||||
removeOverlay();
|
removeOverlay();
|
||||||
});
|
});
|
||||||
|
@ -171,7 +171,10 @@ $(document).ready( function() {
|
|||||||
updateDelEffectlist();
|
updateDelEffectlist();
|
||||||
|
|
||||||
//interval update
|
//interval update
|
||||||
$(hyperion).on("cmd-serverinfo",updateDelEffectlist);
|
$(hyperion).on("cmd-effects-update", function(event){
|
||||||
|
serverInfo.effects = event.response.data.effects
|
||||||
|
updateDelEffectlist();
|
||||||
|
});
|
||||||
|
|
||||||
removeOverlay();
|
removeOverlay();
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ $(document).ready( function() {
|
|||||||
performTranslation();
|
performTranslation();
|
||||||
var conf_editor_v4l2 = null;
|
var conf_editor_v4l2 = null;
|
||||||
var conf_editor_fg = null;
|
var conf_editor_fg = null;
|
||||||
|
var conf_editor_instCapt = null;
|
||||||
|
|
||||||
function hideEl(el)
|
function hideEl(el)
|
||||||
{
|
{
|
||||||
@ -13,6 +14,11 @@ $(document).ready( function() {
|
|||||||
|
|
||||||
if(showOptHelp)
|
if(showOptHelp)
|
||||||
{
|
{
|
||||||
|
//fg
|
||||||
|
$('#conf_cont').append(createRow('conf_cont_instCapt'))
|
||||||
|
$('#conf_cont_instCapt').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
|
||||||
|
$('#conf_cont_instCapt').append(createHelpTable(schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title")));
|
||||||
|
|
||||||
//fg
|
//fg
|
||||||
$('#conf_cont').append(createRow('conf_cont_fg'))
|
$('#conf_cont').append(createRow('conf_cont_fg'))
|
||||||
$('#conf_cont_fg').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
|
$('#conf_cont_fg').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
|
||||||
@ -26,9 +32,23 @@ $(document).ready( function() {
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
$('#conf_cont').addClass('row');
|
$('#conf_cont').addClass('row');
|
||||||
|
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
|
||||||
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
|
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
|
||||||
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
|
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
|
||||||
}
|
}
|
||||||
|
//instCapt
|
||||||
|
conf_editor_instCapt = createJsonEditor('editor_container_instCapt', {
|
||||||
|
instCapture: schema.instCapture
|
||||||
|
}, true, true);
|
||||||
|
|
||||||
|
conf_editor_instCapt.on('change',function() {
|
||||||
|
conf_editor_instCapt.validate().length ? $('#btn_submit_instCapt').attr('disabled', true) : $('#btn_submit_instCapt').attr('disabled', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#btn_submit_instCapt').off().on('click',function() {
|
||||||
|
requestWriteConfig(conf_editor_instCapt.getValue());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//fg
|
//fg
|
||||||
conf_editor_fg = createJsonEditor('editor_container_fg', {
|
conf_editor_fg = createJsonEditor('editor_container_fg', {
|
||||||
@ -68,15 +88,14 @@ $(document).ready( function() {
|
|||||||
var grabbers = serverInfo.grabbers.available;
|
var grabbers = serverInfo.grabbers.available;
|
||||||
|
|
||||||
if(grabbers.indexOf('dispmanx') > -1)
|
if(grabbers.indexOf('dispmanx') > -1)
|
||||||
hideEl(["device","verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]);
|
hideEl(["device","pixelDecimation"]);
|
||||||
else if(grabbers.indexOf('x11') > -1)
|
else if(grabbers.indexOf('x11') > -1)
|
||||||
hideEl(["device","width","height"]);
|
hideEl(["device","width","height"]);
|
||||||
else if(grabbers.indexOf('osx') > -1 )
|
else if(grabbers.indexOf('osx') > -1 )
|
||||||
hideEl(["device","verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]);
|
hideEl(["device","pixelDecimation"]);
|
||||||
else if(grabbers.indexOf('amlogic') > -1)
|
else if(grabbers.indexOf('amlogic') > -1)
|
||||||
hideEl(["verticalPixelDecimation","horizontalPixelDecimation","useXGetImage"]);
|
hideEl(["pixelDecimation"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
removeOverlay();
|
removeOverlay();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
$(document).ready( function() {
|
$(document).ready( function() {
|
||||||
var uiLock = false;
|
var uiLock = false;
|
||||||
var prevSess = 0;
|
|
||||||
|
|
||||||
loadContentTo("#container_connection_lost","connection_lost");
|
loadContentTo("#container_connection_lost","connection_lost");
|
||||||
loadContentTo("#container_restart","restart");
|
loadContentTo("#container_restart","restart");
|
||||||
@ -8,6 +7,17 @@ $(document).ready( function() {
|
|||||||
|
|
||||||
$(hyperion).on("cmd-serverinfo",function(event){
|
$(hyperion).on("cmd-serverinfo",function(event){
|
||||||
serverInfo = event.response.info;
|
serverInfo = event.response.info;
|
||||||
|
// protect components from serverinfo updates
|
||||||
|
if(!compsInited)
|
||||||
|
{
|
||||||
|
comps = event.response.info.components
|
||||||
|
compsInited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!priosInited)
|
||||||
|
{
|
||||||
|
priosInited = true;
|
||||||
|
}
|
||||||
$(hyperion).trigger("ready");
|
$(hyperion).trigger("ready");
|
||||||
|
|
||||||
if (serverInfo.hyperion.config_modified)
|
if (serverInfo.hyperion.config_modified)
|
||||||
@ -15,10 +25,10 @@ $(document).ready( function() {
|
|||||||
else
|
else
|
||||||
$("#hyperion_reload_notify").fadeOut("fast");
|
$("#hyperion_reload_notify").fadeOut("fast");
|
||||||
|
|
||||||
if (serverInfo.hyperion.off)
|
if (serverInfo.hyperion.enabled)
|
||||||
$("#hyperion_disabled_notify").fadeIn("fast");
|
|
||||||
else
|
|
||||||
$("#hyperion_disabled_notify").fadeOut("fast");
|
$("#hyperion_disabled_notify").fadeOut("fast");
|
||||||
|
else
|
||||||
|
$("#hyperion_disabled_notify").fadeIn("fast");
|
||||||
|
|
||||||
if (!serverInfo.hyperion.config_writeable)
|
if (!serverInfo.hyperion.config_writeable)
|
||||||
{
|
{
|
||||||
@ -33,27 +43,14 @@ $(document).ready( function() {
|
|||||||
uiLock = false;
|
uiLock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sess = serverInfo.hyperion.sessions;
|
updateSessions();
|
||||||
if (sess.length != prevSess)
|
|
||||||
{
|
|
||||||
wSess = [];
|
|
||||||
prevSess = sess.length;
|
|
||||||
for(var i = 0; i<sess.length; i++)
|
|
||||||
{
|
|
||||||
if(sess[i].type == "_hyperiond-http._tcp.")
|
|
||||||
{
|
|
||||||
wSess.push(sess[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wSess.length > 1)
|
|
||||||
$('#btn_instanceswitch').toggle(true);
|
|
||||||
else
|
|
||||||
$('#btn_instanceswitch').toggle(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}); // end cmd-serverinfo
|
}); // end cmd-serverinfo
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-sessions-update", function(event) {
|
||||||
|
serverInfo.sessions = event.response.data;
|
||||||
|
updateSessions();
|
||||||
|
});
|
||||||
|
|
||||||
$(hyperion).one("cmd-sysinfo", function(event) {
|
$(hyperion).one("cmd-sysinfo", function(event) {
|
||||||
requestServerInfo();
|
requestServerInfo();
|
||||||
sysInfo = event.response.info;
|
sysInfo = event.response.info;
|
||||||
@ -62,14 +59,14 @@ $(document).ready( function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(hyperion).one("cmd-config-getschema", function(event) {
|
$(hyperion).one("cmd-config-getschema", function(event) {
|
||||||
serverSchema = event.response.result;
|
serverSchema = event.response.info;
|
||||||
requestServerConfig();
|
requestServerConfig();
|
||||||
|
|
||||||
schema = serverSchema.properties;
|
schema = serverSchema.properties;
|
||||||
});
|
});
|
||||||
|
|
||||||
$(hyperion).one("cmd-config-getconfig", function(event) {
|
$(hyperion).one("cmd-config-getconfig", function(event) {
|
||||||
serverConfig = event.response.result;
|
serverConfig = event.response.info;
|
||||||
requestSysInfo();
|
requestSysInfo();
|
||||||
|
|
||||||
showOptHelp = serverConfig.general.showOptHelp;
|
showOptHelp = serverConfig.general.showOptHelp;
|
||||||
@ -87,6 +84,39 @@ $(document).ready( function() {
|
|||||||
loadContent();
|
loadContent();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-adjustment-update", function(event) {
|
||||||
|
serverInfo.adjustment = event.response.data
|
||||||
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-videomode-update", function(event) {
|
||||||
|
serverInfo.videomode = event.response.data.videomode
|
||||||
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-components-update", function(event) {
|
||||||
|
let obj = event.response.data
|
||||||
|
|
||||||
|
// notfication in index
|
||||||
|
if (obj.name == "ALL")
|
||||||
|
{
|
||||||
|
if(obj.enable)
|
||||||
|
$("#hyperion_disabled_notify").fadeOut("fast");
|
||||||
|
else
|
||||||
|
$("#hyperion_disabled_notify").fadeIn("fast");
|
||||||
|
}
|
||||||
|
|
||||||
|
comps.forEach((entry, index) => {
|
||||||
|
if (entry.name === obj.name){
|
||||||
|
comps[index] = obj;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// notify the update
|
||||||
|
$(hyperion).trigger("components-updated");
|
||||||
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-effects-update", function(event){
|
||||||
|
serverInfo.effects = event.response.data.effects
|
||||||
|
});
|
||||||
|
|
||||||
$("#btn_hyperion_reload").on("click", function(){
|
$("#btn_hyperion_reload").on("click", function(){
|
||||||
initRestart();
|
initRestart();
|
||||||
});
|
});
|
||||||
@ -105,4 +135,3 @@ $(function(){
|
|||||||
$(this).toggleClass('active inactive');
|
$(this).toggleClass('active inactive');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
$(document).ready( function() {
|
$(document).ready( function() {
|
||||||
performTranslation();
|
performTranslation();
|
||||||
|
|
||||||
|
var conf_editor_net = null;
|
||||||
var conf_editor_json = null;
|
var conf_editor_json = null;
|
||||||
var conf_editor_proto = null;
|
var conf_editor_proto = null;
|
||||||
var conf_editor_bobl = null;
|
var conf_editor_bobl = null;
|
||||||
@ -128,4 +129,3 @@ $(document).ready( function() {
|
|||||||
|
|
||||||
removeOverlay();
|
removeOverlay();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,22 +86,6 @@ $(document).ready(function() {
|
|||||||
requestSetColor(rgb.r, rgb.g, rgb.b,duration);
|
requestSetColor(rgb.r, rgb.g, rgb.b,duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRemote()
|
|
||||||
{
|
|
||||||
if ($('#componentsbutton').length == 0)
|
|
||||||
{
|
|
||||||
$(hyperion).off("cmd-serverinfo",updateRemote);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updateInputSelect();
|
|
||||||
updateLedMapping();
|
|
||||||
updateVideoMode();
|
|
||||||
updateComponents();
|
|
||||||
updateEffectlist();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateInputSelect()
|
function updateInputSelect()
|
||||||
{
|
{
|
||||||
$('.sstbody').html("");
|
$('.sstbody').html("");
|
||||||
@ -123,6 +107,7 @@ $(document).ready(function() {
|
|||||||
var priority = prios[i].priority;
|
var priority = prios[i].priority;
|
||||||
var compId = prios[i].componentId;
|
var compId = prios[i].componentId;
|
||||||
var duration = prios[i].duration_ms/1000;
|
var duration = prios[i].duration_ms/1000;
|
||||||
|
var value = "0,0,0";
|
||||||
var btn_type = "default";
|
var btn_type = "default";
|
||||||
var btn_text = $.i18n('remote_input_setsource_btn');
|
var btn_text = $.i18n('remote_input_setsource_btn');
|
||||||
var btn_state = "enabled";
|
var btn_state = "enabled";
|
||||||
@ -145,13 +130,16 @@ $(document).ready(function() {
|
|||||||
if(ip)
|
if(ip)
|
||||||
origin += '<br/><span style="font-size:80%; color:grey;">'+$.i18n('remote_input_ip')+' '+ip+'</span>';
|
origin += '<br/><span style="font-size:80%; color:grey;">'+$.i18n('remote_input_ip')+' '+ip+'</span>';
|
||||||
|
|
||||||
|
if("value" in prios[i])
|
||||||
|
value = prios[i].value.RGB;
|
||||||
|
|
||||||
switch (compId)
|
switch (compId)
|
||||||
{
|
{
|
||||||
case "EFFECT":
|
case "EFFECT":
|
||||||
owner = $.i18n('remote_effects_label_effects')+' '+owner;
|
owner = $.i18n('remote_effects_label_effects')+' '+owner;
|
||||||
break;
|
break;
|
||||||
case "COLOR":
|
case "COLOR":
|
||||||
owner = $.i18n('remote_color_label_color')+' '+'<div style="width:18px; height:18px; border-radius:20px; margin-bottom:-4px; border:1px grey solid; background-color: rgb('+prios[i].value.RGB+'); display:inline-block" title="RGB: ('+prios[i].value.RGB+')"></div>';
|
owner = $.i18n('remote_color_label_color')+' '+'<div style="width:18px; height:18px; border-radius:20px; margin-bottom:-4px; border:1px grey solid; background-color: rgb('+value+'); display:inline-block" title="RGB: ('+value+')"></div>';
|
||||||
break;
|
break;
|
||||||
case "GRABBER":
|
case "GRABBER":
|
||||||
owner = $.i18n('general_comp_GRABBER')+': ('+owner+')';
|
owner = $.i18n('general_comp_GRABBER')+': ('+owner+')';
|
||||||
@ -165,6 +153,9 @@ $(document).ready(function() {
|
|||||||
case "UDPLISTENER":
|
case "UDPLISTENER":
|
||||||
owner = $.i18n('general_comp_UDPLISTENER');
|
owner = $.i18n('general_comp_UDPLISTENER');
|
||||||
break;
|
break;
|
||||||
|
case "PROTOSERVER":
|
||||||
|
owner = "Proto";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(duration && compId != "GRABBER" && compId != "PROTOSERVER")
|
if(duration && compId != "GRABBER" && compId != "PROTOSERVER")
|
||||||
@ -195,7 +186,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
function updateLedMapping()
|
function updateLedMapping()
|
||||||
{
|
{
|
||||||
mapping = serverInfo.ledMAppingType;
|
mapping = serverInfo.imageToLedMappingType;
|
||||||
|
|
||||||
$('#mappingsbutton').html("");
|
$('#mappingsbutton').html("");
|
||||||
for(var ix = 0; ix < mappingList.length; ix++)
|
for(var ix = 0; ix < mappingList.length; ix++)
|
||||||
@ -211,16 +202,19 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
function updateComponents()
|
function updateComponents()
|
||||||
{
|
{
|
||||||
components = serverInfo.components;
|
components = comps;
|
||||||
// create buttons
|
// create buttons
|
||||||
$('#componentsbutton').html("");
|
$('#componentsbutton').html("");
|
||||||
for ( idx=0; idx<components.length;idx++)
|
for ( idx=0; idx<components.length;idx++)
|
||||||
{
|
{
|
||||||
|
if(components[idx].name == "ALL")
|
||||||
|
continue
|
||||||
|
|
||||||
enable_style = (components[idx].enabled? "btn-success" : "btn-danger");
|
enable_style = (components[idx].enabled? "btn-success" : "btn-danger");
|
||||||
enable_icon = (components[idx].enabled? "fa-play" : "fa-stop");
|
enable_icon = (components[idx].enabled? "fa-play" : "fa-stop");
|
||||||
comp_name = components[idx].name;
|
comp_name = components[idx].name;
|
||||||
comp_btn_id = "comp_btn_"+comp_name;
|
comp_btn_id = "comp_btn_"+comp_name;
|
||||||
comp_goff = serverInfo.hyperion.off? "disabled" : "enabled";
|
comp_goff = serverInfo.hyperion.enabled? "enabled" : "disabled";
|
||||||
|
|
||||||
// create btn if not there
|
// create btn if not there
|
||||||
if ($("#"+comp_btn_id).length == 0)
|
if ($("#"+comp_btn_id).length == 0)
|
||||||
@ -266,7 +260,7 @@ $(document).ready(function() {
|
|||||||
function updateVideoMode()
|
function updateVideoMode()
|
||||||
{
|
{
|
||||||
videoModes = ["2D","3DSBS","3DTAB"];
|
videoModes = ["2D","3DSBS","3DTAB"];
|
||||||
currVideoMode = serverInfo.grabbers.videomode;
|
currVideoMode = serverInfo.videomode;
|
||||||
|
|
||||||
$('#videomodebtns').html("");
|
$('#videomodebtns').html("");
|
||||||
for(var ix = 0; ix < videoModes.length; ix++)
|
for(var ix = 0; ix < videoModes.length; ix++)
|
||||||
@ -327,10 +321,34 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//force first update
|
//force first update
|
||||||
updateRemote();
|
updateComponents();
|
||||||
|
updateInputSelect();
|
||||||
|
updateLedMapping();
|
||||||
|
updateVideoMode();
|
||||||
|
updateEffectlist();
|
||||||
|
|
||||||
// interval updates
|
// interval updates
|
||||||
$(hyperion).on("cmd-serverinfo",updateRemote);
|
$(hyperion).on("components-updated",updateComponents);
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-priorities-update", function(event){
|
||||||
|
serverInfo.priorities = event.response.data.priorities
|
||||||
|
serverInfo.priorities_autoselect = event.response.data.priorities_autoselect
|
||||||
|
updateInputSelect()
|
||||||
|
});
|
||||||
|
$(hyperion).on("cmd-imageToLedMapping-update", function(event){
|
||||||
|
serverInfo.imageToLedMappingType = event.response.data.imageToLedMappingType
|
||||||
|
updateLedMapping()
|
||||||
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-videomode-update", function(event){
|
||||||
|
serverInfo.videomode = event.response.data.videomode
|
||||||
|
updateVideoMode()
|
||||||
|
});
|
||||||
|
|
||||||
|
$(hyperion).on("cmd-effects-update", function(event){
|
||||||
|
serverInfo.effects = event.response.data.effects
|
||||||
|
updateEffectlist();
|
||||||
|
});
|
||||||
|
|
||||||
removeOverlay();
|
removeOverlay();
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,17 @@ var loggingHandlerInstalled = false;
|
|||||||
var watchdog = 0;
|
var watchdog = 0;
|
||||||
var debugMessagesActive = true;
|
var debugMessagesActive = true;
|
||||||
var wSess = [];
|
var wSess = [];
|
||||||
|
var plugins_installed = {};
|
||||||
|
var plugins_available = {};
|
||||||
|
|
||||||
|
//comps serverinfo lock
|
||||||
|
comps = [];
|
||||||
|
compsInited = false;
|
||||||
|
|
||||||
|
// prios serverinfo lock
|
||||||
|
priosInited = false;
|
||||||
|
// token list
|
||||||
|
tokenList = {}
|
||||||
|
|
||||||
function initRestart()
|
function initRestart()
|
||||||
{
|
{
|
||||||
@ -59,6 +70,7 @@ function connectionLostDetection(type)
|
|||||||
setInterval(connectionLostDetection, 3000);
|
setInterval(connectionLostDetection, 3000);
|
||||||
|
|
||||||
// init websocket to hyperion and bind socket events to jquery events of $(hyperion) object
|
// init websocket to hyperion and bind socket events to jquery events of $(hyperion) object
|
||||||
|
|
||||||
function initWebSocket()
|
function initWebSocket()
|
||||||
{
|
{
|
||||||
if ("WebSocket" in window)
|
if ("WebSocket" in window)
|
||||||
@ -66,8 +78,8 @@ function initWebSocket()
|
|||||||
if (websocket == null)
|
if (websocket == null)
|
||||||
{
|
{
|
||||||
jsonPort = (document.location.port == '') ? '80' : document.location.port;
|
jsonPort = (document.location.port == '') ? '80' : document.location.port;
|
||||||
websocket = new WebSocket('ws://'+document.location.hostname+":"+document.location.port);
|
websocket = new WebSocket('ws://'+document.location.hostname+":"+jsonPort);
|
||||||
console.log(jsonPort)
|
|
||||||
websocket.onopen = function (event) {
|
websocket.onopen = function (event) {
|
||||||
$(hyperion).trigger({type:"open"});
|
$(hyperion).trigger({type:"open"});
|
||||||
|
|
||||||
@ -108,7 +120,7 @@ function initWebSocket()
|
|||||||
response = JSON.parse(event.data);
|
response = JSON.parse(event.data);
|
||||||
success = response.success;
|
success = response.success;
|
||||||
cmd = response.command;
|
cmd = response.command;
|
||||||
if (success)
|
if (success || typeof(success) == "undefined")
|
||||||
{
|
{
|
||||||
$(hyperion).trigger({type:"cmd-"+cmd, response:response});
|
$(hyperion).trigger({type:"cmd-"+cmd, response:response});
|
||||||
}
|
}
|
||||||
@ -161,7 +173,7 @@ function sendToHyperion(command, subcommand, msg)
|
|||||||
// also used for watchdog
|
// also used for watchdog
|
||||||
function requestServerInfo()
|
function requestServerInfo()
|
||||||
{
|
{
|
||||||
sendToHyperion("serverinfo");
|
sendToHyperion("serverinfo","",'"subscribe":["components-update","sessions-update","priorities-update", "imageToLedMapping-update", "adjustment-update", "videomode-update", "effects-update"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestSysInfo()
|
function requestSysInfo()
|
||||||
@ -218,7 +230,7 @@ function requestPriorityClear(prio)
|
|||||||
|
|
||||||
function requestClearAll()
|
function requestClearAll()
|
||||||
{
|
{
|
||||||
sendToHyperion("clearall");
|
requestPriorityClear(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
function requestPlayEffect(effectName, duration)
|
function requestPlayEffect(effectName, duration)
|
||||||
|
2
assets/webconfig/js/lib/bootstrap-notify.min.js
vendored
Normal file
2
assets/webconfig/js/lib/bootstrap-notify.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -48,6 +48,27 @@ function debugMessage(msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSessions()
|
||||||
|
{
|
||||||
|
var sess = serverInfo.sessions;
|
||||||
|
if (sess.length)
|
||||||
|
{
|
||||||
|
wSess = [];
|
||||||
|
for(var i = 0; i<sess.length; i++)
|
||||||
|
{
|
||||||
|
if(sess[i].type == "_hyperiond-http._tcp.")
|
||||||
|
{
|
||||||
|
wSess.push(sess[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wSess.length > 1)
|
||||||
|
$('#btn_instanceswitch').toggle(true);
|
||||||
|
else
|
||||||
|
$('#btn_instanceswitch').toggle(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function validateDuration(d)
|
function validateDuration(d)
|
||||||
{
|
{
|
||||||
if(typeof d === "undefined" || d < 0)
|
if(typeof d === "undefined" || d < 0)
|
||||||
@ -381,6 +402,57 @@ function hexToRgb(hex) {
|
|||||||
} : null;
|
} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Show a notification
|
||||||
|
@param type Valid types are "info","success","warning","danger"
|
||||||
|
@param message The message to show
|
||||||
|
@param title A title (optional)
|
||||||
|
*/
|
||||||
|
function showNotification(type, message, title="")
|
||||||
|
{
|
||||||
|
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: 'animated fadeInRight',
|
||||||
|
exit: 'animated fadeOutRight'
|
||||||
|
},
|
||||||
|
mouse_over : 'pause',
|
||||||
|
template: '<div data-notify="container" class="bg-w col-xs-11 col-sm-3 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>' +
|
||||||
|
'<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)
|
function createCP(id, color, cb)
|
||||||
{
|
{
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
||||||
/// * 'leds' : The indices (or index ranges) of the leds to which this channel adjustment applies
|
/// * 'leds' : The indices (or index ranges) of the leds to which this channel adjustment applies
|
||||||
/// (eg '0-5, 9, 11, 12-17'). The indices are zero based.
|
/// (eg '0-5, 9, 11, 12-17'). The indices are zero based.
|
||||||
/// * 'black'/'white'/'red'/'green'/'blue'/'cyan'/'magenta'/'yellow' : Array of RGB to adjust the output color
|
/// * 'white'/'red'/'green'/'blue'/'cyan'/'magenta'/'yellow' : Array of RGB to adjust the output color
|
||||||
/// * 'gammaRed'/'gammaGreen'/'gammaBlue' : Gamma value for each channel
|
/// * 'gammaRed'/'gammaGreen'/'gammaBlue' : Gamma value for each channel
|
||||||
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
||||||
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
/// * 'id' : The unique identifier of the channel adjustments (eg 'device_1')
|
||||||
@ -60,7 +60,6 @@
|
|||||||
{
|
{
|
||||||
"id" : "default",
|
"id" : "default",
|
||||||
"leds" : "*",
|
"leds" : "*",
|
||||||
"black" : [0,0,0],
|
|
||||||
"white" : [255,255,255],
|
"white" : [255,255,255],
|
||||||
"red" : [255,0,0],
|
"red" : [255,0,0],
|
||||||
"green" : [0,255,0],
|
"green" : [0,255,0],
|
||||||
@ -99,15 +98,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
/// Configuration for the embedded V4L2 grabber
|
/// Configuration for the embedded V4L2 grabber
|
||||||
/// * enable : Enable or disable the v4lgrabber (true/false)
|
|
||||||
/// * device : V4L2 Device to use [default="/dev/video0"]
|
/// * device : V4L2 Device to use [default="/dev/video0"]
|
||||||
/// * input : V4L2 input to use [default=0]
|
/// * input : V4L2 input to use [default=0]
|
||||||
/// * standard : Video standard (PAL/NTSC/SECAM) [default="PAL"]
|
/// * standard : Video standard (PAL/NTSC/SECAM/NO_CHANGE) [default="NO_CHANGE"]
|
||||||
/// * width : V4L2 width to set [default=-1]
|
|
||||||
/// * height : V4L2 height to set [default=-1]
|
|
||||||
/// * frameDecimation : Frame decimation factor [default=2]
|
|
||||||
/// * sizeDecimation : Size decimation factor [default=8]
|
/// * sizeDecimation : Size decimation factor [default=8]
|
||||||
/// * priority : Hyperion priority channel [default=900]
|
|
||||||
/// * cropLeft : Cropping from the left [default=0]
|
/// * cropLeft : Cropping from the left [default=0]
|
||||||
/// * cropRight : Cropping from the right [default=0]
|
/// * cropRight : Cropping from the right [default=0]
|
||||||
/// * cropTop : Cropping from the top [default=0]
|
/// * cropTop : Cropping from the top [default=0]
|
||||||
@ -123,13 +117,9 @@
|
|||||||
"grabberV4L2" :
|
"grabberV4L2" :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"enable" : false,
|
|
||||||
"device" : "auto",
|
"device" : "auto",
|
||||||
"input" : 0,
|
"input" : 0,
|
||||||
"standard" : "PAL",
|
"standard" : "NO_CHANGE",
|
||||||
"width" : 0,
|
|
||||||
"height" : 0,
|
|
||||||
"frameDecimation" : 2,
|
|
||||||
"sizeDecimation" : 8,
|
"sizeDecimation" : 8,
|
||||||
"priority" : 240,
|
"priority" : 240,
|
||||||
"cropLeft" : 0,
|
"cropLeft" : 0,
|
||||||
@ -148,20 +138,16 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
/// The configuration for the frame-grabber, contains the following items:
|
/// The configuration for the frame-grabber, contains the following items:
|
||||||
/// * enable : true if the framegrabber (platform grabber) should be activated
|
|
||||||
/// * type : type of grabber. (auto|osx|dispmanx|amlogic|x11|framebuffer) [auto]
|
/// * type : type of grabber. (auto|osx|dispmanx|amlogic|x11|framebuffer) [auto]
|
||||||
/// * width : The width of the grabbed frames [pixels]
|
/// * width : The width of the grabbed frames [pixels]
|
||||||
/// * height : The height of the grabbed frames [pixels]
|
/// * height : The height of the grabbed frames [pixels]
|
||||||
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
||||||
/// * priority : The priority of the frame-gabber (Default=250) HINT: lower value result in HIGHER priority!
|
|
||||||
/// * ATTENTION : Power-of-Two resolution is not supported and leads to unexpected behaviour!
|
/// * ATTENTION : Power-of-Two resolution is not supported and leads to unexpected behaviour!
|
||||||
"framegrabber" :
|
"framegrabber" :
|
||||||
{
|
{
|
||||||
// for all type of grabbers
|
// for all type of grabbers
|
||||||
"enable" : true,
|
|
||||||
"type" : "framebuffer",
|
"type" : "framebuffer",
|
||||||
"frequency_Hz" : 10,
|
"frequency_Hz" : 10,
|
||||||
"priority" : 250,
|
|
||||||
"cropLeft" : 0,
|
"cropLeft" : 0,
|
||||||
"cropRight" : 0,
|
"cropRight" : 0,
|
||||||
"cropTop" : 0,
|
"cropTop" : 0,
|
||||||
@ -172,9 +158,7 @@
|
|||||||
"height" : 96,
|
"height" : 96,
|
||||||
|
|
||||||
// valid for x11
|
// valid for x11
|
||||||
"useXGetImage" : false,
|
"pixelDecimation" : 8,
|
||||||
"horizontalPixelDecimation" : 8,
|
|
||||||
"verticalPixelDecimation" : 8,
|
|
||||||
|
|
||||||
// valid for framebuffer
|
// valid for framebuffer
|
||||||
"device" : "/dev/fb0"
|
"device" : "/dev/fb0"
|
||||||
@ -313,6 +297,13 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"instCapture" : {
|
||||||
|
"systemEnable" : true,
|
||||||
|
"systemPriority" : 250,
|
||||||
|
"v4lEnable" : false,
|
||||||
|
"v4lPriority" : 240
|
||||||
|
},
|
||||||
|
|
||||||
/// Recreate and save led layouts made with web config. These values are just helpers for ui, not for Hyperion.
|
/// Recreate and save led layouts made with web config. These values are just helpers for ui, not for Hyperion.
|
||||||
"ledConfig" :
|
"ledConfig" :
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
{
|
{
|
||||||
"id" : "default",
|
"id" : "default",
|
||||||
"leds" : "*",
|
"leds" : "*",
|
||||||
"black" : [0,0,0],
|
|
||||||
"white" : [255,255,255],
|
"white" : [255,255,255],
|
||||||
"red" : [255,0,0],
|
"red" : [255,0,0],
|
||||||
"green" : [0,255,0],
|
"green" : [0,255,0],
|
||||||
@ -58,15 +57,10 @@
|
|||||||
"grabberV4L2" :
|
"grabberV4L2" :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"enable" : false,
|
|
||||||
"device" : "auto",
|
"device" : "auto",
|
||||||
"input" : 0,
|
"input" : 0,
|
||||||
"standard" : "PAL",
|
"standard" : "NO_CHANGE",
|
||||||
"width" : 0,
|
|
||||||
"height" : 0,
|
|
||||||
"frameDecimation" : 2,
|
|
||||||
"sizeDecimation" : 8,
|
"sizeDecimation" : 8,
|
||||||
"priority" : 240,
|
|
||||||
"cropLeft" : 0,
|
"cropLeft" : 0,
|
||||||
"cropRight" : 0,
|
"cropRight" : 0,
|
||||||
"cropTop" : 0,
|
"cropTop" : 0,
|
||||||
@ -84,15 +78,11 @@
|
|||||||
|
|
||||||
"framegrabber" :
|
"framegrabber" :
|
||||||
{
|
{
|
||||||
"enable" : true,
|
|
||||||
"type" : "auto",
|
"type" : "auto",
|
||||||
"width" : 80,
|
"width" : 80,
|
||||||
"height" : 45,
|
"height" : 45,
|
||||||
"frequency_Hz" : 10,
|
"frequency_Hz" : 10,
|
||||||
"priority" : 250,
|
"pixelDecimation" : 8,
|
||||||
"useXGetImage" : false,
|
|
||||||
"horizontalPixelDecimation" : 8,
|
|
||||||
"verticalPixelDecimation" : 8,
|
|
||||||
"cropLeft" : 0,
|
"cropLeft" : 0,
|
||||||
"cropRight" : 0,
|
"cropRight" : 0,
|
||||||
"cropTop" : 0,
|
"cropTop" : 0,
|
||||||
@ -175,6 +165,13 @@
|
|||||||
"disable": [""]
|
"disable": [""]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"instCapture" : {
|
||||||
|
"systemEnable" : true,
|
||||||
|
"systemPriority" : 250,
|
||||||
|
"v4lEnable" : false,
|
||||||
|
"v4lPriority" : 240
|
||||||
|
},
|
||||||
|
|
||||||
"ledConfig" :
|
"ledConfig" :
|
||||||
{
|
{
|
||||||
"top" : 8,
|
"top" : 8,
|
||||||
|
@ -4,30 +4,28 @@
|
|||||||
// QT includes
|
// QT includes
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
// util
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
#include <utils/Components.h>
|
||||||
|
|
||||||
// Local Hyperion includes
|
// Local Hyperion includes
|
||||||
#include "BlackBorderDetector.h"
|
#include "BlackBorderDetector.h"
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
namespace hyperion
|
namespace hyperion
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
/// The BlackBorder processor is a wrapper around the black-border detector for keeping track of
|
/// The BlackBorder processor is a wrapper around the black-border detector for keeping track of
|
||||||
/// detected borders and count of the type and size of detected borders.
|
/// detected borders and count of the type and size of detected borders.
|
||||||
///
|
///
|
||||||
class BlackBorderProcessor
|
class BlackBorderProcessor : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
///
|
BlackBorderProcessor(Hyperion* hyperion, QObject* parent);
|
||||||
/// Constructor for the BlackBorderProcessor
|
~BlackBorderProcessor();
|
||||||
/// @param unknownFrameCnt The number of frames(images) that need to contain an unknown
|
|
||||||
/// border before the current border is set to unknown
|
|
||||||
/// @param borderFrameCnt The number of frames(images) that need to contain a vertical or
|
|
||||||
/// horizontal border becomes the current border
|
|
||||||
/// @param blurRemoveCnt The size to add to a horizontal or vertical border (because the
|
|
||||||
/// outer pixels is blurred (black and color combined due to image scaling))
|
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
|
||||||
///
|
|
||||||
BlackBorderProcessor(const QJsonObject &blackborderConfig);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Return the current (detected) border
|
/// Return the current (detected) border
|
||||||
/// @return The current border
|
/// @return The current border
|
||||||
@ -46,6 +44,13 @@ namespace hyperion
|
|||||||
///
|
///
|
||||||
void setEnabled(bool enable);
|
void setEnabled(bool enable);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Sets the _hardDisabled state, if True prevents the enable from COMP_BLACKBORDER state emit (mimiks wrong state to external!)
|
||||||
|
/// It's not possible to enable bb from this method, if the user requsted a disable!
|
||||||
|
/// @param disable The new state
|
||||||
|
///
|
||||||
|
void setHardDisable(const bool& disable);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Processes the image. This performs detecion of black-border on the given image and
|
/// Processes the image. This performs detecion of black-border on the given image and
|
||||||
/// updates the current border accordingly. If the current border is updated the method call
|
/// updates the current border accordingly. If the current border is updated the method call
|
||||||
@ -70,11 +75,11 @@ namespace hyperion
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_detectionMode == "default") {
|
if (_detectionMode == "default") {
|
||||||
imageBorder = _detector.process(image);
|
imageBorder = _detector->process(image);
|
||||||
} else if (_detectionMode == "classic") {
|
} else if (_detectionMode == "classic") {
|
||||||
imageBorder = _detector.process_classic(image);
|
imageBorder = _detector->process_classic(image);
|
||||||
} else if (_detectionMode == "osd") {
|
} else if (_detectionMode == "osd") {
|
||||||
imageBorder = _detector.process_osd(image);
|
imageBorder = _detector->process_osd(image);
|
||||||
}
|
}
|
||||||
// add blur to the border
|
// add blur to the border
|
||||||
if (imageBorder.horizontalSize > 0)
|
if (imageBorder.horizontalSize > 0)
|
||||||
@ -89,8 +94,23 @@ namespace hyperion
|
|||||||
const bool borderUpdated = updateBorder(imageBorder);
|
const bool borderUpdated = updateBorder(imageBorder);
|
||||||
return borderUpdated;
|
return borderUpdated;
|
||||||
}
|
}
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle component state changes, it's not possible for BB to be enabled, when a hardDisable is active
|
||||||
|
///
|
||||||
|
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Hyperion instance
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Updates the current border based on the newly detected border. Returns true if the
|
/// Updates the current border based on the newly detected border. Returns true if the
|
||||||
/// current border has changed.
|
/// current border has changed.
|
||||||
@ -104,22 +124,22 @@ namespace hyperion
|
|||||||
bool _enabled;
|
bool _enabled;
|
||||||
|
|
||||||
/// The number of unknown-borders detected before it becomes the current border
|
/// The number of unknown-borders detected before it becomes the current border
|
||||||
const unsigned _unknownSwitchCnt;
|
unsigned _unknownSwitchCnt;
|
||||||
|
|
||||||
/// The number of horizontal/vertical borders detected before it becomes the current border
|
/// The number of horizontal/vertical borders detected before it becomes the current border
|
||||||
const unsigned _borderSwitchCnt;
|
unsigned _borderSwitchCnt;
|
||||||
|
|
||||||
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
|
// The number of frames that are "ignored" before a new border gets set as _previousDetectedBorder
|
||||||
const unsigned _maxInconsistentCnt;
|
unsigned _maxInconsistentCnt;
|
||||||
|
|
||||||
/// The number of pixels to increase a detected border for removing blury pixels
|
/// The number of pixels to increase a detected border for removing blury pixels
|
||||||
unsigned _blurRemoveCnt;
|
unsigned _blurRemoveCnt;
|
||||||
|
|
||||||
/// The border detection mode
|
/// The border detection mode
|
||||||
const QString _detectionMode;
|
QString _detectionMode;
|
||||||
|
|
||||||
/// The blackborder detector
|
/// The blackborder detector
|
||||||
BlackBorderDetector _detector;
|
BlackBorderDetector* _detector;
|
||||||
|
|
||||||
/// The current detected border
|
/// The current detected border
|
||||||
BlackBorder _currentBorder;
|
BlackBorder _currentBorder;
|
||||||
@ -131,5 +151,12 @@ namespace hyperion
|
|||||||
unsigned _consistentCnt;
|
unsigned _consistentCnt;
|
||||||
/// The number of frame the previous detected border NOT matched the incomming border
|
/// The number of frame the previous detected border NOT matched the incomming border
|
||||||
unsigned _inconsistentCnt;
|
unsigned _inconsistentCnt;
|
||||||
|
/// old threshold
|
||||||
|
double _oldThreshold;
|
||||||
|
/// True when disabled in specific situations, this prevents to enable BB when the visible priority requested a disable
|
||||||
|
bool _hardDisabled;
|
||||||
|
/// Reflect the last component state request from user (comp change)
|
||||||
|
bool _userEnabled;
|
||||||
|
|
||||||
};
|
};
|
||||||
} // end namespace hyperion
|
} // end namespace hyperion
|
||||||
|
@ -4,15 +4,19 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
// Hyperion includes
|
// Hyperion includes
|
||||||
#include <hyperion/Hyperion.h>
|
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Components.h>
|
#include <utils/Components.h>
|
||||||
|
|
||||||
|
// settings
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
class BoblightClientConnection;
|
class BoblightClientConnection;
|
||||||
|
class Hyperion;
|
||||||
|
class QTcpServer;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// This class creates a TCP server which accepts connections from boblight clients.
|
/// This class creates a TCP server which accepts connections from boblight clients.
|
||||||
@ -27,7 +31,7 @@ public:
|
|||||||
/// @param hyperion Hyperion instance
|
/// @param hyperion Hyperion instance
|
||||||
/// @param port port number on which to start listening for connections
|
/// @param port port number on which to start listening for connections
|
||||||
///
|
///
|
||||||
BoblightServer(const int priority, uint16_t port = 19333);
|
BoblightServer(const QJsonDocument& config);
|
||||||
~BoblightServer();
|
~BoblightServer();
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -37,8 +41,7 @@ public:
|
|||||||
|
|
||||||
/// @return true if server is active (bind to a port)
|
/// @return true if server is active (bind to a port)
|
||||||
///
|
///
|
||||||
bool active() { return _isActive; };
|
bool active();
|
||||||
bool componentState() { return active(); };
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
///
|
///
|
||||||
@ -53,8 +56,12 @@ public slots:
|
|||||||
|
|
||||||
void componentStateChanged(const hyperion::Components component, bool enable);
|
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||||
|
|
||||||
signals:
|
///
|
||||||
void statusChanged(bool isActive);
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
@ -73,19 +80,17 @@ private:
|
|||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
|
|
||||||
/// The TCP server object
|
/// The TCP server object
|
||||||
QTcpServer _server;
|
QTcpServer * _server;
|
||||||
|
|
||||||
/// List with open connections
|
/// List with open connections
|
||||||
QSet<BoblightClientConnection *> _openConnections;
|
QSet<BoblightClientConnection *> _openConnections;
|
||||||
|
|
||||||
/// hyperion priority
|
/// hyperion priority
|
||||||
const int _priority;
|
int _priority;
|
||||||
|
|
||||||
/// Logger instance
|
/// Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
/// state of connection
|
// current port
|
||||||
bool _isActive;
|
|
||||||
|
|
||||||
uint16_t _port;
|
uint16_t _port;
|
||||||
};
|
};
|
||||||
|
68
include/bonjour/bonjourbrowserwrapper.h
Normal file
68
include/bonjour/bonjourbrowserwrapper.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
// qt incl
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QHostInfo>
|
||||||
|
|
||||||
|
#include <bonjour/bonjourrecord.h>
|
||||||
|
|
||||||
|
class BonjourServiceBrowser;
|
||||||
|
class BonjourServiceResolver;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
class BonjourBrowserWrapper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
friend class HyperionDaemon;
|
||||||
|
///
|
||||||
|
/// @brief Browse for hyperion services in bonjour, constructed from HyperionDaemon
|
||||||
|
/// Searching for hyperion http service by default
|
||||||
|
///
|
||||||
|
BonjourBrowserWrapper(QObject * parent = 0);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Browse for a service
|
||||||
|
///
|
||||||
|
bool browseForServiceType(const QString &serviceType);
|
||||||
|
///
|
||||||
|
/// @brief Get all available sessions
|
||||||
|
///
|
||||||
|
QMap<QString,BonjourRecord> getAllServices() { return _hyperionSessions; };
|
||||||
|
|
||||||
|
static BonjourBrowserWrapper* instance;
|
||||||
|
static BonjourBrowserWrapper* getInstance(){ return instance; };
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a change happend
|
||||||
|
///
|
||||||
|
void browserChange(const QMap<QString,BonjourRecord>& bRegisters);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// map of service names and browsers
|
||||||
|
QMap< QString, BonjourServiceBrowser* > _browsedServices;
|
||||||
|
/// Resolver
|
||||||
|
BonjourServiceResolver* _bonjourResolver;
|
||||||
|
|
||||||
|
// contains all current active service sessions
|
||||||
|
QMap<QString,BonjourRecord> _hyperionSessions;
|
||||||
|
|
||||||
|
QString _bonjourCurrentServiceToResolve;
|
||||||
|
/// timer to resolve changes
|
||||||
|
QTimer* _timerBonjourResolver;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// @brief is called whenever a BonjourServiceBrowser emits change
|
||||||
|
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
|
||||||
|
/// @brief new record resolved
|
||||||
|
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief timer slot which updates regularly entries
|
||||||
|
///
|
||||||
|
void bonjourResolve();
|
||||||
|
};
|
@ -43,7 +43,8 @@ public:
|
|||||||
BonjourServiceRegister(QObject *parent = 0);
|
BonjourServiceRegister(QObject *parent = 0);
|
||||||
~BonjourServiceRegister();
|
~BonjourServiceRegister();
|
||||||
|
|
||||||
void registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt);
|
void registerService(const QString& service, const int& port);
|
||||||
|
void registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt = std::vector<std::pair<std::string, std::string>>());
|
||||||
inline BonjourRecord registeredRecord() const {return finalRecord; }
|
inline BonjourRecord registeredRecord() const {return finalRecord; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
89
include/effectengine/Effect.h
Normal file
89
include/effectengine/Effect.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Python includes
|
||||||
|
// collide of qt slots macro
|
||||||
|
#undef slots
|
||||||
|
#include "Python.h"
|
||||||
|
#define slots
|
||||||
|
|
||||||
|
// Qt includes
|
||||||
|
#include <QThread>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
// Hyperion includes
|
||||||
|
#include <utils/Components.h>
|
||||||
|
#include <utils/Image.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
class Logger;
|
||||||
|
|
||||||
|
class Effect : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend class EffectModule;
|
||||||
|
|
||||||
|
Effect(Hyperion* hyperion, int priority, int timeout, const QString & script, const QString & name, const QJsonObject & args = QJsonObject());
|
||||||
|
virtual ~Effect();
|
||||||
|
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
|
int getPriority() const { return _priority; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Set manual interuption to true,
|
||||||
|
/// Note: DO NOT USE QThread::interuption!
|
||||||
|
///
|
||||||
|
void setInteruptionFlag() { _interupt = true; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Check if the interuption flag has been set
|
||||||
|
/// @return The flag state
|
||||||
|
///
|
||||||
|
bool hasInteruptionFlag() { return _interupt; };
|
||||||
|
|
||||||
|
QString getScript() const { return _script; }
|
||||||
|
QString getName() const { return _name; }
|
||||||
|
|
||||||
|
int getTimeout() const {return _timeout; }
|
||||||
|
|
||||||
|
QJsonObject getArgs() const { return _args; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void setInput(const int priority, const std::vector<ColorRgb>& ledColors, const int timeout_ms, const bool& clearEffect);
|
||||||
|
void setInputImage(const int priority, const Image<ColorRgb>& image, const int timeout_ms, const bool& clearEffect);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void addImage();
|
||||||
|
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
|
||||||
|
const int _priority;
|
||||||
|
|
||||||
|
const int _timeout;
|
||||||
|
|
||||||
|
const QString _script;
|
||||||
|
const QString _name;
|
||||||
|
|
||||||
|
const QJsonObject _args;
|
||||||
|
|
||||||
|
int64_t _endTime;
|
||||||
|
|
||||||
|
/// Buffer for colorData
|
||||||
|
QVector<ColorRgb> _colors;
|
||||||
|
|
||||||
|
Logger* _log;
|
||||||
|
// Reflects whenever this effects should interupt (timeout or external request)
|
||||||
|
bool _interupt = false;
|
||||||
|
|
||||||
|
QSize _imageSize;
|
||||||
|
QImage _image;
|
||||||
|
QPainter* _painter;
|
||||||
|
QVector<QImage> _imageStack;
|
||||||
|
};
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
// pre-declarioation
|
// pre-declarioation
|
||||||
class Effect;
|
class Effect;
|
||||||
typedef struct _ts PyThreadState;
|
|
||||||
|
|
||||||
class EffectEngine : public QObject
|
class EffectEngine : public QObject
|
||||||
{
|
{
|
||||||
@ -43,6 +42,20 @@ public:
|
|||||||
return _effectSchemas;
|
return _effectSchemas;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get all init data of the running effects and stop them
|
||||||
|
///
|
||||||
|
void cacheRunningEffects();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Start all cached effects, origin and smooth cfg is default
|
||||||
|
///
|
||||||
|
void startCachedEffects();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/// Emit when the effect list has been updated
|
||||||
|
void effectListUpdated();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
||||||
int runEffect(const QString &effectName, int priority, int timeout = -1, const QString &origin="System");
|
int runEffect(const QString &effectName, int priority, int timeout = -1, const QString &origin="System");
|
||||||
@ -78,9 +91,9 @@ private:
|
|||||||
|
|
||||||
std::list<ActiveEffectDefinition> _availableActiveEffects;
|
std::list<ActiveEffectDefinition> _availableActiveEffects;
|
||||||
|
|
||||||
|
std::list<ActiveEffectDefinition> _cachedActiveEffects;
|
||||||
|
|
||||||
std::list<EffectSchema> _effectSchemas;
|
std::list<EffectSchema> _effectSchemas;
|
||||||
|
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
PyThreadState* _mainThreadState;
|
|
||||||
};
|
};
|
||||||
|
@ -1,49 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Python includes
|
|
||||||
// collide of qt slots macro
|
|
||||||
#undef slots
|
#undef slots
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#define slots
|
#define slots
|
||||||
|
|
||||||
// Qt includes
|
#include <QJsonValue>
|
||||||
#include <QThread>
|
|
||||||
#include <QSize>
|
|
||||||
#include <QImage>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QMap>
|
|
||||||
|
|
||||||
// Hyperion includes
|
class Effect;
|
||||||
#include <hyperion/ImageProcessor.h>
|
|
||||||
#include <utils/Components.h>
|
|
||||||
|
|
||||||
class Effect : public QThread
|
class EffectModule
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Effect(PyThreadState* mainThreadState, int priority, int timeout, const QString & script, const QString & name, const QJsonObject & args = QJsonObject(), const QString & origin="System", unsigned smoothCfg=0);
|
// Python 3 module def
|
||||||
virtual ~Effect();
|
static struct PyModuleDef moduleDef;
|
||||||
|
|
||||||
virtual void run();
|
// Init module
|
||||||
|
static PyObject* PyInit_hyperion();
|
||||||
|
|
||||||
int getPriority() const { return _priority; };
|
// Register module once
|
||||||
|
|
||||||
QString getScript() const { return _script; }
|
|
||||||
QString getName() const { return _name; }
|
|
||||||
|
|
||||||
int getTimeout() const {return _timeout; }
|
|
||||||
|
|
||||||
QJsonObject getArgs() const { return _args; }
|
|
||||||
|
|
||||||
/// This function registers the extension module in Python
|
|
||||||
static void registerHyperionExtensionModule();
|
static void registerHyperionExtensionModule();
|
||||||
|
|
||||||
signals:
|
// json 2 python
|
||||||
void setColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms, bool clearEffects, hyperion::Components componentconst, QString origin, unsigned smoothCfg);
|
static PyObject * json2python(const QJsonValue & jsonData);
|
||||||
|
|
||||||
private:
|
|
||||||
PyObject * json2python(const QJsonValue & jsonData) const;
|
|
||||||
|
|
||||||
// Wrapper methods for Python interpreter extra buildin methods
|
// Wrapper methods for Python interpreter extra buildin methods
|
||||||
static PyMethodDef effectMethods[];
|
static PyMethodDef effectMethods[];
|
||||||
@ -72,37 +50,4 @@ private:
|
|||||||
static PyObject* wrapImageCShear (PyObject *self, PyObject *args);
|
static PyObject* wrapImageCShear (PyObject *self, PyObject *args);
|
||||||
static PyObject* wrapImageResetT (PyObject *self, PyObject *args);
|
static PyObject* wrapImageResetT (PyObject *self, PyObject *args);
|
||||||
static Effect * getEffect();
|
static Effect * getEffect();
|
||||||
|
|
||||||
static struct PyModuleDef moduleDef;
|
|
||||||
static PyObject* PyInit_hyperion();
|
|
||||||
|
|
||||||
void addImage();
|
|
||||||
|
|
||||||
PyThreadState* _mainThreadState;
|
|
||||||
|
|
||||||
const int _priority;
|
|
||||||
|
|
||||||
const int _timeout;
|
|
||||||
|
|
||||||
const QString _script;
|
|
||||||
const QString _name;
|
|
||||||
unsigned _smoothCfg;
|
|
||||||
|
|
||||||
const QJsonObject _args;
|
|
||||||
|
|
||||||
int64_t _endTime;
|
|
||||||
|
|
||||||
/// The processor for translating images to led-values
|
|
||||||
ImageProcessor * _imageProcessor;
|
|
||||||
|
|
||||||
/// Buffer for colorData
|
|
||||||
QVector<ColorRgb> _colors;
|
|
||||||
|
|
||||||
Logger* _log;
|
|
||||||
|
|
||||||
QString _origin;
|
|
||||||
QSize _imageSize;
|
|
||||||
QImage _image;
|
|
||||||
QPainter* _painter;
|
|
||||||
QVector<QImage> _imageStack;
|
|
||||||
};
|
};
|
@ -18,9 +18,8 @@ public:
|
|||||||
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
||||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||||
/// @param[in] hyperion The instance of Hyperion used to write the led values
|
|
||||||
///
|
///
|
||||||
AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority);
|
AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this dispmanx frame grabber. Releases any claimed resources.
|
/// Destructor of this dispmanx frame grabber. Releases any claimed resources.
|
||||||
|
@ -40,6 +40,10 @@ public:
|
|||||||
///
|
///
|
||||||
int grabFrame(Image<ColorRgb> & image);
|
int grabFrame(Image<ColorRgb> & image);
|
||||||
|
|
||||||
|
///
|
||||||
|
///@brief Set new width and height for dispmanx, overwrite Grabber.h impl
|
||||||
|
virtual void setWidthHeight(int width, int height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///
|
///
|
||||||
/// Updates the frame-grab flags as used by the VC library for frame grabbing
|
/// Updates the frame-grab flags as used by the VC library for frame grabbing
|
||||||
@ -48,6 +52,11 @@ private:
|
|||||||
///
|
///
|
||||||
void setFlags(const int vc_flags);
|
void setFlags(const int vc_flags);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief free _vc_resource and captureBuffer
|
||||||
|
///
|
||||||
|
void freeResources();
|
||||||
|
|
||||||
/// Handle to the display that is being captured
|
/// Handle to the display that is being captured
|
||||||
DISPMANX_DISPLAY_HANDLE_T _vc_display;
|
DISPMANX_DISPLAY_HANDLE_T _vc_display;
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the
|
/// The DispmanxWrapper uses an instance of the DispmanxFrameGrabber to obtain ImageRgb's from the
|
||||||
/// displayed content. This ImageRgb is processed to a ColorRgb for each led and commmited to the
|
/// displayed content. This ImageRgb is forwarded to all Hyperion instances via HyperionDaemon
|
||||||
/// attached Hyperion.
|
|
||||||
///
|
///
|
||||||
class DispmanxWrapper: public GrabberWrapper
|
class DispmanxWrapper: public GrabberWrapper
|
||||||
{
|
{
|
||||||
@ -20,9 +19,8 @@ public:
|
|||||||
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
||||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||||
/// @param[in] hyperion The instance of Hyperion used to write the led values
|
|
||||||
///
|
///
|
||||||
DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority);
|
DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this dispmanx frame grabber. Releases any claimed resources.
|
/// Destructor of this dispmanx frame grabber. Releases any claimed resources.
|
||||||
|
@ -30,6 +30,11 @@ public:
|
|||||||
///
|
///
|
||||||
int grabFrame(Image<ColorRgb> & image);
|
int grabFrame(Image<ColorRgb> & image);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Overwrite Grabber.h implememtation
|
||||||
|
///
|
||||||
|
virtual void setDevicePath(const QString& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Framebuffer file descriptor
|
/// Framebuffer file descriptor
|
||||||
int _fbfd;
|
int _fbfd;
|
||||||
@ -38,5 +43,5 @@ private:
|
|||||||
unsigned char * _fbp;
|
unsigned char * _fbp;
|
||||||
|
|
||||||
/// Framebuffer device e.g. /dev/fb0
|
/// Framebuffer device e.g. /dev/fb0
|
||||||
const QString _fbDevice;
|
QString _fbDevice;
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||||
///
|
///
|
||||||
FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority);
|
FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this framebuffer frame grabber. Releases any claimed resources.
|
/// Destructor of this framebuffer frame grabber. Releases any claimed resources.
|
||||||
|
@ -37,9 +37,14 @@ public:
|
|||||||
///
|
///
|
||||||
int grabFrame(Image<ColorRgb> & image);
|
int grabFrame(Image<ColorRgb> & image);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
virtual void setDisplayIndex(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// display
|
/// display
|
||||||
const unsigned _screenIndex;
|
unsigned _screenIndex;
|
||||||
|
|
||||||
/// Reference to the captured diaplay
|
/// Reference to the captured diaplay
|
||||||
CGDirectDisplayID _display;
|
CGDirectDisplayID _display;
|
||||||
|
@ -19,9 +19,8 @@ public:
|
|||||||
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
/// @param[in] grabWidth The width of the grabbed image [pixels]
|
||||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||||
/// @param[in] hyperion The instance of Hyperion used to write the led values
|
|
||||||
///
|
///
|
||||||
OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority);
|
OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this osx frame grabber. Releases any claimed resources.
|
/// Destructor of this osx frame grabber. Releases any claimed resources.
|
||||||
|
@ -24,12 +24,9 @@ class V4L2Grabber : public Grabber
|
|||||||
public:
|
public:
|
||||||
V4L2Grabber(const QString & device,
|
V4L2Grabber(const QString & device,
|
||||||
int input,
|
int input,
|
||||||
VideoStandard videoStandard, PixelFormat pixelFormat,
|
VideoStandard videoStandard,
|
||||||
unsigned width,
|
PixelFormat pixelFormat,
|
||||||
unsigned height,
|
int pixelDecimation
|
||||||
int frameDecimation,
|
|
||||||
int horizontalPixelDecimation,
|
|
||||||
int verticalPixelDecimation
|
|
||||||
);
|
);
|
||||||
virtual ~V4L2Grabber();
|
virtual ~V4L2Grabber();
|
||||||
|
|
||||||
@ -38,20 +35,45 @@ public:
|
|||||||
|
|
||||||
int grabFrame(Image<ColorRgb> &);
|
int grabFrame(Image<ColorRgb> &);
|
||||||
|
|
||||||
public slots:
|
///
|
||||||
void setSignalThreshold(
|
/// @brief overwrite Grabber.h implementation, as v4l doesn't use width/height
|
||||||
|
///
|
||||||
|
virtual void setWidthHeight(){};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief set new PixelDecimation value to ImageResampler
|
||||||
|
/// @param pixelDecimation The new pixelDecimation value
|
||||||
|
///
|
||||||
|
virtual void setPixelDecimation(int pixelDecimation);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
virtual void setSignalThreshold(
|
||||||
double redSignalThreshold,
|
double redSignalThreshold,
|
||||||
double greenSignalThreshold,
|
double greenSignalThreshold,
|
||||||
double blueSignalThreshold,
|
double blueSignalThreshold,
|
||||||
int noSignalCounterThreshold);
|
int noSignalCounterThreshold = 50);
|
||||||
|
|
||||||
void setSignalDetectionOffset(
|
///
|
||||||
|
/// @brief overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
virtual void setSignalDetectionOffset(
|
||||||
double verticalMin,
|
double verticalMin,
|
||||||
double horizontalMin,
|
double horizontalMin,
|
||||||
double verticalMax,
|
double verticalMax,
|
||||||
double horizontalMax);
|
double horizontalMax);
|
||||||
|
///
|
||||||
|
/// @brief overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
virtual void setSignalDetectionEnable(bool enable);
|
||||||
|
|
||||||
void setSignalDetectionEnable(bool enable);
|
///
|
||||||
|
/// @brief overwrite Grabber.h implementation
|
||||||
|
///
|
||||||
|
virtual void setInputVideoStandard(int input, VideoStandard videoStandard);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
@ -120,9 +142,9 @@ private:
|
|||||||
std::vector<buffer> _buffers;
|
std::vector<buffer> _buffers;
|
||||||
|
|
||||||
PixelFormat _pixelFormat;
|
PixelFormat _pixelFormat;
|
||||||
|
int _pixelDecimation;
|
||||||
int _lineLength;
|
int _lineLength;
|
||||||
int _frameByteSize;
|
int _frameByteSize;
|
||||||
int _frameDecimation;
|
|
||||||
|
|
||||||
// signal detection
|
// signal detection
|
||||||
int _noSignalCounterThreshold;
|
int _noSignalCounterThreshold;
|
||||||
@ -134,7 +156,6 @@ private:
|
|||||||
double _y_frac_min;
|
double _y_frac_min;
|
||||||
double _x_frac_max;
|
double _x_frac_max;
|
||||||
double _y_frac_max;
|
double _y_frac_max;
|
||||||
int _currentFrame;
|
|
||||||
|
|
||||||
QSocketNotifier * _streamNotifier;
|
QSocketNotifier * _streamNotifier;
|
||||||
|
|
||||||
|
@ -12,14 +12,7 @@ public:
|
|||||||
int input,
|
int input,
|
||||||
VideoStandard videoStandard,
|
VideoStandard videoStandard,
|
||||||
PixelFormat pixelFormat,
|
PixelFormat pixelFormat,
|
||||||
unsigned width,
|
int pixelDecimation );
|
||||||
unsigned height,
|
|
||||||
int frameDecimation,
|
|
||||||
int pixelDecimation,
|
|
||||||
double redSignalThreshold,
|
|
||||||
double greenSignalThreshold,
|
|
||||||
double blueSignalThreshold,
|
|
||||||
const int priority);
|
|
||||||
virtual ~V4L2Wrapper() {};
|
virtual ~V4L2Wrapper() {};
|
||||||
|
|
||||||
bool getSignalDetectionEnable();
|
bool getSignalDetectionEnable();
|
||||||
@ -28,19 +21,16 @@ public slots:
|
|||||||
bool start();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold);
|
||||||
void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom);
|
void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom);
|
||||||
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
|
void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax);
|
||||||
void setSignalDetectionEnable(bool enable);
|
void setSignalDetectionEnable(bool enable);
|
||||||
|
|
||||||
// signals:
|
|
||||||
// void emitColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void newFrame(const Image<ColorRgb> & image);
|
void newFrame(const Image<ColorRgb> & image);
|
||||||
void readError(const char* err);
|
void readError(const char* err);
|
||||||
|
|
||||||
virtual void action();
|
virtual void action();
|
||||||
void checkSources();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The V4L2 grabber
|
/// The V4L2 grabber
|
||||||
|
@ -17,7 +17,7 @@ class X11Grabber : public Grabber
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
X11Grabber(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation);
|
X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation);
|
||||||
|
|
||||||
virtual ~X11Grabber();
|
virtual ~X11Grabber();
|
||||||
|
|
||||||
@ -39,8 +39,27 @@ public:
|
|||||||
|
|
||||||
virtual void setVideoMode(VideoMode mode);
|
virtual void setVideoMode(VideoMode mode);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply new width/height values, overwrite Grabber.h implementation as X11 doesn't use width/height, just pixelDecimation to calc dimensions
|
||||||
|
///
|
||||||
|
virtual void setWidthHeight(int width, int height);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply new pixelDecimation
|
||||||
|
///
|
||||||
|
virtual void setPixelDecimation(int pixelDecimation);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set the crop values
|
||||||
|
/// @param cropLeft Left pixel crop
|
||||||
|
/// @param cropRight Right pixel crop
|
||||||
|
/// @param cropTop Top pixel crop
|
||||||
|
/// @param cropBottom Bottom pixel crop
|
||||||
|
///
|
||||||
|
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _useXGetImage, _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
bool _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable;
|
||||||
|
|
||||||
XImage* _xImage;
|
XImage* _xImage;
|
||||||
XShmSegmentInfo _shminfo;
|
XShmSegmentInfo _shminfo;
|
||||||
@ -58,8 +77,7 @@ private:
|
|||||||
Picture _dstPicture;
|
Picture _dstPicture;
|
||||||
|
|
||||||
XTransform _transform;
|
XTransform _transform;
|
||||||
int _horizontalDecimation;
|
int _pixelDecimation;
|
||||||
int _verticalDecimation;
|
|
||||||
|
|
||||||
unsigned _screenWidth;
|
unsigned _screenWidth;
|
||||||
unsigned _screenHeight;
|
unsigned _screenHeight;
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
/// @param[in] grabHeight The height of the grabbed images [pixels]
|
||||||
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
/// @param[in] updateRate_Hz The image grab rate [Hz]
|
||||||
///
|
///
|
||||||
X11Wrapper(bool useXGetImage, int cropLeft, int cropRight, int cropTop, int cropBottom, int horizontalPixelDecimation, int verticalPixelDecimation, const unsigned updateRate_Hz, const int priority);
|
X11Wrapper(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor of this framebuffer frame grabber. Releases any claimed resources.
|
/// Destructor of this framebuffer frame grabber. Releases any claimed resources.
|
||||||
@ -43,4 +43,3 @@ private:
|
|||||||
|
|
||||||
bool _init;
|
bool _init;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
71
include/hyperion/BGEffectHandler.h
Normal file
71
include/hyperion/BGEffectHandler.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle the background Effect settings, reacts on runtime to settings changes
|
||||||
|
///
|
||||||
|
class BGEffectHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
BGEffectHandler(Hyperion* hyperion)
|
||||||
|
: QObject(hyperion)
|
||||||
|
, _hyperion(hyperion)
|
||||||
|
{
|
||||||
|
// listen for config changes
|
||||||
|
connect(_hyperion, &Hyperion::settingsChanged, this, &BGEffectHandler::handleSettingsUpdate);
|
||||||
|
|
||||||
|
// init
|
||||||
|
handleSettingsUpdate(settings::BGEFFECT, _hyperion->getSetting(settings::BGEFFECT));
|
||||||
|
};
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
||||||
|
{
|
||||||
|
if(type == settings::BGEFFECT)
|
||||||
|
{
|
||||||
|
const QJsonObject& BGEffectConfig = config.object();
|
||||||
|
|
||||||
|
#define BGCONFIG_ARRAY bgColorConfig.toArray()
|
||||||
|
// clear bg prioritiy
|
||||||
|
_hyperion->clear(254);
|
||||||
|
// initial background effect/color
|
||||||
|
if (BGEffectConfig["enable"].toBool(true))
|
||||||
|
{
|
||||||
|
const QString bgTypeConfig = BGEffectConfig["type"].toString("effect");
|
||||||
|
const QString bgEffectConfig = BGEffectConfig["effect"].toString("Warm mood blobs");
|
||||||
|
const QJsonValue bgColorConfig = BGEffectConfig["color"];
|
||||||
|
if (bgTypeConfig.contains("color"))
|
||||||
|
{
|
||||||
|
ColorRgb bg_color = {
|
||||||
|
(uint8_t)BGCONFIG_ARRAY.at(0).toInt(0),
|
||||||
|
(uint8_t)BGCONFIG_ARRAY.at(1).toInt(0),
|
||||||
|
(uint8_t)BGCONFIG_ARRAY.at(2).toInt(0)
|
||||||
|
};
|
||||||
|
_hyperion->setColor(254, bg_color);
|
||||||
|
Info(Logger::getInstance("HYPERION"),"Inital background color set (%d %d %d)",bg_color.red,bg_color.green,bg_color.blue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = _hyperion->setEffect(bgEffectConfig, 254);
|
||||||
|
Info(Logger::getInstance("HYPERION"),"Inital background effect '%s' %s", QSTRING_CSTR(bgEffectConfig), ((result == 0) ? "started" : "failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef BGCONFIG_ARRAY
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Hyperion instance pointer
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
};
|
62
include/hyperion/CaptureCont.h
Normal file
62
include/hyperion/CaptureCont.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
#include <utils/Components.h>
|
||||||
|
#include <utils/Image.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Capture Control class which is a interface to the HyperionDaemon native capture classes.
|
||||||
|
/// It controls the instance based enable/disable of capture feeds and PriorityMuxer registrations
|
||||||
|
///
|
||||||
|
class CaptureCont : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CaptureCont(Hyperion* hyperion);
|
||||||
|
~CaptureCont();
|
||||||
|
|
||||||
|
void setSystemCaptureEnable(const bool& enable);
|
||||||
|
void setV4LCaptureEnable(const bool& enable);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// @brief Handle component state change of V4L and SystemCapture
|
||||||
|
/// @param component The component from enum
|
||||||
|
/// @param enable The new state
|
||||||
|
///
|
||||||
|
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief forward system image
|
||||||
|
/// @param image The image
|
||||||
|
///
|
||||||
|
void handleSystemImage(const Image<ColorRgb>& image);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief forward v4l image
|
||||||
|
/// @param image The image
|
||||||
|
///
|
||||||
|
void handleV4lImage(const Image<ColorRgb> & image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Hyperion instance
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
|
||||||
|
/// Reflect state of System capture and prio
|
||||||
|
bool _systemCaptEnabled;
|
||||||
|
quint8 _systemCaptPrio;
|
||||||
|
|
||||||
|
/// Reflect state of v4l capture and prio
|
||||||
|
bool _v4lCaptEnabled;
|
||||||
|
quint8 _v4lCaptPrio;
|
||||||
|
};
|
@ -8,21 +8,61 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief The component register reflects and manages the current state of all components and Hyperion as a whole
|
||||||
|
/// It emits also real component state changes (triggert from the specific component), which can be used for listening APIs (Network Clients/Plugins)
|
||||||
|
///
|
||||||
class ComponentRegister : public QObject
|
class ComponentRegister : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ComponentRegister();
|
ComponentRegister(Hyperion* hyperion);
|
||||||
~ComponentRegister();
|
~ComponentRegister();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Enable or disable Hyperion (all components)
|
||||||
|
/// @param state The new state of Hyperion
|
||||||
|
///
|
||||||
|
/// @return Returns true on success, false when Hyperion is already at the requested state
|
||||||
|
///
|
||||||
|
bool setHyperionEnable(const bool& state);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Check if a component is currently enabled
|
||||||
|
/// @param comp The component from enum
|
||||||
|
/// @return True if component is running else false
|
||||||
|
///
|
||||||
|
bool isComponentEnabled(const hyperion::Components& comp) const;
|
||||||
|
|
||||||
|
/// contains all components and their state
|
||||||
std::map<hyperion::Components, bool> getRegister() { return _componentStates; };
|
std::map<hyperion::Components, bool> getRegister() { return _componentStates; };
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a component changed (really) the state
|
||||||
|
/// @param comp The component
|
||||||
|
/// @param state The new state of the component
|
||||||
|
///
|
||||||
|
void updatedComponentState(const hyperion::Components comp, const bool state);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
///
|
||||||
|
/// @brief is called whenever a component change a state, DO NOT CALL FROM API (use hyperion->setComponentState() instead)
|
||||||
|
/// @param comp The component
|
||||||
|
/// @param state The new state of the component
|
||||||
|
///
|
||||||
void componentStateChanged(const hyperion::Components comp, const bool activated);
|
void componentStateChanged(const hyperion::Components comp, const bool activated);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<hyperion::Components, bool> _componentStates;
|
/// Hyperion instance
|
||||||
|
Hyperion * _hyperion;
|
||||||
|
/// Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
/// current state of all components
|
||||||
|
std::map<hyperion::Components, bool> _componentStates;
|
||||||
|
/// on hyperion off we save the previous states of all components
|
||||||
|
std::map<hyperion::Components, bool> _prevComponentStates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,14 @@
|
|||||||
#include <utils/ColorRgb.h>
|
#include <utils/ColorRgb.h>
|
||||||
#include <utils/Image.h>
|
#include <utils/Image.h>
|
||||||
#include <utils/VideoMode.h>
|
#include <utils/VideoMode.h>
|
||||||
|
#include <grabber/VideoStandard.h>
|
||||||
#include <utils/ImageResampler.h>
|
#include <utils/ImageResampler.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief The Grabber class is responsible to apply image resizes (with or without ImageResampler)
|
||||||
|
/// Overwrite the videoMode with setVideoMode()
|
||||||
|
/// Overwrite setCropping()
|
||||||
class Grabber : public QObject
|
class Grabber : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -24,14 +28,71 @@ public:
|
|||||||
///
|
///
|
||||||
virtual void setVideoMode(VideoMode mode);
|
virtual void setVideoMode(VideoMode mode);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply new crop values, on errors reject the values
|
||||||
|
///
|
||||||
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
|
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
|
||||||
|
|
||||||
/// gets resulting height of image
|
///
|
||||||
|
/// @brief Apply new width/height values, on errors (collide with cropping) reject the values
|
||||||
|
///
|
||||||
|
virtual void setWidthHeight(int width, int height);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply new pixelDecimation (used from x11)
|
||||||
|
///
|
||||||
|
virtual void setPixelDecimation(int pixelDecimation) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply new signalThreshold (used from v4l)
|
||||||
|
///
|
||||||
|
virtual void setSignalThreshold(
|
||||||
|
double redSignalThreshold,
|
||||||
|
double greenSignalThreshold,
|
||||||
|
double blueSignalThreshold,
|
||||||
|
int noSignalCounterThreshold = 50) {};
|
||||||
|
///
|
||||||
|
/// @brief Apply new SignalDetectionOffset (used from v4l)
|
||||||
|
///
|
||||||
|
virtual void setSignalDetectionOffset(
|
||||||
|
double verticalMin,
|
||||||
|
double horizontalMin,
|
||||||
|
double verticalMax,
|
||||||
|
double horizontalMax) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply SignalDetectionEnable (used from v4l)
|
||||||
|
///
|
||||||
|
virtual void setSignalDetectionEnable(bool enable) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply input and videoStanded (used from v4l)
|
||||||
|
///
|
||||||
|
virtual void setInputVideoStandard(int input, VideoStandard videoStandard) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply display index (used from x11)
|
||||||
|
///
|
||||||
|
virtual void setDisplayIndex(int index) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply path for device (used from framebuffer)
|
||||||
|
///
|
||||||
|
virtual void setDevicePath(const QString& path) {};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief get current resulting height of image (after crop)
|
||||||
|
///
|
||||||
virtual const int getImageWidth() { return _width; };
|
virtual const int getImageWidth() { return _width; };
|
||||||
|
|
||||||
/// gets resulting width of image
|
///
|
||||||
|
/// @brief get current resulting width of image (after crop)
|
||||||
|
///
|
||||||
virtual const int getImageHeight() { return _height; };
|
virtual const int getImageHeight() { return _height; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Prevent the real capture implementation from capturing if disabled
|
||||||
|
///
|
||||||
void setEnabled(bool enable);
|
void setEnabled(bool enable);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Components.h>
|
#include <utils/Components.h>
|
||||||
#include <hyperion/Hyperion.h>
|
#include <hyperion/Hyperion.h>
|
||||||
#include <hyperion/ImageProcessor.h>
|
|
||||||
#include <utils/Image.h>
|
#include <utils/Image.h>
|
||||||
#include <utils/ColorRgb.h>
|
#include <utils/ColorRgb.h>
|
||||||
#include <utils/VideoMode.h>
|
#include <utils/VideoMode.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
class ImageProcessor;
|
|
||||||
class Grabber;
|
class Grabber;
|
||||||
class DispmanxFrameGrabber;
|
class DispmanxFrameGrabber;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This class will be inherted by FramebufferWrapper and others which contains the real capture interface
|
||||||
|
///
|
||||||
class GrabberWrapper : public QObject
|
class GrabberWrapper : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz, const int priority, hyperion::Components grabberComponentId=hyperion::COMP_GRABBER);
|
GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz);
|
||||||
|
|
||||||
virtual ~GrabberWrapper();
|
virtual ~GrabberWrapper();
|
||||||
|
|
||||||
@ -35,8 +37,6 @@ public:
|
|||||||
///
|
///
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
|
||||||
void setImageProcessorEnabled(bool enable);
|
|
||||||
|
|
||||||
static QStringList availableGrabbers();
|
static QStringList availableGrabbers();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -45,18 +45,15 @@ public:
|
|||||||
{
|
{
|
||||||
unsigned w = grabber.getImageWidth();
|
unsigned w = grabber.getImageWidth();
|
||||||
unsigned h = grabber.getImageHeight();
|
unsigned h = grabber.getImageHeight();
|
||||||
if (_imageProcessorEnabled && ( _image.width() != w || _image.height() != h))
|
if ( _image.width() != w || _image.height() != h)
|
||||||
{
|
{
|
||||||
_processor->setSize(w, h);
|
|
||||||
_image.resize(w, h);
|
_image.resize(w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = grabber.grabFrame(_image);
|
int ret = grabber.grabFrame(_image);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
emit emitImage(_priority, _image, _timeout_ms);
|
emit systemImage(_image);
|
||||||
_processor->process(_image, _ledColors);
|
|
||||||
setColors(_ledColors, _timeout_ms);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -64,46 +61,51 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void componentStateChanged(const hyperion::Components component, bool enable);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// virtual method, should perform single frame grab and computes the led-colors
|
/// virtual method, should perform single frame grab and computes the led-colors
|
||||||
///
|
///
|
||||||
virtual void action() = 0;
|
virtual void action() = 0;
|
||||||
|
|
||||||
void actionWrapper();
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Set the video mode (2D/3D)
|
/// Set the video mode (2D/3D)
|
||||||
/// @param[in] mode The new video mode
|
/// @param[in] mode The new video mode
|
||||||
///
|
///
|
||||||
virtual void setVideoMode(const VideoMode videoMode);
|
virtual void setVideoMode(const VideoMode& videoMode);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Set the crop values
|
||||||
|
/// @param cropLeft Left pixel crop
|
||||||
|
/// @param cropRight Right pixel crop
|
||||||
|
/// @param cropTop Top pixel crop
|
||||||
|
/// @param cropBottom Bottom pixel crop
|
||||||
|
///
|
||||||
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
|
virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from HyperionDaemon Settingsmanager emit
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
virtual void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
///
|
||||||
|
/// @brief Emit the final processed image
|
||||||
|
///
|
||||||
|
void systemImage(const Image<ColorRgb>& image);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setColors(const std::vector<ColorRgb> &ledColors, const int timeout_ms);
|
|
||||||
|
|
||||||
QString _grabberName;
|
QString _grabberName;
|
||||||
|
|
||||||
/// Pointer to Hyperion for writing led values
|
/// Pointer to Hyperion for writing led values
|
||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
|
|
||||||
/// The priority of the led colors
|
|
||||||
const int _priority;
|
|
||||||
|
|
||||||
/// The timer for generating events with the specified update rate
|
/// The timer for generating events with the specified update rate
|
||||||
QTimer _timer;
|
QTimer* _timer;
|
||||||
|
|
||||||
/// The update rate [Hz]
|
/// The calced update rate [ms]
|
||||||
const int _updateInterval_ms;
|
int _updateInterval_ms;
|
||||||
|
|
||||||
/// The timeout of the led colors [ms]
|
|
||||||
const int _timeout_ms;
|
|
||||||
|
|
||||||
/// The Logger instance
|
/// The Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
@ -111,18 +113,8 @@ protected:
|
|||||||
// forwarding enabled
|
// forwarding enabled
|
||||||
bool _forward;
|
bool _forward;
|
||||||
|
|
||||||
/// The processor for transforming images to led colors
|
|
||||||
ImageProcessor * _processor;
|
|
||||||
|
|
||||||
hyperion::Components _grabberComponentId;
|
|
||||||
|
|
||||||
Grabber *_ggrabber;
|
Grabber *_ggrabber;
|
||||||
|
|
||||||
/// The image used for grabbing frames
|
/// The image used for grabbing frames
|
||||||
Image<ColorRgb> _image;
|
Image<ColorRgb> _image;
|
||||||
|
|
||||||
/// The list with computed led colors
|
|
||||||
std::vector<ColorRgb> _ledColors;
|
|
||||||
|
|
||||||
bool _imageProcessorEnabled;
|
|
||||||
};
|
};
|
||||||
|
@ -8,12 +8,10 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTimer>
|
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QTimer>
|
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
|
|
||||||
// hyperion-utils includes
|
// hyperion-utils includes
|
||||||
@ -27,7 +25,6 @@
|
|||||||
#include <hyperion/LedString.h>
|
#include <hyperion/LedString.h>
|
||||||
#include <hyperion/PriorityMuxer.h>
|
#include <hyperion/PriorityMuxer.h>
|
||||||
#include <hyperion/ColorAdjustment.h>
|
#include <hyperion/ColorAdjustment.h>
|
||||||
#include <hyperion/MessageForwarder.h>
|
|
||||||
#include <hyperion/ComponentRegister.h>
|
#include <hyperion/ComponentRegister.h>
|
||||||
|
|
||||||
// Effect engine includes
|
// Effect engine includes
|
||||||
@ -35,17 +32,23 @@
|
|||||||
#include <effectengine/ActiveEffectDefinition.h>
|
#include <effectengine/ActiveEffectDefinition.h>
|
||||||
#include <effectengine/EffectSchema.h>
|
#include <effectengine/EffectSchema.h>
|
||||||
|
|
||||||
// bonjour includes
|
// settings utils
|
||||||
#include <bonjour/bonjourservicebrowser.h>
|
#include <utils/settings.h>
|
||||||
#include <bonjour/bonjourserviceresolver.h>
|
|
||||||
|
|
||||||
// Forward class declaration
|
// Forward class declaration
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
class HyperionDaemon;
|
||||||
|
class ImageProcessor;
|
||||||
|
class MessageForwarder;
|
||||||
class LedDevice;
|
class LedDevice;
|
||||||
class LinearColorSmoothing;
|
class LinearColorSmoothing;
|
||||||
class RgbTransform;
|
|
||||||
class EffectEngine;
|
class EffectEngine;
|
||||||
class RgbChannelAdjustment;
|
|
||||||
class MultiColorAdjustment;
|
class MultiColorAdjustment;
|
||||||
|
class ColorAdjustment;
|
||||||
|
class SettingsManager;
|
||||||
|
class BGEffectHandler;
|
||||||
|
class CaptureCont;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
|
/// The main class of Hyperion. This gives other 'users' access to the attached LedDevice through
|
||||||
@ -57,8 +60,6 @@ class Hyperion : public QObject
|
|||||||
public:
|
public:
|
||||||
/// Type definition of the info structure used by the priority muxer
|
/// Type definition of the info structure used by the priority muxer
|
||||||
typedef PriorityMuxer::InputInfo InputInfo;
|
typedef PriorityMuxer::InputInfo InputInfo;
|
||||||
typedef QMap<QString,int> PriorityRegister;
|
|
||||||
typedef QMap<QString,BonjourRecord> BonjourRegister;
|
|
||||||
///
|
///
|
||||||
/// RGB-Color channel enumeration
|
/// RGB-Color channel enumeration
|
||||||
///
|
///
|
||||||
@ -79,11 +80,12 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// @brief creates a new Hyperion instance, usually called from the Hyperion Daemon
|
/// @brief creates a new Hyperion instance, usually called from the Hyperion Daemon
|
||||||
/// @param[in] qjsonConfig The configuration file
|
/// @param[in] daemon The Hyperion daemon parent
|
||||||
|
/// @param[in] instance The instance id
|
||||||
/// @param[in] rootPath Root path of all hyperion userdata
|
/// @param[in] rootPath Root path of all hyperion userdata
|
||||||
/// @return Hyperion instance pointer
|
/// @return Hyperion instance pointer
|
||||||
///
|
///
|
||||||
static Hyperion* initInstance(const QJsonObject& qjsonConfig, const QString configFile, const QString rootPath);
|
static Hyperion* initInstance(HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Get a pointer of this Hyperion instance
|
/// @brief Get a pointer of this Hyperion instance
|
||||||
@ -91,11 +93,41 @@ public:
|
|||||||
///
|
///
|
||||||
static Hyperion* getInstance();
|
static Hyperion* getInstance();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get a pointer to the effect engine
|
||||||
|
/// @return EffectEngine instance pointer
|
||||||
|
///
|
||||||
|
EffectEngine* getEffectEngineInstance() { return _effectEngine; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get a pointer to the priorityMuxer instance
|
||||||
|
/// @return PriorityMuxer instance pointer
|
||||||
|
///
|
||||||
|
PriorityMuxer* getMuxerInstance() { return &_muxer; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get a setting by settings::type from SettingsManager
|
||||||
|
/// @param type The settingsType from enum
|
||||||
|
/// @return Data Document
|
||||||
|
///
|
||||||
|
QJsonDocument getSetting(const settings::type& type);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Save a complete json config
|
||||||
|
/// @param config The entire config object
|
||||||
|
/// @param correct If true will correct json against schema before save
|
||||||
|
/// @return True on success else false
|
||||||
|
///
|
||||||
|
bool saveSettings(QJsonObject config, const bool& correct = false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the number of attached leds
|
/// Returns the number of attached leds
|
||||||
///
|
///
|
||||||
unsigned getLedCount() const;
|
unsigned getLedCount() const;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Return the size of led grid
|
||||||
|
///
|
||||||
QSize getLedGridSize() const { return _ledGridSize; };
|
QSize getLedGridSize() const { return _ledGridSize; };
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -124,11 +156,9 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param[in] priority The priority channel
|
/// @param[in] priority The priority channel
|
||||||
///
|
///
|
||||||
/// @return The information of the given
|
/// @return The information of the given, a not found priority will return lowest priority as fallback
|
||||||
///
|
///
|
||||||
/// @throw std::runtime_error when the priority channel does not exist
|
const InputInfo getPriorityInfo(const int priority) const;
|
||||||
///
|
|
||||||
const InputInfo& getPriorityInfo(const int priority) const;
|
|
||||||
|
|
||||||
/// Reload the list of available effects
|
/// Reload the list of available effects
|
||||||
void reloadEffects();
|
void reloadEffects();
|
||||||
@ -145,27 +175,29 @@ public:
|
|||||||
/// @return The list of available effect schema files
|
/// @return The list of available effect schema files
|
||||||
const std::list<EffectSchema> &getEffectSchemas();
|
const std::list<EffectSchema> &getEffectSchemas();
|
||||||
|
|
||||||
/// gets the current json config object
|
/// gets the current json config object from SettingsManager
|
||||||
/// @return json config
|
/// @return json config
|
||||||
const QJsonObject& getQJsonConfig() { return _qjsonConfig; };
|
const QJsonObject& getQJsonConfig();
|
||||||
|
|
||||||
|
/// get path+filename of configfile
|
||||||
|
/// @return the current config path+filename
|
||||||
|
QString getConfigFilePath() { return _configFile; };
|
||||||
|
|
||||||
/// get filename of configfile
|
/// get filename of configfile
|
||||||
/// @return the current config filename
|
/// @return the current config filename
|
||||||
QString getConfigFileName() { return _configFile; };
|
QString getConfigFileName() const;
|
||||||
|
|
||||||
/// register a input source to a priority channel
|
///
|
||||||
/// @param name uniq name of input source
|
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()
|
||||||
/// @param origin External setter
|
/// A repeated call to update the base data of a known priority won't overwrite their current timeout
|
||||||
/// @param priority priority channel
|
/// @param[in] priority The priority of the channel
|
||||||
void registerPriority(const QString &name, const int priority);
|
/// @param[in] component The component of the channel
|
||||||
|
/// @param[in] origin Who set the channel (CustomString@IP)
|
||||||
|
/// @param[in] owner Speicifc owner string, might be empty
|
||||||
|
/// @param[in] smooth_cfg The smooth id to use
|
||||||
|
///
|
||||||
|
void registerInput(const int priority, const hyperion::Components& component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = 0);
|
||||||
|
|
||||||
/// unregister a input source to a priority channel
|
|
||||||
/// @param name uniq name of input source
|
|
||||||
void unRegisterPriority(const QString &name);
|
|
||||||
|
|
||||||
/// gets current priority register
|
|
||||||
/// @return the priority register
|
|
||||||
const PriorityRegister& getPriorityRegister() { return _priorityRegister; }
|
|
||||||
|
|
||||||
/// enable/disable automatic/priorized source selection
|
/// enable/disable automatic/priorized source selection
|
||||||
/// @param enabled the state
|
/// @param enabled the state
|
||||||
@ -178,12 +210,18 @@ public:
|
|||||||
|
|
||||||
/// gets current state of automatic/priorized source selection
|
/// gets current state of automatic/priorized source selection
|
||||||
/// @return the state
|
/// @return the state
|
||||||
bool sourceAutoSelectEnabled() { return _sourceAutoSelectEnabled; };
|
bool sourceAutoSelectEnabled();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Enable/Disable components during runtime
|
/// @brief Get the last untransformed/unadjusted led colors
|
||||||
|
/// @return The _rawLedBuffer leds
|
||||||
///
|
///
|
||||||
/// @param component The component [SMOOTHING, BLACKBORDER, FORWARDER, UDPLISTENER, BOBLIGHT_SERVER, GRABBER]
|
const std::vector<ColorRgb>& getRawLedBuffer() { return _rawLedBuffer; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Enable/Disable components during runtime, called from external API (requests)
|
||||||
|
///
|
||||||
|
/// @param component The component from enum
|
||||||
/// @param state The state of the component [true | false]
|
/// @param state The state of the component [true | false]
|
||||||
///
|
///
|
||||||
void setComponentState(const hyperion::Components component, const bool state);
|
void setComponentState(const hyperion::Components component, const bool state);
|
||||||
@ -195,54 +233,63 @@ public:
|
|||||||
bool configWriteable() { return _configWrite; };
|
bool configWriteable() { return _configWrite; };
|
||||||
|
|
||||||
/// gets the methode how image is maped to leds
|
/// gets the methode how image is maped to leds
|
||||||
int getLedMappingType() { return _ledMAppingType; };
|
const int & getLedMappingType();
|
||||||
|
|
||||||
/// get the configuration
|
|
||||||
QJsonObject getConfig() { return _qjsonConfig; };
|
|
||||||
|
|
||||||
/// get the root path for all hyperion user data files
|
/// get the root path for all hyperion user data files
|
||||||
QString getRootPath() { return _rootPath; };
|
const QString &getRootPath() { return _rootPath; };
|
||||||
|
|
||||||
/// unique id per instance
|
/// get unique id per instance
|
||||||
QString id;
|
const QString &getId(){ return _id; };
|
||||||
|
/// set unique id
|
||||||
|
void setId(QString id){ _id = id; };
|
||||||
|
|
||||||
int getLatchTime() const;
|
int getLatchTime() const;
|
||||||
|
|
||||||
/// forward smoothing config
|
/// forward smoothing config
|
||||||
unsigned addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0);
|
unsigned addSmoothingConfig(int settlingTime_ms, double ledUpdateFrequency_hz=25.0, unsigned updateDelay=0);
|
||||||
|
|
||||||
VideoMode getCurrentVideoMode() { return _videoMode; };
|
const VideoMode & getCurrentVideoMode();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get the current active led device
|
||||||
|
/// @return The device nam
|
||||||
|
/// e
|
||||||
|
const QString & getActiveDevice();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
///
|
||||||
|
/// @brief Update the current color of a priority (prev registered with registerInput())
|
||||||
|
/// DO NOT use this together with setInputImage() at the same time!
|
||||||
|
/// @param priority The priority to update
|
||||||
|
/// @param ledColors The colors
|
||||||
|
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
||||||
|
/// @param clearEffect Should be true when NOT called from an effect
|
||||||
|
/// @return True on success, false when priority is not found
|
||||||
|
///
|
||||||
|
const bool setInput(const int priority, const std::vector<ColorRgb>& ledColors, const int timeout_ms = -1, const bool& clearEffect = true);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Update the current image of a priority (prev registered with registerInput())
|
||||||
|
/// DO NOT use this together with setInput() at the same time!
|
||||||
|
/// @param priority The priority to update
|
||||||
|
/// @param image The new image
|
||||||
|
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
||||||
|
/// @param clearEffect Should be true when NOT called from an effect
|
||||||
|
/// @return True on success, false when priority is not found
|
||||||
|
///
|
||||||
|
const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1, const bool& clearEffect = true);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Writes a single color to all the leds for the given time and priority
|
/// Writes a single color to all the leds for the given time and priority
|
||||||
|
/// Registers comp color or provided type against muxer
|
||||||
|
/// Should be never used to update leds continuous
|
||||||
///
|
///
|
||||||
/// @param[in] priority The priority of the written color
|
/// @param[in] priority The priority of the written color
|
||||||
/// @param[in] ledColor The color to write to the leds
|
/// @param[in] ledColor The color to write to the leds
|
||||||
|
/// @param[in] origin The setter
|
||||||
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
|
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
|
||||||
///
|
///
|
||||||
void setColor(int priority, const ColorRgb &ledColor, const int timeout_ms, bool clearEffects = true);
|
void setColor(int priority, const ColorRgb &ledColor, const int timeout_ms = -1, const QString& origin = "System" ,bool clearEffects = true);
|
||||||
|
|
||||||
///
|
|
||||||
/// Writes the given colors to all leds for the given time and priority
|
|
||||||
///
|
|
||||||
/// @param[in] priority The priority of the written colors
|
|
||||||
/// @param[in] ledColors The colors to write to the leds
|
|
||||||
/// @param[in] timeout_ms The time the leds are set to the given colors [ms]
|
|
||||||
/// @param[in] component The current component
|
|
||||||
/// @param[in] origin Who set it
|
|
||||||
/// @param[in] smoothCfg smoothing config id
|
|
||||||
///
|
|
||||||
void setColors(int priority, const std::vector<ColorRgb> &ledColors, const int timeout_ms, bool clearEffects = true, hyperion::Components component=hyperion::COMP_INVALID, const QString origin="System", unsigned smoothCfg=SMOOTHING_MODE_DEFAULT);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Writes the given colors to all leds for the given time and priority
|
|
||||||
///
|
|
||||||
/// @param[in] priority The priority of the written colors
|
|
||||||
/// @param[in] ledColors The colors to write to the leds
|
|
||||||
/// @param[in] timeout_ms The time the leds are set to the given colors [ms]
|
|
||||||
///
|
|
||||||
void setImage(int priority, const Image<ColorRgb> & image, int duration_ms);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the list with unique adjustment identifiers
|
/// Returns the list with unique adjustment identifiers
|
||||||
@ -270,8 +317,9 @@ public slots:
|
|||||||
/// lower priority channel (or off if no more channels are set)
|
/// lower priority channel (or off if no more channels are set)
|
||||||
///
|
///
|
||||||
/// @param[in] priority The priority channel
|
/// @param[in] priority The priority channel
|
||||||
|
/// @return True on success else false (not found)
|
||||||
///
|
///
|
||||||
void clear(int priority);
|
const bool clear(int priority);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Clears all priority channels. This will switch the leds off until a new priority is written.
|
/// Clears all priority channels. This will switch the leds off until a new priority is written.
|
||||||
@ -292,44 +340,18 @@ public slots:
|
|||||||
int setEffect(const QString & effectName, const QJsonObject & args, int priority,
|
int setEffect(const QString & effectName, const QJsonObject & args, int priority,
|
||||||
int timeout = -1, const QString & pythonScript = "", const QString & origin="System");
|
int timeout = -1, const QString & pythonScript = "", const QString & origin="System");
|
||||||
|
|
||||||
/// sets the methode how image is maped to leds
|
/// sets the methode how image is maped to leds at ImageProcessor
|
||||||
void setLedMappingType(int mappingType);
|
void setLedMappingType(const int& mappingType);
|
||||||
|
|
||||||
///
|
|
||||||
Hyperion::BonjourRegister getHyperionSessions();
|
|
||||||
|
|
||||||
/// Slot which is called, when state of hyperion has been changed
|
|
||||||
void hyperionStateChanged();
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Set the video mode (2D/3D)
|
/// Set the video mode (2D/3D)
|
||||||
/// @param[in] mode The new video mode
|
/// @param[in] mode The new video mode
|
||||||
///
|
///
|
||||||
void setVideoMode(VideoMode mode);
|
void setVideoMode(const VideoMode& mode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Hyperion *_hyperion;
|
static Hyperion *_hyperion;
|
||||||
|
|
||||||
static ColorOrder createColorOrder(const QJsonObject & deviceConfig);
|
|
||||||
/**
|
|
||||||
* Construct the 'led-string' with the integration area definition per led and the color
|
|
||||||
* ordering of the RGB channels
|
|
||||||
* @param ledsConfig The configuration of the led areas
|
|
||||||
* @param deviceOrder The default RGB channel ordering
|
|
||||||
* @return The constructed ledstring
|
|
||||||
*/
|
|
||||||
static LedString createLedString(const QJsonValue & ledsConfig, const ColorOrder deviceOrder);
|
|
||||||
static LedString createLedStringClone(const QJsonValue & ledsConfig, const ColorOrder deviceOrder);
|
|
||||||
|
|
||||||
static MultiColorAdjustment * createLedColorsAdjustment(const unsigned ledCnt, const QJsonObject & colorAdjustmentConfig);
|
|
||||||
static ColorAdjustment * createColorAdjustment(const QJsonObject & adjustmentConfig);
|
|
||||||
static RgbTransform * createRgbTransform(const QJsonObject& colorConfig);
|
|
||||||
static RgbChannelAdjustment * createRgbChannelAdjustment(const QJsonObject & colorConfig, const QString channelName, const int defaultR, const int defaultG, const int defaultB);
|
|
||||||
|
|
||||||
static LinearColorSmoothing * createColorSmoothing(const QJsonObject & smoothingConfig, LedDevice* leddevice);
|
|
||||||
static MessageForwarder * createMessageForwarder(const QJsonObject & forwarderConfig);
|
|
||||||
static QSize getLedLayoutGridSize(const QJsonValue& ledsConfig);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/// Signal which is emitted when a priority channel is actively cleared
|
/// Signal which is emitted when a priority channel is actively cleared
|
||||||
/// This signal will not be emitted when a priority channel time out
|
/// This signal will not be emitted when a priority channel time out
|
||||||
@ -339,25 +361,67 @@ signals:
|
|||||||
/// This signal will not be emitted when a priority channel time out
|
/// This signal will not be emitted when a priority channel time out
|
||||||
void allChannelsCleared();
|
void allChannelsCleared();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a user request a component state change, it's up the component to listen
|
||||||
|
/// and update the component state at the componentRegister
|
||||||
|
/// @param component The component from enum
|
||||||
|
/// @param enabled The new state of the component
|
||||||
|
///
|
||||||
void componentStateChanged(const hyperion::Components component, bool enabled);
|
void componentStateChanged(const hyperion::Components component, bool enabled);
|
||||||
|
|
||||||
void imageToLedsMappingChanged(int mappingType);
|
///
|
||||||
void emitImage(int priority, const Image<ColorRgb> & image, const int timeout_ms);
|
/// @brief Emits whenever the imageToLedsMapping has changed
|
||||||
|
/// @param mappingType The new mapping type
|
||||||
|
///
|
||||||
|
void imageToLedsMappingChanged(const int& mappingType);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever the visible priority delivers a image which is applied in update()
|
||||||
|
/// priorities with ledColors won't emit this signal
|
||||||
|
/// @param image The current image
|
||||||
|
///
|
||||||
|
void currentImage(const Image<ColorRgb> & image);
|
||||||
|
|
||||||
void closing();
|
void closing();
|
||||||
|
|
||||||
/// Signal which is emitted, when a new json message should be forwarded
|
/// Signal which is emitted, when a new json message should be forwarded
|
||||||
void forwardJsonMessage(QJsonObject);
|
void forwardJsonMessage(QJsonObject);
|
||||||
|
|
||||||
/// Signal which is emitted, after the hyperionStateChanged has been processed with a emit count blocker (250ms interval)
|
///
|
||||||
void sendServerInfo();
|
/// @brief Is emitted from clients who request a videoMode change
|
||||||
|
///
|
||||||
/// Signal emitted when a 3D movie is detected
|
void videoMode(const VideoMode& mode);
|
||||||
void videoMode(VideoMode mode);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Emits whenever new untransformed ledColos data is available, reflects the current visible device
|
/// @brief A new videoMode was requested (called from Daemon!)
|
||||||
///
|
///
|
||||||
void rawLedColors(const std::vector<ColorRgb>& ledValues);
|
void newVideoMode(const VideoMode& mode);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a config part changed. SIGNAL PIPE helper for SettingsManager -> HyperionDaemon
|
||||||
|
/// @param type The settings type from enum
|
||||||
|
/// @param data The data as QJsonDocument
|
||||||
|
///
|
||||||
|
void settingsChanged(const settings::type& type, const QJsonDocument& data);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever the adjustments have been updated
|
||||||
|
///
|
||||||
|
void adjustmentChanged();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Signal pipe from EffectEngine to external, emits when effect list has been updated
|
||||||
|
///
|
||||||
|
void effectListUpdated();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief systemImage from the parent HyperionDaemon SystemCapture
|
||||||
|
///
|
||||||
|
void systemImage(const Image<ColorRgb>& image);
|
||||||
|
///
|
||||||
|
/// @brief v4lImage from the parent HyperionDaemon V4lCapture
|
||||||
|
///
|
||||||
|
void v4lImage(const Image<ColorRgb> & image);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
@ -366,13 +430,23 @@ private slots:
|
|||||||
///
|
///
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
|
|
||||||
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
|
|
||||||
void bonjourResolve();
|
|
||||||
|
|
||||||
/// check for configWriteable and modified changes, called by _fsWatcher or fallback _cTimer
|
/// check for configWriteable and modified changes, called by _fsWatcher or fallback _cTimer
|
||||||
void checkConfigState(QString cfile = NULL);
|
void checkConfigState(QString cfile = NULL);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply ComponentRegister emits for COMP_ALL. Enables/Disables core timers
|
||||||
|
/// @param comp The component
|
||||||
|
/// @param state The new state of the component
|
||||||
|
///
|
||||||
|
void updatedComponentState(const hyperion::Components comp, const bool state);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Apply settings updates for LEDS and COLOR
|
||||||
|
/// @param type The type from enum
|
||||||
|
/// @param config The configuration
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -380,7 +454,16 @@ private:
|
|||||||
///
|
///
|
||||||
/// @param[in] qjsonConfig The Json configuration
|
/// @param[in] qjsonConfig The Json configuration
|
||||||
///
|
///
|
||||||
Hyperion(const QJsonObject& qjsonConfig, const QString configFile, const QString rootPath);
|
Hyperion(HyperionDaemon* daemon, const quint8& instance, const QString configFile, const QString rootPath);
|
||||||
|
|
||||||
|
/// The parent Hyperion Daemon
|
||||||
|
HyperionDaemon* _daemon;
|
||||||
|
|
||||||
|
/// Settings manager of this instance
|
||||||
|
SettingsManager* _settingsManager;
|
||||||
|
|
||||||
|
/// Register that holds component states
|
||||||
|
ComponentRegister _componentRegister;
|
||||||
|
|
||||||
/// The specifiation of the led frame construction and picture integration
|
/// The specifiation of the led frame construction and picture integration
|
||||||
LedString _ledString;
|
LedString _ledString;
|
||||||
@ -388,6 +471,9 @@ private:
|
|||||||
/// specifiation of cloned leds
|
/// specifiation of cloned leds
|
||||||
LedString _ledStringClone;
|
LedString _ledStringClone;
|
||||||
|
|
||||||
|
/// Image Processor
|
||||||
|
ImageProcessor* _imageProcessor;
|
||||||
|
|
||||||
std::vector<ColorOrder> _ledStringColorOrder;
|
std::vector<ColorOrder> _ledStringColorOrder;
|
||||||
|
|
||||||
/// The priority muxer
|
/// The priority muxer
|
||||||
@ -408,21 +494,14 @@ private:
|
|||||||
// proto and json Message forwarder
|
// proto and json Message forwarder
|
||||||
MessageForwarder * _messageForwarder;
|
MessageForwarder * _messageForwarder;
|
||||||
|
|
||||||
// json configuration
|
|
||||||
const QJsonObject& _qjsonConfig;
|
|
||||||
|
|
||||||
/// the name of config file
|
/// the name of config file
|
||||||
QString _configFile;
|
QString _configFile;
|
||||||
|
|
||||||
/// root path for all hyperion user data files
|
/// root path for all hyperion user data files
|
||||||
QString _rootPath;
|
QString _rootPath;
|
||||||
|
|
||||||
/// The timer for handling priority channel timeouts
|
/// unique id per instance
|
||||||
QTimer _timer;
|
QString _id;
|
||||||
QTimer _timerBonjourResolver;
|
|
||||||
|
|
||||||
/// buffer for leds (with adjustment)
|
|
||||||
std::vector<ColorRgb> _ledBuffer;
|
|
||||||
|
|
||||||
/// Logger instance
|
/// Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
@ -430,32 +509,16 @@ private:
|
|||||||
/// count of hardware leds
|
/// count of hardware leds
|
||||||
unsigned _hwLedCount;
|
unsigned _hwLedCount;
|
||||||
|
|
||||||
ComponentRegister _componentRegister;
|
|
||||||
|
|
||||||
/// register of input sources and it's prio channel
|
|
||||||
PriorityRegister _priorityRegister;
|
|
||||||
|
|
||||||
/// flag indicates state for autoselection of input source
|
|
||||||
bool _sourceAutoSelectEnabled;
|
|
||||||
|
|
||||||
/// holds the current priority channel that is manualy selected
|
|
||||||
int _currentSourcePriority;
|
|
||||||
|
|
||||||
QByteArray _configHash;
|
QByteArray _configHash;
|
||||||
|
|
||||||
QSize _ledGridSize;
|
QSize _ledGridSize;
|
||||||
|
|
||||||
int _ledMAppingType;
|
/// Store the previous compID for smarter update()
|
||||||
|
|
||||||
hyperion::Components _prevCompId;
|
hyperion::Components _prevCompId;
|
||||||
BonjourServiceBrowser _bonjourBrowser;
|
|
||||||
BonjourServiceResolver _bonjourResolver;
|
|
||||||
BonjourRegister _hyperionSessions;
|
|
||||||
QString _bonjourCurrentServiceToResolve;
|
|
||||||
|
|
||||||
/// Observe filesystem changes (_configFile), if failed use Timer
|
/// Observe filesystem changes (_configFile), if failed use Timer
|
||||||
QFileSystemWatcher _fsWatcher;
|
QFileSystemWatcher _fsWatcher;
|
||||||
QTimer _cTimer;
|
QTimer* _cTimer;
|
||||||
|
|
||||||
/// holds the prev states of configWriteable and modified
|
/// holds the prev states of configWriteable and modified
|
||||||
bool _prevConfigMod = false;
|
bool _prevConfigMod = false;
|
||||||
@ -465,9 +528,16 @@ private:
|
|||||||
bool _configMod = false;
|
bool _configMod = false;
|
||||||
bool _configWrite = true;
|
bool _configWrite = true;
|
||||||
|
|
||||||
/// timers to handle severinfo blocking
|
/// Background effect instance, kept active to react on setting changes
|
||||||
QTimer _fsi_timer;
|
BGEffectHandler* _BGEffectHandler;
|
||||||
QTimer _fsi_blockTimer;
|
/// Capture control for Daemon native capture
|
||||||
|
CaptureCont* _captureCont;
|
||||||
|
|
||||||
VideoMode _videoMode;
|
// lock Hyperion::update() for exec
|
||||||
|
bool _lockUpdate = false;
|
||||||
|
|
||||||
|
/// buffer for leds (with adjustment)
|
||||||
|
std::vector<ColorRgb> _ledBuffer;
|
||||||
|
/// buffer for leds (without adjustment)
|
||||||
|
std::vector<ColorRgb> _rawLedBuffer;
|
||||||
};
|
};
|
||||||
|
@ -6,14 +6,18 @@
|
|||||||
#include <utils/Image.h>
|
#include <utils/Image.h>
|
||||||
|
|
||||||
// Hyperion includes
|
// Hyperion includes
|
||||||
#include <hyperion/ImageProcessorFactory.h>
|
|
||||||
#include <hyperion/LedString.h>
|
#include <hyperion/LedString.h>
|
||||||
#include <hyperion/ImageToLedsMap.h>
|
#include <hyperion/ImageToLedsMap.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
|
// settings
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
// Black border includes
|
// Black border includes
|
||||||
#include <blackborder/BlackBorderProcessor.h>
|
#include <blackborder/BlackBorderProcessor.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
/// The ImageProcessor translates an RGB-image to RGB-values for the leds. The processing is
|
||||||
/// performed in two steps. First the average color per led-region is computed. Second a
|
/// performed in two steps. First the average color per led-region is computed. Second a
|
||||||
@ -24,14 +28,16 @@ class ImageProcessor : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
///
|
||||||
|
/// Constructs an image-processor for translating an image to led-color values based on the
|
||||||
|
/// given led-string specification
|
||||||
|
/// @param[in] ledString LedString data
|
||||||
|
/// @param[in] hyperion Hyperion instance pointer
|
||||||
|
///
|
||||||
|
ImageProcessor(const LedString& ledString, Hyperion* hyperion);
|
||||||
|
|
||||||
~ImageProcessor();
|
~ImageProcessor();
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns the number of attached leds
|
|
||||||
///
|
|
||||||
unsigned getLedCount() const;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
/// Specifies the width and height of 'incomming' images. This will resize the buffer-image to
|
||||||
/// match the given size.
|
/// match the given size.
|
||||||
@ -42,20 +48,39 @@ public:
|
|||||||
///
|
///
|
||||||
void setSize(const unsigned width, const unsigned height);
|
void setSize(const unsigned width, const unsigned height);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Update the led string (eg on settings change)
|
||||||
|
///
|
||||||
|
void setLedString(const LedString& ledString);
|
||||||
|
|
||||||
/// Returns starte of black border detector
|
/// Returns starte of black border detector
|
||||||
bool blackBorderDetectorEnabled();
|
bool blackBorderDetectorEnabled();
|
||||||
|
|
||||||
/// Returns starte of black border detector
|
/// Returns the current _userMappingType, this may not be the current applied type!
|
||||||
int ledMappingType();
|
const int & getUserLedMappingType() { return _userMappingType; };
|
||||||
|
|
||||||
|
/// Returns the current _mappingType
|
||||||
|
const int & ledMappingType() { return _mappingType; };
|
||||||
|
|
||||||
static int mappingTypeToInt(QString mappingType);
|
static int mappingTypeToInt(QString mappingType);
|
||||||
static QString mappingTypeToStr(int mappingType);
|
static QString mappingTypeToStr(int mappingType);
|
||||||
|
|
||||||
public slots:
|
///
|
||||||
/// Enable or disable the black border detector
|
/// @brief Set the Hyperion::update() requestes led mapping type. This type is used in favour of type set with setLedMappingType.
|
||||||
void enableBlackBorderDetector(bool enable);
|
/// If you don't want to force a mapType set this to -1 (user choice will be set)
|
||||||
|
/// @param mapType The new mapping type
|
||||||
|
///
|
||||||
|
void setHardLedMappingType(int mapType);
|
||||||
|
|
||||||
/// Enable or disable the black border detector
|
public slots:
|
||||||
|
/// Enable or disable the black border detector based on component
|
||||||
|
void setBlackbarDetectDisable(bool enable);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Set the user requested led mapping.
|
||||||
|
/// The type set with setHardLedMappingType() will be used in favour to respect comp specific settings
|
||||||
|
/// @param mapType The new mapping type
|
||||||
|
///
|
||||||
void setLedMappingType(int mapType);
|
void setLedMappingType(int mapType);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -101,7 +126,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Warning(_log, "ImageProcessor::process called without image size 0");
|
Warning(_log, "ImageProcessor::process called with image size 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the computed colors
|
// return the computed colors
|
||||||
@ -134,7 +159,7 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Warning(_log, "ImageProcessor::process called without image size 0");
|
Warning(_log, "Called with image size 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,18 +175,6 @@ public:
|
|||||||
bool getScanParameters(size_t led, double & hscanBegin, double & hscanEnd, double & vscanBegin, double & vscanEnd) const;
|
bool getScanParameters(size_t led, double & hscanBegin, double & hscanEnd, double & vscanBegin, double & vscanEnd) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Friend declaration of the factory for creating ImageProcessor's
|
|
||||||
friend class ImageProcessorFactory;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs an image-processor for translating an image to led-color values based on the
|
|
||||||
/// given led-string specification
|
|
||||||
///
|
|
||||||
/// @param[in] ledString The led-string specification
|
|
||||||
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
|
|
||||||
///
|
|
||||||
ImageProcessor(const LedString &ledString, const QJsonObject &blackborderConfig);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Performs black-border detection (if enabled) on the given image
|
/// Performs black-border detection (if enabled) on the given image
|
||||||
///
|
///
|
||||||
@ -172,7 +185,7 @@ private:
|
|||||||
{
|
{
|
||||||
if (!_borderProcessor->enabled() && ( _imageToLeds->horizontalBorder()!=0 || _imageToLeds->verticalBorder()!=0 ))
|
if (!_borderProcessor->enabled() && ( _imageToLeds->horizontalBorder()!=0 || _imageToLeds->verticalBorder()!=0 ))
|
||||||
{
|
{
|
||||||
Debug(Logger::getInstance("BLACKBORDER"), "disabled, reset border");
|
Debug(_log, "Reset border");
|
||||||
_borderProcessor->process(image);
|
_borderProcessor->process(image);
|
||||||
delete _imageToLeds;
|
delete _imageToLeds;
|
||||||
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
|
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
|
||||||
@ -180,8 +193,6 @@ private:
|
|||||||
|
|
||||||
if(_borderProcessor->enabled() && _borderProcessor->process(image))
|
if(_borderProcessor->enabled() && _borderProcessor->process(image))
|
||||||
{
|
{
|
||||||
//Debug(Logger::getInstance("BLACKBORDER"), "BORDER SWITCH REQUIRED!!");
|
|
||||||
|
|
||||||
const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder();
|
const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder();
|
||||||
|
|
||||||
// Clean up the old mapping
|
// Clean up the old mapping
|
||||||
@ -203,10 +214,13 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
/// The Led-string specification
|
/// The Led-string specification
|
||||||
const LedString _ledString;
|
LedString _ledString;
|
||||||
|
|
||||||
/// The processor for black border detection
|
/// The processor for black border detection
|
||||||
hyperion::BlackBorderProcessor * _borderProcessor;
|
hyperion::BlackBorderProcessor * _borderProcessor;
|
||||||
@ -216,4 +230,11 @@ private:
|
|||||||
|
|
||||||
/// Type of image 2 led mapping
|
/// Type of image 2 led mapping
|
||||||
int _mappingType;
|
int _mappingType;
|
||||||
|
/// Type of last requested user type
|
||||||
|
int _userMappingType;
|
||||||
|
/// Type of last requested hard type
|
||||||
|
int _hardMappingType;
|
||||||
|
|
||||||
|
/// Hyperion instance pointer
|
||||||
|
Hyperion* _hyperion;
|
||||||
};
|
};
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// STL includes
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// QT includes
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
#include <hyperion/LedString.h>
|
|
||||||
|
|
||||||
// Forward class declaration
|
|
||||||
class ImageProcessor;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// The ImageProcessor is a singleton factor for creating ImageProcessors that translate images to
|
|
||||||
/// led color values.
|
|
||||||
///
|
|
||||||
class ImageProcessorFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Returns the 'singleton' instance (creates the singleton if it does not exist)
|
|
||||||
///
|
|
||||||
/// @return The singleton instance of the ImageProcessorFactory
|
|
||||||
///
|
|
||||||
static ImageProcessorFactory& getInstance();
|
|
||||||
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Initialises this factory with the given led-configuration
|
|
||||||
///
|
|
||||||
/// @param[in] ledString The led configuration
|
|
||||||
/// @param[in] blackborderConfig Contains the blackborder configuration
|
|
||||||
///
|
|
||||||
void init(const LedString& ledString, const QJsonObject &blackborderConfig, int mappingType);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller.
|
|
||||||
///
|
|
||||||
/// @return The newly created ImageProcessor
|
|
||||||
///
|
|
||||||
ImageProcessor* newImageProcessor() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// The Led-string specification
|
|
||||||
LedString _ledString;
|
|
||||||
|
|
||||||
/// Reference to the blackborder json configuration values
|
|
||||||
QJsonObject _blackborderConfig;
|
|
||||||
|
|
||||||
// image 2 led mapping type
|
|
||||||
int _mappingType;
|
|
||||||
};
|
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
// hyperion-utils includes
|
// hyperion-utils includes
|
||||||
#include <utils/Image.h>
|
#include <utils/Image.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
// hyperion includes
|
// hyperion includes
|
||||||
#include <hyperion/LedString.h>
|
#include <hyperion/LedString.h>
|
||||||
@ -86,7 +87,12 @@ namespace hyperion
|
|||||||
void getMeanLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
|
void getMeanLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
|
||||||
{
|
{
|
||||||
// Sanity check for the number of leds
|
// Sanity check for the number of leds
|
||||||
assert(_colorsMap.size() == ledColors.size());
|
//assert(_colorsMap.size() == ledColors.size());
|
||||||
|
if(_colorsMap.size() != ledColors.size())
|
||||||
|
{
|
||||||
|
Debug(Logger::getInstance("HYPERION"), "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate each led and compute the mean
|
// Iterate each led and compute the mean
|
||||||
auto led = ledColors.begin();
|
auto led = ledColors.begin();
|
||||||
@ -124,7 +130,13 @@ namespace hyperion
|
|||||||
void getUniLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
|
void getUniLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
|
||||||
{
|
{
|
||||||
// Sanity check for the number of leds
|
// Sanity check for the number of leds
|
||||||
assert(_colorsMap.size() == ledColors.size());
|
// assert(_colorsMap.size() == ledColors.size());
|
||||||
|
if(_colorsMap.size() != ledColors.size())
|
||||||
|
{
|
||||||
|
Debug(Logger::getInstance("HYPERION"), "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// calculate uni color
|
// calculate uni color
|
||||||
const ColorRgb color = calcMeanColor(image);
|
const ColorRgb color = calcMeanColor(image);
|
||||||
|
@ -10,19 +10,23 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
// Utils includes
|
// Utils includes
|
||||||
#include <utils/ColorRgb.h>
|
#include <utils/ColorRgb.h>
|
||||||
class MessageForwarder
|
#include <utils/settings.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
|
class MessageForwarder : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct JsonSlaveAddress {
|
MessageForwarder(Hyperion* hyperion, const QJsonDocument & config);
|
||||||
QHostAddress addr;
|
|
||||||
quint16 port;
|
|
||||||
};
|
|
||||||
|
|
||||||
MessageForwarder();
|
|
||||||
~MessageForwarder();
|
~MessageForwarder();
|
||||||
|
|
||||||
void addJsonSlave(QString slave);
|
void addJsonSlave(QString slave);
|
||||||
@ -31,10 +35,20 @@ public:
|
|||||||
bool protoForwardingEnabled();
|
bool protoForwardingEnabled();
|
||||||
bool jsonForwardingEnabled();
|
bool jsonForwardingEnabled();
|
||||||
bool forwardingEnabled() { return jsonForwardingEnabled() || protoForwardingEnabled(); };
|
bool forwardingEnabled() { return jsonForwardingEnabled() || protoForwardingEnabled(); };
|
||||||
QStringList getProtoSlaves();
|
QStringList getProtoSlaves() const { return _protoSlaves; };
|
||||||
QList<MessageForwarder::JsonSlaveAddress> getJsonSlaves();
|
QStringList getJsonSlaves() const { return _jsonSlaves; };
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
Logger* _log;
|
||||||
QStringList _protoSlaves;
|
QStringList _protoSlaves;
|
||||||
QList<MessageForwarder::JsonSlaveAddress> _jsonSlaves;
|
QStringList _jsonSlaves;
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void addAdjustment(ColorAdjustment * adjustment);
|
void addAdjustment(ColorAdjustment * adjustment);
|
||||||
|
|
||||||
void setAdjustmentForLed(const QString& id, const unsigned startLed, const unsigned endLed);
|
void setAdjustmentForLed(const QString& id, const unsigned startLed, unsigned endLed);
|
||||||
|
|
||||||
bool verifyAdjustments() const;
|
bool verifyAdjustments() const;
|
||||||
|
|
@ -7,23 +7,25 @@
|
|||||||
// QT includes
|
// QT includes
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
// Utils includes
|
// Utils includes
|
||||||
#include <utils/ColorRgb.h>
|
#include <utils/ColorRgb.h>
|
||||||
|
#include <utils/Image.h>
|
||||||
#include <utils/Components.h>
|
#include <utils/Components.h>
|
||||||
|
|
||||||
// global defines
|
// global defines
|
||||||
#define SMOOTHING_MODE_DEFAULT 0
|
#define SMOOTHING_MODE_DEFAULT 0
|
||||||
#define SMOOTHING_MODE_PAUSE 1
|
#define SMOOTHING_MODE_PAUSE 1
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
class Logger;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The PriorityMuxer handles the priority channels. Led values input is written to the priority map
|
/// The PriorityMuxer handles the priority channels. Led values input/ images are written to the priority map
|
||||||
/// and the muxer keeps track of all active priorities. The current priority can be queried and per
|
/// and the muxer keeps track of all active priorities. The current priority can be queried and per
|
||||||
/// priority the led colors.
|
/// priority the led colors. Handles also manual/auto selection mode, provides a lot of signals to hook into priority related events
|
||||||
///
|
///
|
||||||
class PriorityMuxer : public QObject
|
class PriorityMuxer : public QObject
|
||||||
{
|
{
|
||||||
@ -36,17 +38,20 @@ public:
|
|||||||
{
|
{
|
||||||
/// The priority of this channel
|
/// The priority of this channel
|
||||||
int priority;
|
int priority;
|
||||||
|
|
||||||
/// The absolute timeout of the channel
|
/// The absolute timeout of the channel
|
||||||
int64_t timeoutTime_ms;
|
int64_t timeoutTime_ms;
|
||||||
/// The colors for each led of the channel
|
/// The colors for each led of the channel
|
||||||
std::vector<ColorRgb> ledColors;
|
std::vector<ColorRgb> ledColors;
|
||||||
|
/// The raw Image (size should be preprocessed!)
|
||||||
|
Image<ColorRgb> image;
|
||||||
/// The component
|
/// The component
|
||||||
hyperion::Components componentId;
|
hyperion::Components componentId;
|
||||||
/// Who set it
|
/// Who set it
|
||||||
QString origin;
|
QString origin;
|
||||||
/// id fo smoothing config
|
/// id of smoothing config
|
||||||
unsigned smooth_cfg;
|
unsigned smooth_cfg;
|
||||||
|
/// specific owner description
|
||||||
|
QString owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The lowest possible priority, which is used when no priority channels are active
|
/// The lowest possible priority, which is used when no priority channels are active
|
||||||
@ -65,6 +70,38 @@ public:
|
|||||||
///
|
///
|
||||||
~PriorityMuxer();
|
~PriorityMuxer();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Start/Stop the PriorityMuxer update timer; On disabled no priority and timeout updates will be performend
|
||||||
|
/// @param enable The new state
|
||||||
|
///
|
||||||
|
void setEnable(const bool& enable);
|
||||||
|
|
||||||
|
/// @brief Enable or disable auto source selection
|
||||||
|
/// @param enable True if it should be enabled else false
|
||||||
|
/// @param update True to update _currentPriority - INTERNAL usage.
|
||||||
|
/// @return True if changed has been applied, false if the state is unchanged
|
||||||
|
///
|
||||||
|
bool setSourceAutoSelectEnabled(const bool& enabel, const bool& update = true);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get the state of source auto selection
|
||||||
|
/// @return True if enabled, else false
|
||||||
|
///
|
||||||
|
bool isSourceAutoSelectEnabled() const { return _sourceAutoSelectEnabled; };
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Overwrite current lowest piority with manual selection; On success disables aito selection
|
||||||
|
/// @param priority The
|
||||||
|
/// @return True on success, false if priority not found
|
||||||
|
///
|
||||||
|
bool setPriority(const uint8_t priority);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Update all ledColos with min length of >= 1 to fit the new led length
|
||||||
|
/// @param[in] ledCount The count of leds
|
||||||
|
///
|
||||||
|
void updateLedColorsLength(const int& ledCount);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the current priority
|
/// Returns the current priority
|
||||||
///
|
///
|
||||||
@ -87,69 +124,134 @@ public:
|
|||||||
QList<int> getPriorities() const;
|
QList<int> getPriorities() const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the information of a specified priority channel
|
/// Returns the information of a specified priority channel.
|
||||||
|
/// If a priority is no longer available the _lowestPriorityInfo (255) is returned
|
||||||
///
|
///
|
||||||
/// @param priority The priority channel
|
/// @param priority The priority channel
|
||||||
///
|
///
|
||||||
/// @return The information for the specified priority channel
|
/// @return The information for the specified priority channel
|
||||||
///
|
///
|
||||||
/// @throws std::runtime_error if the priority channel does not exist
|
const InputInfo getInputInfo(const int priority) const;
|
||||||
///
|
|
||||||
const InputInfo& getInputInfo(const int priority) const;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets/Updates the data for a priority channel
|
/// @brief Register a new input by priority, the priority is not active (timeout -100 isn't muxer recognized) until you start to update the data with setInput()
|
||||||
///
|
/// A repeated call to update the base data of a known priority won't overwrite their current timeout
|
||||||
/// @param[in] priority The priority of the channel
|
/// @param[in] priority The priority of the channel
|
||||||
/// @param[in] ledColors The led colors of the priority channel
|
|
||||||
/// @param[in] timeoutTime_ms The absolute timeout time of the channel
|
|
||||||
/// @param[in] component The component of the channel
|
/// @param[in] component The component of the channel
|
||||||
/// @param[in] origin Who set the channel
|
/// @param[in] origin Who set the channel (CustomString@IP)
|
||||||
|
/// @param[in] owner Speicifc owner string, might be empty
|
||||||
|
/// @param[in] smooth_cfg The smooth id to use
|
||||||
///
|
///
|
||||||
void setInput(const int priority, const std::vector<ColorRgb>& ledColors, const int64_t timeoutTime_ms=-1, hyperion::Components component=hyperion::COMP_INVALID, const QString origin="System", unsigned smooth_cfg=SMOOTHING_MODE_DEFAULT);
|
void registerInput(const int priority, const hyperion::Components& component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = SMOOTHING_MODE_DEFAULT);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Clears the specified priority channel
|
/// @brief Update the current color of a priority (prev registered with registerInput())
|
||||||
|
/// @param priority The priority to update
|
||||||
|
/// @param ledColors The colors
|
||||||
|
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
||||||
|
/// @return True on success, false when priority is not found
|
||||||
|
///
|
||||||
|
const bool setInput(const int priority, const std::vector<ColorRgb>& ledColors, int64_t timeout_ms = -1);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Update the current image of a priority (prev registered with registerInput())
|
||||||
|
/// @param priority The priority to update
|
||||||
|
/// @param image The new image
|
||||||
|
/// @param timeout_ms The new timeout (defaults to -1 endless)
|
||||||
|
/// @return True on success, false when priority is not found
|
||||||
|
///
|
||||||
|
const bool setInputImage(const int priority, const Image<ColorRgb>& image, int64_t timeout_ms = -1);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Clears the specified priority channel and update _currentPriority on success
|
||||||
///
|
///
|
||||||
/// @param[in] priority The priority of the channel to clear
|
/// @param[in] priority The priority of the channel to clear
|
||||||
|
/// @return True if priority has been cleared else false (not found)
|
||||||
///
|
///
|
||||||
void clearInput(const int priority);
|
const bool clearInput(const uint8_t priority);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Clears all priority channels
|
/// Clears all priority channels
|
||||||
///
|
///
|
||||||
void clearAll(bool forceClearAll=false);
|
void clearAll(bool forceClearAll=false);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// @brief Signal which emits when a effect or color with timeout > -1 is running, once per second
|
||||||
|
///
|
||||||
|
void timeRunner();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief A priority has been added (registerInput()) or deleted, method clear or timeout clear
|
||||||
|
/// @param priority The priority which has changed
|
||||||
|
/// @param state If true it was added else it was removed!
|
||||||
|
///
|
||||||
|
void priorityChanged(const quint8& priority, const bool& state);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever the visible priority has changed
|
||||||
|
/// @param priority The new visible prioritiy
|
||||||
|
///
|
||||||
|
void visiblePriorityChanged(const quint8& priority);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a priority changes active state
|
||||||
|
/// @param priority The priority who changed the active state
|
||||||
|
/// @param state The new state, state true = active else false
|
||||||
|
///
|
||||||
|
void activeStateChanged(const quint8& priority, const bool& state);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever the auto selection state has been changed
|
||||||
|
/// @param state The new state of auto selection; True enabled else false
|
||||||
|
///
|
||||||
|
void autoSelectChanged(const bool& state);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever something changes which influences the priorities listing
|
||||||
|
/// Emits also in 1s interval when a COLOR or EFFECT is running with a timeout > -1
|
||||||
|
///
|
||||||
|
void prioritiesChanged(void);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// internal used signal to resolve treading issues with timer
|
||||||
|
///
|
||||||
|
void signalTimeTrigger();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
///
|
||||||
|
/// Slot which is called to adapt to 1s interval for signal timeRunner() / prioritiesChanged()
|
||||||
|
///
|
||||||
|
void timeTrigger();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Updates the current time. Channels with a configured time out will be checked and cleared if
|
/// Updates the current time. Channels with a configured time out will be checked and cleared if
|
||||||
/// required.
|
/// required.
|
||||||
///
|
///
|
||||||
/// @param[in] now The current time
|
void setCurrentTime(void);
|
||||||
///
|
|
||||||
void setCurrentTime(const int64_t& now);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
///
|
|
||||||
/// Signal which is called, when a effect or color with timeout is running, once per second
|
|
||||||
///
|
|
||||||
void timerunner();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
///
|
|
||||||
/// Slots which is called to adapt to 1s interval for signal timerunner()
|
|
||||||
///
|
|
||||||
void emitReq();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// Logger instance
|
||||||
|
Logger* _log;
|
||||||
|
|
||||||
/// The current priority (lowest value in _activeInputs)
|
/// The current priority (lowest value in _activeInputs)
|
||||||
int _currentPriority;
|
int _currentPriority;
|
||||||
|
|
||||||
|
/// The manual select priority set with setPriority
|
||||||
|
int _manualSelectedPriority;
|
||||||
|
|
||||||
/// The mapping from priority channel to led-information
|
/// The mapping from priority channel to led-information
|
||||||
QMap<int, InputInfo> _activeInputs;
|
QMap<int, InputInfo> _activeInputs;
|
||||||
|
|
||||||
/// The information of the lowest priority channel
|
/// The information of the lowest priority channel
|
||||||
InputInfo _lowestPriorityInfo;
|
InputInfo _lowestPriorityInfo;
|
||||||
|
|
||||||
QTimer _timer;
|
// Reflect the state of auto select
|
||||||
QTimer _blockTimer;
|
bool _sourceAutoSelectEnabled;
|
||||||
|
|
||||||
|
// Timer to update Muxer times independent
|
||||||
|
QTimer* _updateTimer;
|
||||||
|
|
||||||
|
QTimer* _timer;
|
||||||
|
QTimer* _blockTimer;
|
||||||
};
|
};
|
||||||
|
72
include/hyperion/SettingsManager.h
Normal file
72
include/hyperion/SettingsManager.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
|
// qt incl
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
class SettingsTable;
|
||||||
|
class Hyperion;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Manage the settings read write from/to database, on settings changed will emit a signal to update components accordingly
|
||||||
|
///
|
||||||
|
class SettingsManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// @brief Construct a settings manager and assign a hyperion instance
|
||||||
|
/// @params hyperion The parent hyperion instance
|
||||||
|
/// @params instance Instance number of Hyperion
|
||||||
|
///
|
||||||
|
SettingsManager(Hyperion* hyperion, const quint8& instance, const QString& configFile);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Construct a settings manager for HyperionDaemon
|
||||||
|
///
|
||||||
|
SettingsManager(const quint8& instance, const QString& configFile);
|
||||||
|
~SettingsManager();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Save a complete json config
|
||||||
|
/// @param config The entire config object
|
||||||
|
/// @param correct If true will correct json against schema before save
|
||||||
|
/// @return True on success else false
|
||||||
|
///
|
||||||
|
const bool saveSettings(QJsonObject config, const bool& correct = false);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief get a single setting json from database
|
||||||
|
/// @param type The settings::type from enum
|
||||||
|
/// @return The requested json data as QJsonDocument
|
||||||
|
///
|
||||||
|
const QJsonDocument getSetting(const settings::type& type);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief get the full settings object of this instance (with global settings)
|
||||||
|
/// @return The requested json
|
||||||
|
///
|
||||||
|
const QJsonObject & getSettings() { return _qconfig; };
|
||||||
|
|
||||||
|
signals:
|
||||||
|
///
|
||||||
|
/// @brief Emits whenever a config part changed. Comparison of database and new data to prevent false positive
|
||||||
|
/// @param type The settings type from enum
|
||||||
|
/// @param data The data as QJsonDocument
|
||||||
|
///
|
||||||
|
void settingsChanged(const settings::type& type, const QJsonDocument& data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Hyperion instance
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
/// Logger instance
|
||||||
|
Logger* _log;
|
||||||
|
/// instance of database table interface
|
||||||
|
SettingsTable* _sTable;
|
||||||
|
/// the schema
|
||||||
|
static QJsonObject schemaJson;
|
||||||
|
/// the current config of this instance
|
||||||
|
QJsonObject _qconfig;
|
||||||
|
};
|
@ -1,14 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
// Hyperion includes
|
// Hyperion includes
|
||||||
#include <hyperion/Hyperion.h>
|
#include <utils/Components.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
|
class QTcpServer;
|
||||||
|
class QTcpSocket;
|
||||||
class JsonClientConnection;
|
class JsonClientConnection;
|
||||||
|
class BonjourServiceRegister;
|
||||||
|
class ComponentRegister;
|
||||||
|
class NetOrigin;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// This class creates a TCP server which accepts connections wich can then send
|
/// This class creates a TCP server which accepts connections wich can then send
|
||||||
@ -22,10 +28,9 @@ class JsonServer : public QObject
|
|||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
/// JsonServer constructor
|
/// JsonServer constructor
|
||||||
/// @param hyperion Hyperion instance
|
/// @param The configuration
|
||||||
/// @param port port number on which to start listening for connections
|
|
||||||
///
|
///
|
||||||
JsonServer(uint16_t port = 19444);
|
JsonServer(const QJsonDocument& config);
|
||||||
~JsonServer();
|
~JsonServer();
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -59,9 +64,16 @@ public slots:
|
|||||||
///
|
///
|
||||||
void sendMessage(const QJsonObject & message, QTcpSocket * socket);
|
void sendMessage(const QJsonObject & message, QTcpSocket * socket);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The TCP server object
|
/// The TCP server object
|
||||||
QTcpServer _server;
|
QTcpServer * _server;
|
||||||
|
|
||||||
/// Link to Hyperion to get config state emiter
|
/// Link to Hyperion to get config state emiter
|
||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
@ -72,6 +84,16 @@ private:
|
|||||||
/// the logger instance
|
/// the logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
/// Flag if forwarder is enabled
|
/// Component Register pointer
|
||||||
bool _forwarder_enabled = true;
|
ComponentRegister* _componentRegister;
|
||||||
|
|
||||||
|
NetOrigin* _netOrigin;
|
||||||
|
|
||||||
|
/// port
|
||||||
|
uint16_t _port = 0;
|
||||||
|
|
||||||
|
BonjourServiceRegister * _serviceRegister = nullptr;
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
};
|
};
|
||||||
|
@ -55,13 +55,19 @@ public:
|
|||||||
///
|
///
|
||||||
virtual int open();
|
virtual int open();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Get color order of device
|
||||||
|
/// @return The color order
|
||||||
|
///
|
||||||
|
const QString & getColorOrder() { return _colorOrder; };
|
||||||
|
|
||||||
static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr);
|
static int addToDeviceMap(QString name, LedDeviceCreateFuncType funcPtr);
|
||||||
static const LedDeviceRegistry& getDeviceMap();
|
static const LedDeviceRegistry& getDeviceMap();
|
||||||
static void setActiveDevice(QString dev);
|
void setActiveDevice(QString dev);
|
||||||
static QString activeDevice() { return _activeDevice; }
|
const QString & getActiveDevice() { return _activeDevice; };
|
||||||
static QJsonObject getLedDeviceSchemas();
|
static QJsonObject getLedDeviceSchemas();
|
||||||
static void setLedCount(int ledCount);
|
void setLedCount(int ledCount);
|
||||||
static int getLedCount() { return _ledCount; }
|
int getLedCount() { return _ledCount; }
|
||||||
|
|
||||||
void setEnable(bool enable);
|
void setEnable(bool enable);
|
||||||
bool enabled() { return _enabled; };
|
bool enabled() { return _enabled; };
|
||||||
@ -95,12 +101,12 @@ protected:
|
|||||||
|
|
||||||
bool _deviceReady;
|
bool _deviceReady;
|
||||||
|
|
||||||
static QString _activeDevice;
|
QString _activeDevice;
|
||||||
static LedDeviceRegistry _ledDeviceMap;
|
static LedDeviceRegistry _ledDeviceMap;
|
||||||
|
|
||||||
static int _ledCount;
|
int _ledCount;
|
||||||
static int _ledRGBCount;
|
int _ledRGBCount;
|
||||||
static int _ledRGBWCount;
|
int _ledRGBWCount;
|
||||||
|
|
||||||
/// Timer object which makes sure that led data is written at a minimum rate
|
/// Timer object which makes sure that led data is written at a minimum rate
|
||||||
/// e.g. Adalight device will switch off when it does not receive data at least every 15 seconds
|
/// e.g. Adalight device will switch off when it does not receive data at least every 15 seconds
|
||||||
@ -116,4 +122,5 @@ private:
|
|||||||
std::vector<ColorRgb> _ledValues;
|
std::vector<ColorRgb> _ledValues;
|
||||||
bool _componentRegistered;
|
bool _componentRegistered;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
|
QString _colorOrder;
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
// Leddevice includes
|
// Leddevice includes
|
||||||
#include <leddevice/LedDevice.h>
|
#include <leddevice/LedDevice.h>
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The LedDeviceFactory is responsible for constructing 'LedDevices'
|
/// The LedDeviceFactory is responsible for constructing 'LedDevices'
|
||||||
///
|
///
|
||||||
@ -20,5 +19,5 @@ public:
|
|||||||
/// @return The constructed LedDevice or nullptr if configuration is invalid. The ownership of
|
/// @return The constructed LedDevice or nullptr if configuration is invalid. The ownership of
|
||||||
/// the constructed LedDevice is tranferred to the caller
|
/// the constructed LedDevice is tranferred to the caller
|
||||||
///
|
///
|
||||||
static LedDevice * construct(const QJsonObject & deviceConfig, const int ledCount);
|
static LedDevice * construct(const QJsonObject & deviceConfig);
|
||||||
};
|
};
|
||||||
|
@ -4,23 +4,29 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QJsonDocument>
|
||||||
// Hyperion includes
|
|
||||||
#include <hyperion/Hyperion.h>
|
|
||||||
|
|
||||||
// hyperion includes
|
// hyperion includes
|
||||||
#include <utils/Image.h>
|
#include <utils/Image.h>
|
||||||
#include <utils/ColorRgb.h>
|
#include <utils/ColorRgb.h>
|
||||||
#include <utils/VideoMode.h>
|
#include <utils/VideoMode.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/Components.h>
|
||||||
|
|
||||||
|
// settings
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
// forward decl
|
// forward decl
|
||||||
class ProtoClientConnection;
|
class ProtoClientConnection;
|
||||||
class ProtoConnection;
|
class ProtoConnection;
|
||||||
|
class QTcpServer;
|
||||||
|
class Hyperion;
|
||||||
|
class BonjourServiceRegister;
|
||||||
|
class ComponentRegister;
|
||||||
|
class NetOrigin;
|
||||||
|
|
||||||
namespace proto {
|
namespace proto {
|
||||||
class HyperionRequest;
|
class HyperionRequest;
|
||||||
@ -38,10 +44,9 @@ class ProtoServer : public QObject
|
|||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
/// ProtoServer constructor
|
/// ProtoServer constructor
|
||||||
/// @param hyperion Hyperion instance
|
/// @param config the configuration
|
||||||
/// @param port port number on which to start listening for connections
|
|
||||||
///
|
///
|
||||||
ProtoServer(uint16_t port = 19445);
|
ProtoServer(const QJsonDocument& config);
|
||||||
~ProtoServer();
|
~ProtoServer();
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -53,6 +58,13 @@ public slots:
|
|||||||
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
|
void sendImageToProtoSlaves(int priority, const Image<ColorRgb> & image, int duration_ms);
|
||||||
void componentStateChanged(const hyperion::Components component, bool enable);
|
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
///
|
///
|
||||||
/// Forwarding videoMode
|
/// Forwarding videoMode
|
||||||
@ -78,7 +90,7 @@ private:
|
|||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
|
|
||||||
/// The TCP server object
|
/// The TCP server object
|
||||||
QTcpServer _server;
|
QTcpServer * _server;
|
||||||
|
|
||||||
/// List with open connections
|
/// List with open connections
|
||||||
QSet<ProtoClientConnection *> _openConnections;
|
QSet<ProtoClientConnection *> _openConnections;
|
||||||
@ -90,6 +102,22 @@ private:
|
|||||||
/// Logger instance
|
/// Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
|
/// Component Register
|
||||||
|
ComponentRegister* _componentRegister;
|
||||||
|
|
||||||
|
/// Network Origin Check
|
||||||
|
NetOrigin* _netOrigin;
|
||||||
|
|
||||||
|
/// Service register
|
||||||
|
BonjourServiceRegister * _serviceRegister = nullptr;
|
||||||
|
|
||||||
/// flag if forwarder is enabled
|
/// flag if forwarder is enabled
|
||||||
bool _forwarder_enabled;
|
bool _forwarder_enabled;
|
||||||
|
|
||||||
|
uint16_t _port = 0;
|
||||||
|
|
||||||
|
/// Start server
|
||||||
|
void start();
|
||||||
|
/// Stop server
|
||||||
|
void stop();
|
||||||
};
|
};
|
||||||
|
13
include/python/PythonInit.h
Normal file
13
include/python/PythonInit.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle the PythonInit, module registers and DeInit
|
||||||
|
///
|
||||||
|
class PythonInit
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend class HyperionDaemon;
|
||||||
|
|
||||||
|
PythonInit();
|
||||||
|
~PythonInit();
|
||||||
|
};
|
15
include/python/PythonUtils.h
Normal file
15
include/python/PythonUtils.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#undef slots
|
||||||
|
#include <Python.h>
|
||||||
|
#define slots
|
||||||
|
|
||||||
|
// decl
|
||||||
|
extern PyThreadState* mainThreadState;
|
||||||
|
|
||||||
|
// py path seperator
|
||||||
|
#ifdef TARGET_WINDOWS
|
||||||
|
#define PY_PATH_SEP ";";
|
||||||
|
#else // not windows
|
||||||
|
#define PY_PATH_SEP ":";
|
||||||
|
#endif
|
@ -4,16 +4,22 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
// Qt includes
|
// Qt includes
|
||||||
#include <QUdpSocket>
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
// Hyperion includes
|
// Hyperion includes
|
||||||
#include <hyperion/Hyperion.h>
|
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Components.h>
|
#include <utils/Components.h>
|
||||||
|
|
||||||
|
// settings
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
|
class Hyperion;
|
||||||
class UDPClientConnection;
|
class UDPClientConnection;
|
||||||
|
class BonjourServiceRegister;
|
||||||
|
class QUdpSocket;
|
||||||
|
class NetOrigin;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// This class creates a UDP server which accepts connections from boblight clients.
|
/// This class creates a UDP server which accepts connections from boblight clients.
|
||||||
@ -28,7 +34,7 @@ public:
|
|||||||
/// @param hyperion Hyperion instance
|
/// @param hyperion Hyperion instance
|
||||||
/// @param port port number on which to start listening for connections
|
/// @param port port number on which to start listening for connections
|
||||||
///
|
///
|
||||||
UDPListener(const int priority, const int timeout, const QString& address, quint16 listenPort, bool shared);
|
UDPListener(const QJsonDocument& config);
|
||||||
~UDPListener();
|
~UDPListener();
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -40,7 +46,6 @@ public:
|
|||||||
/// @return true if server is active (bind to a port)
|
/// @return true if server is active (bind to a port)
|
||||||
///
|
///
|
||||||
bool active() { return _isActive; };
|
bool active() { return _isActive; };
|
||||||
bool componentState() { return active(); };
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
///
|
///
|
||||||
@ -55,8 +60,12 @@ public slots:
|
|||||||
|
|
||||||
void componentStateChanged(const hyperion::Components component, bool enable);
|
void componentStateChanged(const hyperion::Components component, bool enable);
|
||||||
|
|
||||||
signals:
|
///
|
||||||
void statusChanged(bool isActive);
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
///
|
///
|
||||||
@ -84,11 +93,17 @@ private:
|
|||||||
/// Logger instance
|
/// Logger instance
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
|
||||||
|
/// Bonjour Service Register
|
||||||
|
BonjourServiceRegister* _bonjourService = nullptr;
|
||||||
|
|
||||||
/// state of connection
|
/// state of connection
|
||||||
bool _isActive;
|
bool _isActive;
|
||||||
|
|
||||||
/// address to bind
|
/// address to bind
|
||||||
QHostAddress _listenAddress;
|
QHostAddress _listenAddress;
|
||||||
quint16 _listenPort;
|
uint16_t _listenPort;
|
||||||
QAbstractSocket::BindFlag _bondage;
|
QAbstractSocket::BindFlag _bondage;
|
||||||
|
|
||||||
|
/// Check Network Origin
|
||||||
|
NetOrigin* _netOrigin;
|
||||||
};
|
};
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
namespace hyperion
|
namespace hyperion
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enumeration of components in Hyperion.
|
* Enumeration of components in Hyperion.
|
||||||
*/
|
*/
|
||||||
enum Components
|
enum Components
|
||||||
{
|
{
|
||||||
COMP_INVALID,
|
COMP_INVALID,
|
||||||
|
COMP_ALL,
|
||||||
COMP_SMOOTHING,
|
COMP_SMOOTHING,
|
||||||
COMP_BLACKBORDER,
|
COMP_BLACKBORDER,
|
||||||
COMP_FORWARDER,
|
COMP_FORWARDER,
|
||||||
@ -17,6 +19,7 @@ enum Components
|
|||||||
COMP_GRABBER,
|
COMP_GRABBER,
|
||||||
COMP_V4L,
|
COMP_V4L,
|
||||||
COMP_COLOR,
|
COMP_COLOR,
|
||||||
|
COMP_IMAGE,
|
||||||
COMP_EFFECT,
|
COMP_EFFECT,
|
||||||
COMP_PROTOSERVER,
|
COMP_PROTOSERVER,
|
||||||
COMP_LEDDEVICE
|
COMP_LEDDEVICE
|
||||||
@ -26,6 +29,7 @@ inline const char* componentToString(Components c)
|
|||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
case COMP_ALL: return "Hyperion";
|
||||||
case COMP_SMOOTHING: return "Smoothing";
|
case COMP_SMOOTHING: return "Smoothing";
|
||||||
case COMP_BLACKBORDER: return "Blackborder detector";
|
case COMP_BLACKBORDER: return "Blackborder detector";
|
||||||
case COMP_FORWARDER: return "Json/Proto forwarder";
|
case COMP_FORWARDER: return "Json/Proto forwarder";
|
||||||
@ -35,6 +39,7 @@ inline const char* componentToString(Components c)
|
|||||||
case COMP_V4L: return "V4L capture device";
|
case COMP_V4L: return "V4L capture device";
|
||||||
case COMP_COLOR: return "Solid color";
|
case COMP_COLOR: return "Solid color";
|
||||||
case COMP_EFFECT: return "Effect";
|
case COMP_EFFECT: return "Effect";
|
||||||
|
case COMP_IMAGE: return "Image";
|
||||||
case COMP_PROTOSERVER: return "Proto Server";
|
case COMP_PROTOSERVER: return "Proto Server";
|
||||||
case COMP_LEDDEVICE: return "LED device";
|
case COMP_LEDDEVICE: return "LED device";
|
||||||
default: return "";
|
default: return "";
|
||||||
@ -45,6 +50,7 @@ inline const char* componentToIdString(Components c)
|
|||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
case COMP_ALL: return "ALL";
|
||||||
case COMP_SMOOTHING: return "SMOOTHING";
|
case COMP_SMOOTHING: return "SMOOTHING";
|
||||||
case COMP_BLACKBORDER: return "BLACKBORDER";
|
case COMP_BLACKBORDER: return "BLACKBORDER";
|
||||||
case COMP_FORWARDER: return "FORWARDER";
|
case COMP_FORWARDER: return "FORWARDER";
|
||||||
@ -54,6 +60,7 @@ inline const char* componentToIdString(Components c)
|
|||||||
case COMP_V4L: return "V4L";
|
case COMP_V4L: return "V4L";
|
||||||
case COMP_COLOR: return "COLOR";
|
case COMP_COLOR: return "COLOR";
|
||||||
case COMP_EFFECT: return "EFFECT";
|
case COMP_EFFECT: return "EFFECT";
|
||||||
|
case COMP_IMAGE: return "IMAGE";
|
||||||
case COMP_PROTOSERVER: return "PROTOSERVER";
|
case COMP_PROTOSERVER: return "PROTOSERVER";
|
||||||
case COMP_LEDDEVICE: return "LEDDEVICE";
|
case COMP_LEDDEVICE: return "LEDDEVICE";
|
||||||
default: return "";
|
default: return "";
|
||||||
@ -63,6 +70,7 @@ inline const char* componentToIdString(Components c)
|
|||||||
inline Components stringToComponent(QString component)
|
inline Components stringToComponent(QString component)
|
||||||
{
|
{
|
||||||
component = component.toUpper();
|
component = component.toUpper();
|
||||||
|
if (component == "ALL") return COMP_ALL;
|
||||||
if (component == "SMOOTHING") return COMP_SMOOTHING;
|
if (component == "SMOOTHING") return COMP_SMOOTHING;
|
||||||
if (component == "BLACKBORDER") return COMP_BLACKBORDER;
|
if (component == "BLACKBORDER") return COMP_BLACKBORDER;
|
||||||
if (component == "FORWARDER") return COMP_FORWARDER;
|
if (component == "FORWARDER") return COMP_FORWARDER;
|
||||||
@ -72,6 +80,7 @@ inline Components stringToComponent(QString component)
|
|||||||
if (component == "V4L") return COMP_V4L;
|
if (component == "V4L") return COMP_V4L;
|
||||||
if (component == "COLOR") return COMP_COLOR;
|
if (component == "COLOR") return COMP_COLOR;
|
||||||
if (component == "EFFECT") return COMP_EFFECT;
|
if (component == "EFFECT") return COMP_EFFECT;
|
||||||
|
if (component == "IMAGE") return COMP_IMAGE;
|
||||||
if (component == "PROTOSERVER") return COMP_PROTOSERVER;
|
if (component == "PROTOSERVER") return COMP_PROTOSERVER;
|
||||||
if (component == "LEDDEVICE") return COMP_LEDDEVICE;
|
if (component == "LEDDEVICE") return COMP_LEDDEVICE;
|
||||||
|
|
||||||
|
@ -13,6 +13,11 @@ namespace FileUtils {
|
|||||||
QString getBaseName( QString sourceFile);
|
QString getBaseName( QString sourceFile);
|
||||||
QString getDirName( QString sourceFile);
|
QString getDirName( QString sourceFile);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief remove directory recursive given by path
|
||||||
|
/// @param[in] path Path to directory
|
||||||
|
bool removeDir(const QString& path, Logger* log);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief check if the file exists
|
/// @brief check if the file exists
|
||||||
/// @param[in] path The file path to check
|
/// @param[in] path The file path to check
|
||||||
@ -45,9 +50,10 @@ QString getDirName( QString sourceFile);
|
|||||||
/// @brief delete a file by given path
|
/// @brief delete a file by given path
|
||||||
/// @param[in] path The file path to delete
|
/// @param[in] path The file path to delete
|
||||||
/// @param[in] log The logger of the caller to print errors
|
/// @param[in] log The logger of the caller to print errors
|
||||||
|
/// @param[in] ignError Ignore errors during file delete (no log output)
|
||||||
/// @return true on success else false
|
/// @return true on success else false
|
||||||
///
|
///
|
||||||
bool removeFile(const QString& path, Logger* log);
|
bool removeFile(const QString& path, Logger* log, bool ignError=false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Convert a path that may contain special placeholders
|
/// @brief Convert a path that may contain special placeholders
|
||||||
|
@ -71,6 +71,38 @@ public:
|
|||||||
memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T));
|
memcpy(_pixels, other._pixels, other._width * other._height * sizeof(Pixel_T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define assignment operator in terms of the copy constructor
|
||||||
|
// More to read: https://stackoverflow.com/questions/255612/dynamically-allocating-an-array-of-objects?answertab=active#tab-top
|
||||||
|
Image& operator=(Image rhs)
|
||||||
|
{
|
||||||
|
rhs.swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(Image& s) noexcept
|
||||||
|
{
|
||||||
|
using std::swap;
|
||||||
|
swap(this->_width, s._width);
|
||||||
|
swap(this->_height, s._height);
|
||||||
|
swap(this->_pixels, s._pixels);
|
||||||
|
swap(this->_endOfPixels, s._endOfPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++11
|
||||||
|
Image(Image&& src) noexcept
|
||||||
|
: _width(0)
|
||||||
|
, _height(0)
|
||||||
|
, _pixels(NULL)
|
||||||
|
, _endOfPixels(NULL)
|
||||||
|
{
|
||||||
|
src.swap(*this);
|
||||||
|
}
|
||||||
|
Image& operator=(Image&& src) noexcept
|
||||||
|
{
|
||||||
|
src.swap(*this);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Destructor
|
/// Destructor
|
||||||
///
|
///
|
||||||
|
@ -1,280 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// hyperion includes
|
|
||||||
#include <utils/Logger.h>
|
|
||||||
#include <utils/jsonschema/QJsonSchemaChecker.h>
|
|
||||||
#include <utils/Components.h>
|
|
||||||
#include <hyperion/Hyperion.h>
|
|
||||||
|
|
||||||
// qt includess
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
// createEffect helper
|
|
||||||
struct find_schema: std::unary_function<EffectSchema, bool>
|
|
||||||
{
|
|
||||||
QString pyFile;
|
|
||||||
find_schema(QString pyFile):pyFile(pyFile) { }
|
|
||||||
bool operator()(EffectSchema const& schema) const
|
|
||||||
{
|
|
||||||
return schema.pyFile == pyFile;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// deleteEffect helper
|
|
||||||
struct find_effect: std::unary_function<EffectDefinition, bool>
|
|
||||||
{
|
|
||||||
QString effectName;
|
|
||||||
find_effect(QString effectName) :effectName(effectName) { }
|
|
||||||
bool operator()(EffectDefinition const& effectDefinition) const
|
|
||||||
{
|
|
||||||
return effectDefinition.name == effectName;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImageProcessor;
|
|
||||||
|
|
||||||
class JsonProcessor : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Constructor
|
|
||||||
///
|
|
||||||
/// @param peerAddress provide the Address of the peer
|
|
||||||
/// @param log The Logger class of the creator
|
|
||||||
/// @param parent Parent QObject
|
|
||||||
/// @param noListener if true, this instance won't listen for hyperion push events
|
|
||||||
///
|
|
||||||
JsonProcessor(QString peerAddress, Logger* log, QObject* parent, bool noListener = false);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message as string
|
|
||||||
///
|
|
||||||
void handleMessage(const QString & message);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// send a forced serverinfo to a client
|
|
||||||
///
|
|
||||||
void forceServerInfo();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
///
|
|
||||||
/// @brief is called whenever the current Hyperion instance pushes new led raw values (if enabled)
|
|
||||||
/// @param ledColors The current ledColors
|
|
||||||
///
|
|
||||||
void streamLedcolorsUpdate(const std::vector<ColorRgb>& ledColors);
|
|
||||||
|
|
||||||
/// push images whenever hyperion emits (if enabled)
|
|
||||||
void setImage(int priority, const Image<ColorRgb> & image, int duration_ms);
|
|
||||||
|
|
||||||
/// process and push new log messages from logger (if enabled)
|
|
||||||
void incommingLogMessage(Logger::T_LOG_MESSAGE);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
///
|
|
||||||
/// Signal which is emitted when a sendSuccessReply() has been executed
|
|
||||||
///
|
|
||||||
void pushReq();
|
|
||||||
///
|
|
||||||
/// Signal emits with the reply message provided with handleMessage()
|
|
||||||
///
|
|
||||||
void callbackMessage(QJsonObject);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Signal emits whenever a jsonmessage should be forwarded
|
|
||||||
///
|
|
||||||
void forwardJsonMessage(QJsonObject);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// The peer address of the client
|
|
||||||
QString _peerAddress;
|
|
||||||
|
|
||||||
/// Log instance
|
|
||||||
Logger* _log;
|
|
||||||
|
|
||||||
/// Hyperion instance
|
|
||||||
Hyperion* _hyperion;
|
|
||||||
|
|
||||||
/// The processor for translating images to led-values
|
|
||||||
ImageProcessor * _imageProcessor;
|
|
||||||
|
|
||||||
/// holds the state before off state
|
|
||||||
static std::map<hyperion::Components, bool> _componentsPrevState;
|
|
||||||
|
|
||||||
/// returns if hyperion is on or off
|
|
||||||
inline bool hyperionIsActive() { return JsonProcessor::_componentsPrevState.empty(); };
|
|
||||||
|
|
||||||
// streaming buffers
|
|
||||||
QJsonObject _streaming_leds_reply;
|
|
||||||
QJsonObject _streaming_image_reply;
|
|
||||||
QJsonObject _streaming_logging_reply;
|
|
||||||
bool _ledcolorsLedsActive = false;
|
|
||||||
|
|
||||||
/// flag to determine state of log streaming
|
|
||||||
bool _streaming_logging_activated;
|
|
||||||
|
|
||||||
/// mutex to determine state of image streaming
|
|
||||||
QMutex _image_stream_mutex;
|
|
||||||
/// mutex to determine state of led color streaming
|
|
||||||
QMutex _led_stream_mutex;
|
|
||||||
|
|
||||||
/// timeout for live video refresh
|
|
||||||
volatile qint64 _image_stream_timeout;
|
|
||||||
|
|
||||||
/// timeout for led color refresh
|
|
||||||
volatile qint64 _led_stream_timeout;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Color message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleColorCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Image message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleImageCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Effect message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Effect message (Write JSON Effect)
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleCreateEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Effect message (Delete JSON Effect)
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleDeleteEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON System info message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleSysInfoCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Server info message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleServerInfoCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Clear message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleClearCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Clearall message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleClearallCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Adjustment message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleAdjustmentCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON SourceSelect message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleSourceSelectCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON GetConfig message and check subcommand
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleConfigCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON GetConfig message from handleConfigCommand()
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleSchemaGetCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON GetConfig message from handleConfigCommand()
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleConfigGetCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON SetConfig message from handleConfigCommand()
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleConfigSetCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON Component State message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleComponentStateCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON Led Colors message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleLedColorsCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON Logging message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleLoggingCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON Proccessing message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleProcessingCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
/// Handle an incoming JSON VideoMode message
|
|
||||||
///
|
|
||||||
/// @param message the incoming message
|
|
||||||
///
|
|
||||||
void handleVideoModeCommand(const QJsonObject & message, const QString &command, const int tan);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Handle an incoming JSON message of unknown type
|
|
||||||
///
|
|
||||||
void handleNotImplemented();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Send a standard reply indicating success
|
|
||||||
///
|
|
||||||
void sendSuccessReply(const QString &command="", const int tan=0);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Send an error message back to the client
|
|
||||||
///
|
|
||||||
/// @param error String describing the error
|
|
||||||
///
|
|
||||||
void sendErrorReply(const QString & error, const QString &command="", const int tan=0);
|
|
||||||
};
|
|
@ -26,7 +26,7 @@ namespace JsonUtils{
|
|||||||
bool readSchema(const QString& path, QJsonObject& obj, Logger* log);
|
bool readSchema(const QString& path, QJsonObject& obj, Logger* log);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief parse a json QString and get the result on success
|
/// @brief parse a json QString and get a QJsonObject. Overloaded funtion
|
||||||
/// @param[in] path The file path/name just used for log messages
|
/// @param[in] path The file path/name just used for log messages
|
||||||
/// @param[in] data Data to parse
|
/// @param[in] data Data to parse
|
||||||
/// @param[out] obj Retuns the parsed QJsonObject
|
/// @param[out] obj Retuns the parsed QJsonObject
|
||||||
@ -35,6 +35,26 @@ namespace JsonUtils{
|
|||||||
///
|
///
|
||||||
bool parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
|
bool parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief parse a json QString and get a QJsonArray. Overloaded function
|
||||||
|
/// @param[in] path The file path/name just used for log messages
|
||||||
|
/// @param[in] data Data to parse
|
||||||
|
/// @param[out] arr Retuns the parsed QJsonArray
|
||||||
|
/// @param[in] log The logger of the caller to print errors
|
||||||
|
/// @return true on success else false
|
||||||
|
///
|
||||||
|
bool parse(const QString& path, const QString& data, QJsonArray& arr, Logger* log);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief parse a json QString and get a QJsonDocument
|
||||||
|
/// @param[in] path The file path/name just used for log messages
|
||||||
|
/// @param[in] data Data to parse
|
||||||
|
/// @param[out] doc Retuns the parsed QJsonDocument
|
||||||
|
/// @param[in] log The logger of the caller to print errors
|
||||||
|
/// @return true on success else false
|
||||||
|
///
|
||||||
|
bool parse(const QString& path, const QString& data, QJsonDocument& doc, Logger* log);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Validate json data against a schema
|
/// @brief Validate json data against a schema
|
||||||
/// @param[in] file The path/name of json file just used for log messages
|
/// @param[in] file The path/name of json file just used for log messages
|
||||||
@ -45,6 +65,16 @@ namespace JsonUtils{
|
|||||||
///
|
///
|
||||||
bool validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
|
bool validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Validate json data against a schema
|
||||||
|
/// @param[in] file The path/name of json file just used for log messages
|
||||||
|
/// @param[in] json The json data
|
||||||
|
/// @param[in] schema The schema object
|
||||||
|
/// @param[in] log The logger of the caller to print errors
|
||||||
|
/// @return true on success else false
|
||||||
|
///
|
||||||
|
bool validate(const QString& file, const QJsonObject& json, const QJsonObject& schema, Logger* log);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Write json data to file
|
/// @brief Write json data to file
|
||||||
/// @param[in] filenameThe file path to write
|
/// @param[in] filenameThe file path to write
|
||||||
|
320
include/utils/hyperion.h
Normal file
320
include/utils/hyperion.h
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hyperion/ColorAdjustment.h>
|
||||||
|
#include <hyperion/MultiColorAdjustment.h>
|
||||||
|
#include <hyperion/LedString.h>
|
||||||
|
// fg effect
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Provide utility methods for Hyperion class
|
||||||
|
///
|
||||||
|
namespace hyperion {
|
||||||
|
|
||||||
|
void handleInitialEffect(Hyperion* hyperion, const QJsonObject& FGEffectConfig)
|
||||||
|
{
|
||||||
|
#define FGCONFIG_ARRAY fgColorConfig.toArray()
|
||||||
|
const int FG_PRIORITY = 0;
|
||||||
|
const int DURATION_INFINITY = 0;
|
||||||
|
|
||||||
|
// initial foreground effect/color
|
||||||
|
if (FGEffectConfig["enable"].toBool(true))
|
||||||
|
{
|
||||||
|
const QString fgTypeConfig = FGEffectConfig["type"].toString("effect");
|
||||||
|
const QString fgEffectConfig = FGEffectConfig["effect"].toString("Rainbow swirl fast");
|
||||||
|
const QJsonValue fgColorConfig = FGEffectConfig["color"];
|
||||||
|
int default_fg_duration_ms = 3000;
|
||||||
|
int fg_duration_ms = FGEffectConfig["duration_ms"].toInt(default_fg_duration_ms);
|
||||||
|
if (fg_duration_ms == DURATION_INFINITY)
|
||||||
|
{
|
||||||
|
fg_duration_ms = default_fg_duration_ms;
|
||||||
|
Warning(Logger::getInstance("HYPERION"), "foreground effect duration 'infinity' is forbidden, set to default value %d ms",default_fg_duration_ms);
|
||||||
|
}
|
||||||
|
if ( fgTypeConfig.contains("color") )
|
||||||
|
{
|
||||||
|
ColorRgb fg_color = {
|
||||||
|
(uint8_t)FGCONFIG_ARRAY.at(0).toInt(0),
|
||||||
|
(uint8_t)FGCONFIG_ARRAY.at(1).toInt(0),
|
||||||
|
(uint8_t)FGCONFIG_ARRAY.at(2).toInt(0)
|
||||||
|
};
|
||||||
|
hyperion->setColor(FG_PRIORITY, fg_color, fg_duration_ms);
|
||||||
|
Info(Logger::getInstance("HYPERION"),"Inital foreground color set (%d %d %d)",fg_color.red,fg_color.green,fg_color.blue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int result = hyperion->setEffect(fgEffectConfig, FG_PRIORITY, fg_duration_ms);
|
||||||
|
Info(Logger::getInstance("HYPERION"),"Inital foreground effect '%s' %s", QSTRING_CSTR(fgEffectConfig), ((result == 0) ? "started" : "failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef FGCONFIG_ARRAY
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorOrder createColorOrder(const QJsonObject &deviceConfig)
|
||||||
|
{
|
||||||
|
return stringToColorOrder(deviceConfig["colorOrder"].toString("rgb"));
|
||||||
|
}
|
||||||
|
|
||||||
|
RgbTransform* createRgbTransform(const QJsonObject& colorConfig)
|
||||||
|
{
|
||||||
|
const double backlightThreshold = colorConfig["backlightThreshold"].toDouble(0.0);
|
||||||
|
const bool backlightColored = colorConfig["backlightColored"].toBool(false);
|
||||||
|
const double brightness = colorConfig["brightness"].toInt(100);
|
||||||
|
const double brightnessComp= colorConfig["brightnessCompensation"].toInt(100);
|
||||||
|
const double gammaR = colorConfig["gammaRed"].toDouble(1.0);
|
||||||
|
const double gammaG = colorConfig["gammaGreen"].toDouble(1.0);
|
||||||
|
const double gammaB = colorConfig["gammaBlue"].toDouble(1.0);
|
||||||
|
|
||||||
|
RgbTransform* transform = new RgbTransform(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessComp);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
RgbChannelAdjustment* createRgbChannelAdjustment(const QJsonObject& colorConfig, const QString channelName, const int defaultR, const int defaultG, const int defaultB)
|
||||||
|
{
|
||||||
|
const QJsonArray& channelConfig = colorConfig[channelName].toArray();
|
||||||
|
RgbChannelAdjustment* adjustment = new RgbChannelAdjustment(
|
||||||
|
channelConfig[0].toInt(defaultR),
|
||||||
|
channelConfig[1].toInt(defaultG),
|
||||||
|
channelConfig[2].toInt(defaultB),
|
||||||
|
"ChannelAdjust_"+channelName.toUpper()
|
||||||
|
);
|
||||||
|
return adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorAdjustment * createColorAdjustment(const QJsonObject & adjustmentConfig)
|
||||||
|
{
|
||||||
|
const QString id = adjustmentConfig["id"].toString("default");
|
||||||
|
|
||||||
|
RgbChannelAdjustment * blackAdjustment = createRgbChannelAdjustment(adjustmentConfig, "black" , 0, 0, 0);
|
||||||
|
RgbChannelAdjustment * whiteAdjustment = createRgbChannelAdjustment(adjustmentConfig, "white" , 255,255,255);
|
||||||
|
RgbChannelAdjustment * redAdjustment = createRgbChannelAdjustment(adjustmentConfig, "red" , 255, 0, 0);
|
||||||
|
RgbChannelAdjustment * greenAdjustment = createRgbChannelAdjustment(adjustmentConfig, "green" , 0,255, 0);
|
||||||
|
RgbChannelAdjustment * blueAdjustment = createRgbChannelAdjustment(adjustmentConfig, "blue" , 0, 0,255);
|
||||||
|
RgbChannelAdjustment * cyanAdjustment = createRgbChannelAdjustment(adjustmentConfig, "cyan" , 0,255,255);
|
||||||
|
RgbChannelAdjustment * magentaAdjustment = createRgbChannelAdjustment(adjustmentConfig, "magenta", 255, 0,255);
|
||||||
|
RgbChannelAdjustment * yellowAdjustment = createRgbChannelAdjustment(adjustmentConfig, "yellow" , 255,255, 0);
|
||||||
|
RgbTransform * rgbTransform = createRgbTransform(adjustmentConfig);
|
||||||
|
|
||||||
|
ColorAdjustment * adjustment = new ColorAdjustment();
|
||||||
|
adjustment->_id = id;
|
||||||
|
adjustment->_rgbBlackAdjustment = *blackAdjustment;
|
||||||
|
adjustment->_rgbWhiteAdjustment = *whiteAdjustment;
|
||||||
|
adjustment->_rgbRedAdjustment = *redAdjustment;
|
||||||
|
adjustment->_rgbGreenAdjustment = *greenAdjustment;
|
||||||
|
adjustment->_rgbBlueAdjustment = *blueAdjustment;
|
||||||
|
adjustment->_rgbCyanAdjustment = *cyanAdjustment;
|
||||||
|
adjustment->_rgbMagentaAdjustment = *magentaAdjustment;
|
||||||
|
adjustment->_rgbYellowAdjustment = *yellowAdjustment;
|
||||||
|
adjustment->_rgbTransform = *rgbTransform;
|
||||||
|
|
||||||
|
// Cleanup the allocated individual adjustments
|
||||||
|
delete blackAdjustment;
|
||||||
|
delete whiteAdjustment;
|
||||||
|
delete redAdjustment;
|
||||||
|
delete greenAdjustment;
|
||||||
|
delete blueAdjustment;
|
||||||
|
delete cyanAdjustment;
|
||||||
|
delete magentaAdjustment;
|
||||||
|
delete yellowAdjustment;
|
||||||
|
delete rgbTransform;
|
||||||
|
|
||||||
|
return adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiColorAdjustment * createLedColorsAdjustment(const unsigned ledCnt, const QJsonObject & colorConfig)
|
||||||
|
{
|
||||||
|
// Create the result, the transforms are added to this
|
||||||
|
MultiColorAdjustment * adjustment = new MultiColorAdjustment(ledCnt);
|
||||||
|
|
||||||
|
const QJsonValue adjustmentConfig = colorConfig["channelAdjustment"];
|
||||||
|
const QRegExp overallExp("([0-9]+(\\-[0-9]+)?)(,[ ]*([0-9]+(\\-[0-9]+)?))*");
|
||||||
|
|
||||||
|
const QJsonArray & adjustmentConfigArray = adjustmentConfig.toArray();
|
||||||
|
for (signed i = 0; i < adjustmentConfigArray.size(); ++i)
|
||||||
|
{
|
||||||
|
const QJsonObject & config = adjustmentConfigArray.at(i).toObject();
|
||||||
|
ColorAdjustment * colorAdjustment = createColorAdjustment(config);
|
||||||
|
adjustment->addAdjustment(colorAdjustment);
|
||||||
|
|
||||||
|
const QString ledIndicesStr = config["leds"].toString("").trimmed();
|
||||||
|
if (ledIndicesStr.compare("*") == 0)
|
||||||
|
{
|
||||||
|
// Special case for indices '*' => all leds
|
||||||
|
adjustment->setAdjustmentForLed(colorAdjustment->_id, 0, ledCnt-1);
|
||||||
|
//Info(_log, "ColorAdjustment '%s' => [0; %d]", QSTRING_CSTR(colorAdjustment->_id), ledCnt-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!overallExp.exactMatch(ledIndicesStr))
|
||||||
|
{
|
||||||
|
//Error(_log, "Given led indices %d not correct format: %s", i, QSTRING_CSTR(ledIndicesStr));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
const QStringList ledIndexList = ledIndicesStr.split(",");
|
||||||
|
for (int i=0; i<ledIndexList.size(); ++i) {
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
ss << ", ";
|
||||||
|
}
|
||||||
|
if (ledIndexList[i].contains("-"))
|
||||||
|
{
|
||||||
|
QStringList ledIndices = ledIndexList[i].split("-");
|
||||||
|
int startInd = ledIndices[0].toInt();
|
||||||
|
int endInd = ledIndices[1].toInt();
|
||||||
|
|
||||||
|
adjustment->setAdjustmentForLed(colorAdjustment->_id, startInd, endInd);
|
||||||
|
ss << startInd << "-" << endInd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int index = ledIndexList[i].toInt();
|
||||||
|
adjustment->setAdjustmentForLed(colorAdjustment->_id, index, index);
|
||||||
|
ss << index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Info(_log, "ColorAdjustment '%s' => [%s]", QSTRING_CSTR(colorAdjustment->_id), ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the 'led-string' with the integration area definition per led and the color
|
||||||
|
* ordering of the RGB channels
|
||||||
|
* @param ledsConfig The configuration of the led areas
|
||||||
|
* @param deviceOrder The default RGB channel ordering
|
||||||
|
* @return The constructed ledstring
|
||||||
|
*/
|
||||||
|
LedString createLedString(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 )
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize getLedLayoutGridSize(const QJsonArray& ledConfigArray)
|
||||||
|
{
|
||||||
|
std::vector<int> midPointsX;
|
||||||
|
std::vector<int> midPointsY;
|
||||||
|
|
||||||
|
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()["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) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove duplicates
|
||||||
|
std::sort(midPointsX.begin(), midPointsX.end());
|
||||||
|
midPointsX.erase(std::unique(midPointsX.begin(), midPointsX.end()), midPointsX.end());
|
||||||
|
std::sort(midPointsY.begin(), midPointsY.end());
|
||||||
|
midPointsY.erase(std::unique(midPointsY.begin(), midPointsY.end()), midPointsY.end());
|
||||||
|
|
||||||
|
QSize gridSize( midPointsX.size(), midPointsY.size() );
|
||||||
|
//Debug(_log, "led layout grid: %dx%d", gridSize.width(), gridSize.height());
|
||||||
|
|
||||||
|
return gridSize;
|
||||||
|
}
|
||||||
|
};
|
99
include/utils/settings.h
Normal file
99
include/utils/settings.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Provide util methods to work with SettingsManager class
|
||||||
|
///
|
||||||
|
namespace settings {
|
||||||
|
// all available settings sections
|
||||||
|
enum type {
|
||||||
|
BGEFFECT,
|
||||||
|
FGEFFECT,
|
||||||
|
BLACKBORDER,
|
||||||
|
BOBLSERVER,
|
||||||
|
COLOR,
|
||||||
|
DEVICE,
|
||||||
|
EFFECTS,
|
||||||
|
NETFORWARD,
|
||||||
|
SYSTEMCAPTURE,
|
||||||
|
GENERAL,
|
||||||
|
V4L2,
|
||||||
|
JSONSERVER,
|
||||||
|
LEDCONFIG,
|
||||||
|
LEDS,
|
||||||
|
LOGGER,
|
||||||
|
PROTOSERVER,
|
||||||
|
SMOOTHING,
|
||||||
|
UDPLISTENER,
|
||||||
|
WEBSERVER,
|
||||||
|
INSTCAPTURE,
|
||||||
|
NETWORK,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Convert settings::type to string representation
|
||||||
|
/// @param type The settings::type from enum
|
||||||
|
/// @return The settings type as string
|
||||||
|
///
|
||||||
|
inline QString typeToString(const type& type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case BGEFFECT: return "backgroundEffect";
|
||||||
|
case FGEFFECT: return "foregroundEffect";
|
||||||
|
case BLACKBORDER: return "blackborderdetector";
|
||||||
|
case BOBLSERVER: return "boblightServer";
|
||||||
|
case COLOR: return "color";
|
||||||
|
case DEVICE: return "device";
|
||||||
|
case EFFECTS: return "effects";
|
||||||
|
case NETFORWARD: return "forwarder";
|
||||||
|
case SYSTEMCAPTURE: return "framegrabber";
|
||||||
|
case GENERAL: return "general";
|
||||||
|
case V4L2: return "grabberV4L2";
|
||||||
|
case JSONSERVER: return "jsonServer";
|
||||||
|
case LEDCONFIG: return "ledConfig";
|
||||||
|
case LEDS: return "leds";
|
||||||
|
case LOGGER: return "logger";
|
||||||
|
case PROTOSERVER: return "protoServer";
|
||||||
|
case SMOOTHING: return "smoothing";
|
||||||
|
case UDPLISTENER: return "udpListener";
|
||||||
|
case WEBSERVER: return "webConfig";
|
||||||
|
case INSTCAPTURE: return "instCapture";
|
||||||
|
case NETWORK: return "network";
|
||||||
|
default: return "invalid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Convert string to settings::type representation
|
||||||
|
/// @param type The string to convert
|
||||||
|
/// @return The settings type from enum
|
||||||
|
///
|
||||||
|
inline type stringToType(const QString& type)
|
||||||
|
{
|
||||||
|
if (type == "backgroundEffect") return BGEFFECT;
|
||||||
|
else if (type == "foregroundEffect") return FGEFFECT;
|
||||||
|
else if (type == "blackborderdetector") return BLACKBORDER;
|
||||||
|
else if (type == "boblightServer") return BOBLSERVER;
|
||||||
|
else if (type == "color") return COLOR;
|
||||||
|
else if (type == "device") return DEVICE;
|
||||||
|
else if (type == "effects") return EFFECTS;
|
||||||
|
else if (type == "forwarder") return NETFORWARD;
|
||||||
|
else if (type == "framegrabber") return SYSTEMCAPTURE;
|
||||||
|
else if (type == "general") return GENERAL;
|
||||||
|
else if (type == "grabberV4L2") return V4L2;
|
||||||
|
else if (type == "jsonServer") return JSONSERVER;
|
||||||
|
else if (type == "ledConfig") return LEDCONFIG;
|
||||||
|
else if (type == "leds") return LEDS;
|
||||||
|
else if (type == "logger") return LOGGER;
|
||||||
|
else if (type == "protoServer") return PROTOSERVER;
|
||||||
|
else if (type == "smoothing") return SMOOTHING;
|
||||||
|
else if (type == "udpListener") return UDPLISTENER;
|
||||||
|
else if (type == "webConfig") return WEBSERVER;
|
||||||
|
else if (type == "instCapture") return INSTCAPTURE;
|
||||||
|
else if (type == "network") return NETWORK;
|
||||||
|
else return INVALID;
|
||||||
|
}
|
||||||
|
};
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef WEBCONFIG_H
|
|
||||||
#define WEBCONFIG_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <hyperion/Hyperion.h>
|
|
||||||
|
|
||||||
class StaticFileServing;
|
|
||||||
|
|
||||||
class WebConfig : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
WebConfig (QObject * parent = NULL);
|
|
||||||
|
|
||||||
virtual ~WebConfig (void);
|
|
||||||
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
quint16 getPort() { return _port; };
|
|
||||||
|
|
||||||
private:
|
|
||||||
Hyperion* _hyperion;
|
|
||||||
QString _baseUrl;
|
|
||||||
quint16 _port;
|
|
||||||
StaticFileServing* _server;
|
|
||||||
|
|
||||||
const QString WEBCONFIG_DEFAULT_PATH = ":/webconfig";
|
|
||||||
const quint16 WEBCONFIG_DEFAULT_PORT = 8099;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // WEBCONFIG_H
|
|
||||||
|
|
55
include/webserver/WebServer.h
Normal file
55
include/webserver/WebServer.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef WEBSERVER_H
|
||||||
|
#define WEBSERVER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
// hyperion / utils
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
|
// settings
|
||||||
|
#include <utils/settings.h>
|
||||||
|
|
||||||
|
class StaticFileServing;
|
||||||
|
class QtHttpServer;
|
||||||
|
|
||||||
|
class WebServer : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebServer (const QJsonDocument& config, QObject * parent = 0);
|
||||||
|
|
||||||
|
virtual ~WebServer (void);
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
quint16 getPort() { return _port; };
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onServerStopped (void);
|
||||||
|
void onServerStarted (quint16 port);
|
||||||
|
void onServerError (QString msg);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
|
||||||
|
/// @param type settingyType from enum
|
||||||
|
/// @param config configuration object
|
||||||
|
///
|
||||||
|
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger* _log;
|
||||||
|
Hyperion* _hyperion;
|
||||||
|
QString _baseUrl;
|
||||||
|
quint16 _port;
|
||||||
|
StaticFileServing* _staticFileServing;
|
||||||
|
QtHttpServer* _server;
|
||||||
|
|
||||||
|
const QString WEBSERVER_DEFAULT_PATH = ":/webconfig";
|
||||||
|
const quint16 WEBSERVER_DEFAULT_PORT = 8090;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBSERVER_H
|
@ -15,4 +15,6 @@ add_subdirectory(leddevice)
|
|||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
add_subdirectory(effectengine)
|
add_subdirectory(effectengine)
|
||||||
add_subdirectory(grabber)
|
add_subdirectory(grabber)
|
||||||
add_subdirectory(webconfig)
|
add_subdirectory(webserver)
|
||||||
|
add_subdirectory(api)
|
||||||
|
add_subdirectory(python)
|
||||||
|
@ -84,17 +84,6 @@
|
|||||||
"minItems": 3,
|
"minItems": 3,
|
||||||
"maxItems": 3
|
"maxItems": 3
|
||||||
},
|
},
|
||||||
"black": {
|
|
||||||
"type": "array",
|
|
||||||
"required": false,
|
|
||||||
"items" : {
|
|
||||||
"type": "integer",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 255
|
|
||||||
},
|
|
||||||
"minItems": 3,
|
|
||||||
"maxItems": 3
|
|
||||||
},
|
|
||||||
"white": {
|
"white": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"required": false,
|
"required": false,
|
@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"priority": {
|
"priority": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minimum" : 1,
|
"minimum" : -1,
|
||||||
"maximum" : 253,
|
"maximum" : 253,
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
@ -7,6 +7,9 @@
|
|||||||
"required" : true,
|
"required" : true,
|
||||||
"enum" : ["serverinfo"]
|
"enum" : ["serverinfo"]
|
||||||
},
|
},
|
||||||
|
"subscribe" : {
|
||||||
|
"type" : "array"
|
||||||
|
},
|
||||||
"tan" : {
|
"tan" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
}
|
}
|
@ -6,7 +6,6 @@
|
|||||||
<file alias="schema-serverinfo">JSONRPC_schema/schema-serverinfo.json</file>
|
<file alias="schema-serverinfo">JSONRPC_schema/schema-serverinfo.json</file>
|
||||||
<file alias="schema-sysinfo">JSONRPC_schema/schema-sysinfo.json</file>
|
<file alias="schema-sysinfo">JSONRPC_schema/schema-sysinfo.json</file>
|
||||||
<file alias="schema-clear">JSONRPC_schema/schema-clear.json</file>
|
<file alias="schema-clear">JSONRPC_schema/schema-clear.json</file>
|
||||||
<file alias="schema-clearall">JSONRPC_schema/schema-clearall.json</file>
|
|
||||||
<file alias="schema-adjustment">JSONRPC_schema/schema-adjustment.json</file>
|
<file alias="schema-adjustment">JSONRPC_schema/schema-adjustment.json</file>
|
||||||
<file alias="schema-effect">JSONRPC_schema/schema-effect.json</file>
|
<file alias="schema-effect">JSONRPC_schema/schema-effect.json</file>
|
||||||
<file alias="schema-create-effect">JSONRPC_schema/schema-create-effect.json</file>
|
<file alias="schema-create-effect">JSONRPC_schema/schema-create-effect.json</file>
|
@ -23,7 +23,7 @@ uint8_t BlackBorderDetector::calculateThreshold(double threshold)
|
|||||||
|
|
||||||
uint8_t blackborderThreshold = uint8_t(rgbThreshold);
|
uint8_t blackborderThreshold = uint8_t(rgbThreshold);
|
||||||
|
|
||||||
Debug(Logger::getInstance("BLACKBORDER"), "threshold set to %f (%d)", threshold , int(blackborderThreshold));
|
//Debug(Logger::getInstance("BLACKBORDER"), "threshold set to %f (%d)", threshold , int(blackborderThreshold));
|
||||||
|
|
||||||
return blackborderThreshold;
|
return blackborderThreshold;
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,105 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <utils/Logger.h>
|
#include <hyperion/Hyperion.h>
|
||||||
|
|
||||||
// Blackborder includes
|
// Blackborder includes
|
||||||
#include <blackborder/BlackBorderProcessor.h>
|
#include <blackborder/BlackBorderProcessor.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace hyperion;
|
using namespace hyperion;
|
||||||
|
|
||||||
BlackBorderProcessor::BlackBorderProcessor(const QJsonObject &blackborderConfig)
|
BlackBorderProcessor::BlackBorderProcessor(Hyperion* hyperion, QObject* parent)
|
||||||
: _enabled(blackborderConfig["enable"].toBool(true))
|
: QObject(parent)
|
||||||
, _unknownSwitchCnt(blackborderConfig["unknownFrameCnt"].toInt(600))
|
, _hyperion(hyperion)
|
||||||
, _borderSwitchCnt(blackborderConfig["borderFrameCnt"].toInt(50))
|
, _enabled(false)
|
||||||
, _maxInconsistentCnt(blackborderConfig["maxInconsistentCnt"].toInt(10))
|
, _unknownSwitchCnt(600)
|
||||||
, _blurRemoveCnt(blackborderConfig["blurRemoveCnt"].toInt(1))
|
, _borderSwitchCnt(50)
|
||||||
, _detectionMode(blackborderConfig["mode"].toString("default"))
|
, _maxInconsistentCnt(10)
|
||||||
, _detector(blackborderConfig["threshold"].toDouble(5.0)/100)
|
, _blurRemoveCnt(1)
|
||||||
|
, _detectionMode("default")
|
||||||
|
, _detector(nullptr)
|
||||||
, _currentBorder({true, -1, -1})
|
, _currentBorder({true, -1, -1})
|
||||||
, _previousDetectedBorder({true, -1, -1})
|
, _previousDetectedBorder({true, -1, -1})
|
||||||
, _consistentCnt(0)
|
, _consistentCnt(0)
|
||||||
, _inconsistentCnt(10)
|
, _inconsistentCnt(10)
|
||||||
|
, _oldThreshold(-0.1)
|
||||||
|
, _hardDisabled(false)
|
||||||
|
, _userEnabled(false)
|
||||||
{
|
{
|
||||||
if (_enabled)
|
// init
|
||||||
|
handleSettingsUpdate(settings::BLACKBORDER, _hyperion->getSetting(settings::BLACKBORDER));
|
||||||
|
|
||||||
|
// listen for settings updates
|
||||||
|
connect(_hyperion, &Hyperion::settingsChanged, this, &BlackBorderProcessor::handleSettingsUpdate);
|
||||||
|
|
||||||
|
// listen for component state changes
|
||||||
|
connect(_hyperion, &Hyperion::componentStateChanged, this, &BlackBorderProcessor::componentStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlackBorderProcessor::~BlackBorderProcessor()
|
||||||
{
|
{
|
||||||
Debug(Logger::getInstance("BLACKBORDER"), "mode: %s", QSTRING_CSTR(_detectionMode));
|
delete _detector;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlackBorderProcessor::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
||||||
|
{
|
||||||
|
if(type == settings::BLACKBORDER)
|
||||||
|
{
|
||||||
|
const QJsonObject& obj = config.object();
|
||||||
|
_unknownSwitchCnt = obj["unknownFrameCnt"].toInt(600);
|
||||||
|
_borderSwitchCnt = obj["borderFrameCnt"].toInt(50);
|
||||||
|
_maxInconsistentCnt = obj["maxInconsistentCnt"].toInt(10);
|
||||||
|
_blurRemoveCnt = obj["blurRemoveCnt"].toInt(1);
|
||||||
|
_detectionMode = obj["mode"].toString("default");
|
||||||
|
|
||||||
|
if(_oldThreshold != obj["threshold"].toDouble(5.0/100))
|
||||||
|
{
|
||||||
|
_oldThreshold = obj["threshold"].toDouble(5.0/100);
|
||||||
|
if(_detector != nullptr) delete _detector;
|
||||||
|
_detector = new BlackBorderDetector(obj["threshold"].toDouble(5.0/100));
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug(Logger::getInstance("BLACKBORDER"), "Set mode to: %s", QSTRING_CSTR(_detectionMode));
|
||||||
|
|
||||||
|
// eval the comp state
|
||||||
|
componentStateChanged(hyperion::COMP_BLACKBORDER, obj["enable"].toBool(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlackBorderProcessor::componentStateChanged(const hyperion::Components component, bool enable)
|
||||||
|
{
|
||||||
|
if(component == hyperion::COMP_BLACKBORDER)
|
||||||
|
{
|
||||||
|
_userEnabled = enable;
|
||||||
|
if(enable)
|
||||||
|
{
|
||||||
|
// eg effects and probably other components don't want a BB, mimik a wrong comp state to the comp register
|
||||||
|
if(!_hardDisabled)
|
||||||
|
_enabled = enable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_enabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
_hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_BLACKBORDER, enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlackBorderProcessor::setHardDisable(const bool& disable) {
|
||||||
|
|
||||||
|
if (disable)
|
||||||
|
{
|
||||||
|
_enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the user has the last word to enable
|
||||||
|
if(_userEnabled)
|
||||||
|
_enabled = true;
|
||||||
|
}
|
||||||
|
_hardDisabled = disable;
|
||||||
|
};
|
||||||
|
|
||||||
BlackBorder BlackBorderProcessor::getCurrentBorder() const
|
BlackBorder BlackBorderProcessor::getCurrentBorder() const
|
||||||
{
|
{
|
||||||
return _currentBorder;
|
return _currentBorder;
|
||||||
|
@ -7,4 +7,7 @@ FILE ( GLOB Blackborder_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_D
|
|||||||
|
|
||||||
add_library(blackborder ${Blackborder_SOURCES} )
|
add_library(blackborder ${Blackborder_SOURCES} )
|
||||||
|
|
||||||
target_link_libraries(blackborder hyperion-utils )
|
target_link_libraries(blackborder
|
||||||
|
hyperion-utils
|
||||||
|
hyperion
|
||||||
|
)
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
|
|
||||||
// hyperion util includes
|
// hyperion util includes
|
||||||
#include "hyperion/ImageProcessorFactory.h"
|
//#include "hyperion/ImageProcessorFactory.h"
|
||||||
#include "hyperion/ImageProcessor.h"
|
//#include "hyperion/ImageProcessor.h"
|
||||||
#include "utils/ColorRgb.h"
|
#include "utils/ColorRgb.h"
|
||||||
#include "HyperionConfig.h"
|
#include "HyperionConfig.h"
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ BoblightClientConnection::BoblightClientConnection(QTcpSocket *socket, const int
|
|||||||
: QObject()
|
: QObject()
|
||||||
, _locale(QLocale::C)
|
, _locale(QLocale::C)
|
||||||
, _socket(socket)
|
, _socket(socket)
|
||||||
, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
|
//, _imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor())
|
||||||
, _hyperion(Hyperion::getInstance())
|
, _hyperion(Hyperion::getInstance())
|
||||||
, _receiveBuffer()
|
, _receiveBuffer()
|
||||||
, _priority(priority)
|
, _priority(priority)
|
||||||
@ -167,7 +167,7 @@ void BoblightClientConnection::handleMessage(const QString & message)
|
|||||||
// send current color values to hyperion if this is the last led assuming leds values are send in order of id
|
// send current color values to hyperion if this is the last led assuming leds values are send in order of id
|
||||||
if ((ledIndex == _ledColors.size() -1) && _priority < 255)
|
if ((ledIndex == _ledColors.size() -1) && _priority < 255)
|
||||||
{
|
{
|
||||||
_hyperion->setColors(_priority, _ledColors, -1, true, hyperion::COMP_BOBLIGHTSERVER, _clientAddress);
|
_hyperion->setInput(_priority, _ledColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -205,7 +205,7 @@ void BoblightClientConnection::handleMessage(const QString & message)
|
|||||||
// send current color values to hyperion
|
// send current color values to hyperion
|
||||||
if (_priority < 255)
|
if (_priority < 255)
|
||||||
{
|
{
|
||||||
_hyperion->setColors(_priority, _ledColors, -1, true, hyperion::COMP_BOBLIGHTSERVER, _clientAddress);
|
_hyperion->setInput(_priority, _ledColors);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -227,11 +227,11 @@ void BoblightClientConnection::sendLightMessage()
|
|||||||
int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount());
|
int n = snprintf(buffer, sizeof(buffer), "lights %d\n", _hyperion->getLedCount());
|
||||||
sendMessage(QByteArray(buffer, n));
|
sendMessage(QByteArray(buffer, n));
|
||||||
|
|
||||||
double h0, h1, v0, v1;
|
//double h0, h1, v0, v1;
|
||||||
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
|
for (unsigned i = 0; i < _hyperion->getLedCount(); ++i)
|
||||||
{
|
{
|
||||||
_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
|
//_imageProcessor->getScanParameters(i, h0, h1, v0, v1);
|
||||||
n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
|
//n = snprintf(buffer, sizeof(buffer), "light %03d scan %f %f %f %f\n", i, 100*v0, 100*v1, 100*h0, 100*h1);
|
||||||
sendMessage(QByteArray(buffer, n));
|
//sendMessage(QByteArray(buffer, n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#include <hyperion/Hyperion.h>
|
#include <hyperion/Hyperion.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
class ImageProcessor;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The Connection object created by \a BoblightServer when a new connection is establshed
|
/// The Connection object created by \a BoblightServer when a new connection is establshed
|
||||||
///
|
///
|
||||||
@ -76,9 +74,6 @@ private:
|
|||||||
/// The TCP-Socket that is connected tot the boblight-client
|
/// The TCP-Socket that is connected tot the boblight-client
|
||||||
QTcpSocket * _socket;
|
QTcpSocket * _socket;
|
||||||
|
|
||||||
/// The processor for translating images to led-values
|
|
||||||
ImageProcessor * _imageProcessor;
|
|
||||||
|
|
||||||
/// Link to Hyperion for writing led-values to a priority channel
|
/// Link to Hyperion for writing led-values to a priority channel
|
||||||
Hyperion * _hyperion;
|
Hyperion * _hyperion;
|
||||||
|
|
||||||
|
@ -5,20 +5,31 @@
|
|||||||
#include <boblightserver/BoblightServer.h>
|
#include <boblightserver/BoblightServer.h>
|
||||||
#include "BoblightClientConnection.h"
|
#include "BoblightClientConnection.h"
|
||||||
|
|
||||||
|
// hyperion includes
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
// qt incl
|
||||||
|
#include <QTcpServer>
|
||||||
|
|
||||||
using namespace hyperion;
|
using namespace hyperion;
|
||||||
|
|
||||||
BoblightServer::BoblightServer(const int priority, uint16_t port)
|
BoblightServer::BoblightServer(const QJsonDocument& config)
|
||||||
: QObject()
|
: QObject()
|
||||||
, _hyperion(Hyperion::getInstance())
|
, _hyperion(Hyperion::getInstance())
|
||||||
, _server()
|
, _server(new QTcpServer(this))
|
||||||
, _openConnections()
|
, _openConnections()
|
||||||
, _priority(priority)
|
, _priority(0)
|
||||||
, _log(Logger::getInstance("BOBLIGHT"))
|
, _log(Logger::getInstance("BOBLIGHT"))
|
||||||
, _isActive(false)
|
, _port(0)
|
||||||
, _port(port)
|
|
||||||
{
|
{
|
||||||
// Set trigger for incoming connections
|
Debug(_log, "Instance created");
|
||||||
connect(&_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
|
||||||
|
// listen for component change
|
||||||
|
connect(_hyperion, SIGNAL(componentStateChanged(hyperion::Components,bool)), this, SLOT(componentStateChanged(hyperion::Components,bool)));
|
||||||
|
// listen new connection signal from server
|
||||||
|
connect(_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
||||||
|
|
||||||
|
// init
|
||||||
|
handleSettingsUpdate(settings::BOBLSERVER, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoblightServer::~BoblightServer()
|
BoblightServer::~BoblightServer()
|
||||||
@ -28,63 +39,63 @@ BoblightServer::~BoblightServer()
|
|||||||
|
|
||||||
void BoblightServer::start()
|
void BoblightServer::start()
|
||||||
{
|
{
|
||||||
if ( active() )
|
if ( _server->isListening() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_server.listen(QHostAddress::Any, _port))
|
if (!_server->listen(QHostAddress::Any, _port))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("BOBLIGHT ERROR: server could not bind to port");
|
Error(_log, "Could not bind to port '%d', please use an available port", _port);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Info(_log, "Boblight server started on port %d", _port);
|
Info(_log, "Started on port %d", _port);
|
||||||
|
|
||||||
_isActive = true;
|
_hyperion->getComponentRegister().componentStateChanged(COMP_BOBLIGHTSERVER, _server->isListening());
|
||||||
emit statusChanged(_isActive);
|
|
||||||
|
|
||||||
_hyperion->registerPriority("Boblight", _priority);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoblightServer::stop()
|
void BoblightServer::stop()
|
||||||
{
|
{
|
||||||
if ( ! active() )
|
if ( ! _server->isListening() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (BoblightClientConnection * connection, _openConnections) {
|
foreach (BoblightClientConnection * connection, _openConnections) {
|
||||||
delete connection;
|
delete connection;
|
||||||
}
|
}
|
||||||
_server.close();
|
_server->close();
|
||||||
_isActive = false;
|
|
||||||
emit statusChanged(_isActive);
|
|
||||||
|
|
||||||
_hyperion->unRegisterPriority("Boblight");
|
Info(_log, "Stopped");
|
||||||
|
_hyperion->getComponentRegister().componentStateChanged(COMP_BOBLIGHTSERVER, _server->isListening());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoblightServer::active()
|
||||||
|
{
|
||||||
|
return _server->isListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoblightServer::componentStateChanged(const hyperion::Components component, bool enable)
|
void BoblightServer::componentStateChanged(const hyperion::Components component, bool enable)
|
||||||
{
|
{
|
||||||
if (component == COMP_BOBLIGHTSERVER)
|
if (component == COMP_BOBLIGHTSERVER)
|
||||||
{
|
{
|
||||||
if (_isActive != enable)
|
if (_server->isListening() != enable)
|
||||||
{
|
{
|
||||||
if (enable) start();
|
if (enable) start();
|
||||||
else stop();
|
else stop();
|
||||||
Info(_log, "change state to %s", (_isActive ? "enabled" : "disabled") );
|
|
||||||
}
|
}
|
||||||
_hyperion->getComponentRegister().componentStateChanged(component, _isActive);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t BoblightServer::getPort() const
|
uint16_t BoblightServer::getPort() const
|
||||||
{
|
{
|
||||||
return _server.serverPort();
|
return _server->serverPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoblightServer::newConnection()
|
void BoblightServer::newConnection()
|
||||||
{
|
{
|
||||||
QTcpSocket * socket = _server.nextPendingConnection();
|
QTcpSocket * socket = _server->nextPendingConnection();
|
||||||
|
|
||||||
if (socket != nullptr)
|
if (socket != nullptr)
|
||||||
{
|
{
|
||||||
Info(_log, "new connection");
|
Info(_log, "new connection");
|
||||||
|
_hyperion->registerInput(_priority, hyperion::COMP_BOBLIGHTSERVER, QString("Boblight@%1").arg(socket->peerAddress().toString()));
|
||||||
BoblightClientConnection * connection = new BoblightClientConnection(socket, _priority);
|
BoblightClientConnection * connection = new BoblightClientConnection(socket, _priority);
|
||||||
_openConnections.insert(connection);
|
_openConnections.insert(connection);
|
||||||
|
|
||||||
@ -101,3 +112,16 @@ void BoblightServer::closedConnection(BoblightClientConnection *connection)
|
|||||||
// schedule to delete the connection object
|
// schedule to delete the connection object
|
||||||
connection->deleteLater();
|
connection->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BoblightServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
||||||
|
{
|
||||||
|
if(type == settings::BOBLSERVER)
|
||||||
|
{
|
||||||
|
QJsonObject obj = config.object();
|
||||||
|
_port = obj["port"].toInt();
|
||||||
|
_priority = obj["priority"].toInt();
|
||||||
|
stop();
|
||||||
|
if(obj["enable"].toBool())
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
81
libsrc/bonjour/bonjourbrowserwrapper.cpp
Normal file
81
libsrc/bonjour/bonjourbrowserwrapper.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include <bonjour/bonjourbrowserwrapper.h>
|
||||||
|
|
||||||
|
//qt incl
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
// bonjour
|
||||||
|
#include <bonjour/bonjourservicebrowser.h>
|
||||||
|
#include <bonjour/bonjourserviceresolver.h>
|
||||||
|
|
||||||
|
BonjourBrowserWrapper* BonjourBrowserWrapper::instance = nullptr;
|
||||||
|
|
||||||
|
BonjourBrowserWrapper::BonjourBrowserWrapper(QObject * parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, _bonjourResolver(new BonjourServiceResolver(this))
|
||||||
|
, _timerBonjourResolver( new QTimer(this))
|
||||||
|
{
|
||||||
|
BonjourBrowserWrapper::instance = this;
|
||||||
|
connect(_bonjourResolver, &BonjourServiceResolver::bonjourRecordResolved, this, &BonjourBrowserWrapper::bonjourRecordResolved);
|
||||||
|
|
||||||
|
connect(_timerBonjourResolver, &QTimer::timeout, this, &BonjourBrowserWrapper::bonjourResolve);
|
||||||
|
_timerBonjourResolver->setInterval(1000);
|
||||||
|
_timerBonjourResolver->start();
|
||||||
|
|
||||||
|
// browse for _hyperiond-http._tcp
|
||||||
|
browseForServiceType(QLatin1String("_hyperiond-http._tcp"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BonjourBrowserWrapper::browseForServiceType(const QString &serviceType)
|
||||||
|
{
|
||||||
|
if(!_browsedServices.contains(serviceType))
|
||||||
|
{
|
||||||
|
BonjourServiceBrowser* newBrowser = new BonjourServiceBrowser(this);
|
||||||
|
connect(newBrowser, &BonjourServiceBrowser::currentBonjourRecordsChanged, this, &BonjourBrowserWrapper::currentBonjourRecordsChanged);
|
||||||
|
newBrowser->browseForServiceType(serviceType);
|
||||||
|
_browsedServices.insert(serviceType, newBrowser);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BonjourBrowserWrapper::currentBonjourRecordsChanged(const QList<BonjourRecord> &list)
|
||||||
|
{
|
||||||
|
_hyperionSessions.clear();
|
||||||
|
for ( auto rec : list )
|
||||||
|
{
|
||||||
|
_hyperionSessions.insert(rec.serviceName, rec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BonjourBrowserWrapper::bonjourRecordResolved(const QHostInfo &hostInfo, int port)
|
||||||
|
{
|
||||||
|
if ( _hyperionSessions.contains(_bonjourCurrentServiceToResolve))
|
||||||
|
{
|
||||||
|
QString host = hostInfo.hostName();
|
||||||
|
QString domain = _hyperionSessions[_bonjourCurrentServiceToResolve].replyDomain;
|
||||||
|
if (host.endsWith("."+domain))
|
||||||
|
{
|
||||||
|
host.remove(host.length()-domain.length()-1,domain.length()+1);
|
||||||
|
}
|
||||||
|
_hyperionSessions[_bonjourCurrentServiceToResolve].hostName = host;
|
||||||
|
_hyperionSessions[_bonjourCurrentServiceToResolve].port = port;
|
||||||
|
_hyperionSessions[_bonjourCurrentServiceToResolve].address = hostInfo.addresses().isEmpty() ? "" : hostInfo.addresses().first().toString();
|
||||||
|
//Debug(_log, "found hyperion session: %s:%d",QSTRING_CSTR(hostInfo.hostName()), port);
|
||||||
|
|
||||||
|
//emit change
|
||||||
|
emit browserChange(_hyperionSessions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BonjourBrowserWrapper::bonjourResolve()
|
||||||
|
{
|
||||||
|
for(auto key : _hyperionSessions.keys())
|
||||||
|
{
|
||||||
|
if (_hyperionSessions[key].port < 0)
|
||||||
|
{
|
||||||
|
_bonjourCurrentServiceToResolve = key;
|
||||||
|
_bonjourResolver->resolveBonjourRecord(_hyperionSessions[key]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,8 +30,12 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <QtCore/QSocketNotifier>
|
#include <QtCore/QSocketNotifier>
|
||||||
|
#include <QHostInfo>
|
||||||
|
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
#include <HyperionConfig.h>
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
|
||||||
|
|
||||||
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
|
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
|
||||||
: QObject(parent), dnssref(0), bonjourSocket(0)
|
: QObject(parent), dnssref(0), bonjourSocket(0)
|
||||||
@ -48,6 +52,19 @@ BonjourServiceRegister::~BonjourServiceRegister()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BonjourServiceRegister::registerService(const QString& service, const int& port)
|
||||||
|
{
|
||||||
|
// zeroconf $configname@$hostname:port
|
||||||
|
QString prettyName = Hyperion::getInstance()->getQJsonConfig()["general"].toObject()["name"].toString();
|
||||||
|
registerService(
|
||||||
|
BonjourRecord(prettyName+"@"+QHostInfo::localHostName()+ ":" + QString::number(port),
|
||||||
|
service,
|
||||||
|
QString()
|
||||||
|
),
|
||||||
|
port
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void BonjourServiceRegister::registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt)
|
void BonjourServiceRegister::registerService(const BonjourRecord &record, quint16 servicePort, std::vector<std::pair<std::string, std::string>> txt)
|
||||||
{
|
{
|
||||||
if (dnssref)
|
if (dnssref)
|
||||||
@ -61,21 +78,24 @@ void BonjourServiceRegister::registerService(const BonjourRecord &record, quint1
|
|||||||
bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8);
|
bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// base txtRec
|
||||||
|
std::vector<std::pair<std::string, std::string> > txtBase = {{"id",Hyperion::getInstance()->getId().toStdString()},{"version",HYPERION_VERSION}};
|
||||||
// create txt record
|
// create txt record
|
||||||
TXTRecordRef txtRec;
|
TXTRecordRef txtRec;
|
||||||
TXTRecordCreate(&txtRec,0,NULL);
|
TXTRecordCreate(&txtRec,0,NULL);
|
||||||
|
|
||||||
// add txt records
|
|
||||||
if(!txt.empty())
|
if(!txt.empty())
|
||||||
{
|
{
|
||||||
for(std::vector<std::pair<std::string, std::string> >::const_iterator it = txt.begin(); it != txt.end(); ++it)
|
txtBase.insert(txtBase.end(), txt.begin(), txt.end());
|
||||||
|
}
|
||||||
|
// add txt records
|
||||||
|
for(std::vector<std::pair<std::string, std::string> >::const_iterator it = txtBase.begin(); it != txtBase.end(); ++it)
|
||||||
{
|
{
|
||||||
//Debug(Logger::getInstance("BonJour"), "TXTRecord: key:%s, value:%s",it->first.c_str(),it->second.c_str());
|
//Debug(Logger::getInstance("BonJour"), "TXTRecord: key:%s, value:%s",it->first.c_str(),it->second.c_str());
|
||||||
uint8_t txtLen = (uint8_t)strlen(it->second.c_str());
|
uint8_t txtLen = (uint8_t)strlen(it->second.c_str());
|
||||||
TXTRecordSetValue(&txtRec, it->first.c_str(), txtLen, it->second.c_str());
|
TXTRecordSetValue(&txtRec, it->first.c_str(), txtLen, it->second.c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DNSServiceErrorType err = DNSServiceRegister(&dnssref, 0, 0, record.serviceName.toUtf8().constData(),
|
DNSServiceErrorType err = DNSServiceRegister(&dnssref, 0, 0, record.serviceName.toUtf8().constData(),
|
||||||
record.registeredType.toUtf8().constData(),
|
record.registeredType.toUtf8().constData(),
|
||||||
|
@ -27,6 +27,7 @@ add_library(effectengine
|
|||||||
|
|
||||||
target_link_libraries(effectengine
|
target_link_libraries(effectengine
|
||||||
hyperion
|
hyperion
|
||||||
|
python
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Gui
|
Qt5::Gui
|
||||||
${PYTHON_LIBRARIES}
|
${PYTHON_LIBRARIES}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
// effect engine includes
|
// effect engine includes
|
||||||
#include <effectengine/EffectEngine.h>
|
#include <effectengine/EffectEngine.h>
|
||||||
#include "Effect.h"
|
#include <effectengine/Effect.h>
|
||||||
|
#include <effectengine/EffectModule.h>
|
||||||
#include "HyperionConfig.h"
|
#include "HyperionConfig.h"
|
||||||
|
|
||||||
EffectEngine::EffectEngine(Hyperion * hyperion, const QJsonObject & jsonEffectConfig)
|
EffectEngine::EffectEngine(Hyperion * hyperion, const QJsonObject & jsonEffectConfig)
|
||||||
@ -25,11 +26,11 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const QJsonObject & jsonEffectCo
|
|||||||
, _availableEffects()
|
, _availableEffects()
|
||||||
, _activeEffects()
|
, _activeEffects()
|
||||||
, _log(Logger::getInstance("EFFECTENGINE"))
|
, _log(Logger::getInstance("EFFECTENGINE"))
|
||||||
, _mainThreadState(nullptr)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
Q_INIT_RESOURCE(EffectEngine);
|
Q_INIT_RESOURCE(EffectEngine);
|
||||||
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
|
qRegisterMetaType<std::vector<ColorRgb>>("std::vector<ColorRgb>");
|
||||||
|
qRegisterMetaType<Image<ColorRgb>>("Image<ColorRgb>");
|
||||||
qRegisterMetaType<hyperion::Components>("hyperion::Components");
|
qRegisterMetaType<hyperion::Components>("hyperion::Components");
|
||||||
|
|
||||||
// connect the Hyperion channel clear feedback
|
// connect the Hyperion channel clear feedback
|
||||||
@ -38,21 +39,10 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const QJsonObject & jsonEffectCo
|
|||||||
|
|
||||||
// read all effects
|
// read all effects
|
||||||
readEffects();
|
readEffects();
|
||||||
|
|
||||||
// initialize the python interpreter
|
|
||||||
Debug(_log, "Initializing Python interpreter");
|
|
||||||
Effect::registerHyperionExtensionModule();
|
|
||||||
Py_InitializeEx(0);
|
|
||||||
PyEval_InitThreads(); // Create the GIL
|
|
||||||
_mainThreadState = PyEval_SaveThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectEngine::~EffectEngine()
|
EffectEngine::~EffectEngine()
|
||||||
{
|
{
|
||||||
// clean up the Python interpreter
|
|
||||||
Debug(_log, "Cleaning up Python interpreter");
|
|
||||||
PyEval_RestoreThread(_mainThreadState);
|
|
||||||
Py_Finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
||||||
@ -73,6 +63,33 @@ const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
|||||||
return _availableActiveEffects;
|
return _availableActiveEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EffectEngine::cacheRunningEffects()
|
||||||
|
{
|
||||||
|
_cachedActiveEffects.clear();
|
||||||
|
|
||||||
|
for (Effect * effect : _activeEffects)
|
||||||
|
{
|
||||||
|
ActiveEffectDefinition activeEffectDefinition;
|
||||||
|
activeEffectDefinition.script = effect->getScript();
|
||||||
|
activeEffectDefinition.name = effect->getName();
|
||||||
|
activeEffectDefinition.priority = effect->getPriority();
|
||||||
|
activeEffectDefinition.timeout = effect->getTimeout();
|
||||||
|
activeEffectDefinition.args = effect->getArgs();
|
||||||
|
_cachedActiveEffects.push_back(activeEffectDefinition);
|
||||||
|
channelCleared(effect->getPriority());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectEngine::startCachedEffects()
|
||||||
|
{
|
||||||
|
for (const auto & def : _cachedActiveEffects)
|
||||||
|
{
|
||||||
|
// the smooth cfg AND origin are ignored for this start!
|
||||||
|
runEffect(def.name, def.args, def.priority, def.timeout, def.script);
|
||||||
|
}
|
||||||
|
_cachedActiveEffects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition)
|
bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition)
|
||||||
{
|
{
|
||||||
QString fileName = path + QDir::separator() + effectConfigFile;
|
QString fileName = path + QDir::separator() + effectConfigFile;
|
||||||
@ -241,6 +258,8 @@ void EffectEngine::readEffects()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ErrorIf(_availableEffects.size()==0, _log, "no effects found, check your effect directories");
|
ErrorIf(_availableEffects.size()==0, _log, "no effects found, check your effect directories");
|
||||||
|
|
||||||
|
emit effectListUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
int EffectEngine::runEffect(const QString &effectName, int priority, int timeout, const QString &origin)
|
int EffectEngine::runEffect(const QString &effectName, int priority, int timeout, const QString &origin)
|
||||||
@ -266,7 +285,7 @@ int EffectEngine::runEffect(const QString &effectName, const QJsonObject &args,
|
|||||||
if (effectDefinition == nullptr)
|
if (effectDefinition == nullptr)
|
||||||
{
|
{
|
||||||
// no such effect
|
// no such effect
|
||||||
Error(_log, "effect %s not found", QSTRING_CSTR(effectName));
|
Error(_log, "Effect %s not found", QSTRING_CSTR(effectName));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,13 +300,14 @@ int EffectEngine::runEffectScript(const QString &script, const QString &name, co
|
|||||||
channelCleared(priority);
|
channelCleared(priority);
|
||||||
|
|
||||||
// create the effect
|
// create the effect
|
||||||
Effect * effect = new Effect(_mainThreadState, priority, timeout, script, name, args, origin, smoothCfg);
|
Effect * effect = new Effect(_hyperion, priority, timeout, script, name, args);
|
||||||
connect(effect, SIGNAL(setColors(int,std::vector<ColorRgb>,int,bool,hyperion::Components,const QString,unsigned)), _hyperion, SLOT(setColors(int,std::vector<ColorRgb>,int,bool,hyperion::Components,const QString,unsigned)), Qt::QueuedConnection);
|
connect(effect, &Effect::setInput, _hyperion, &Hyperion::setInput, Qt::QueuedConnection);
|
||||||
|
connect(effect, &Effect::setInputImage, _hyperion, &Hyperion::setInputImage, Qt::QueuedConnection);
|
||||||
connect(effect, &QThread::finished, this, &EffectEngine::effectFinished);
|
connect(effect, &QThread::finished, this, &EffectEngine::effectFinished);
|
||||||
_activeEffects.push_back(effect);
|
_activeEffects.push_back(effect);
|
||||||
|
|
||||||
// start the effect
|
// start the effect
|
||||||
_hyperion->registerPriority(name, priority);
|
_hyperion->registerInput(priority, hyperion::COMP_EFFECT, origin, name ,smoothCfg);
|
||||||
effect->start();
|
effect->start();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -299,7 +319,7 @@ void EffectEngine::channelCleared(int priority)
|
|||||||
{
|
{
|
||||||
if (effect->getPriority() == priority)
|
if (effect->getPriority() == priority)
|
||||||
{
|
{
|
||||||
effect->requestInterruption();
|
effect->setInteruptionFlag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,7 +330,7 @@ void EffectEngine::allChannelsCleared()
|
|||||||
{
|
{
|
||||||
if (effect->getPriority() != 254)
|
if (effect->getPriority() != 254)
|
||||||
{
|
{
|
||||||
effect->requestInterruption();
|
effect->setInteruptionFlag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,7 +338,7 @@ void EffectEngine::allChannelsCleared()
|
|||||||
void EffectEngine::effectFinished()
|
void EffectEngine::effectFinished()
|
||||||
{
|
{
|
||||||
Effect* effect = qobject_cast<Effect*>(sender());
|
Effect* effect = qobject_cast<Effect*>(sender());
|
||||||
if (!effect->isInterruptionRequested())
|
if (!effect->hasInteruptionFlag())
|
||||||
{
|
{
|
||||||
// effect stopped by itself. Clear the channel
|
// effect stopped by itself. Clear the channel
|
||||||
_hyperion->clear(effect->getPriority());
|
_hyperion->clear(effect->getPriority());
|
||||||
@ -336,5 +356,4 @@ void EffectEngine::effectFinished()
|
|||||||
|
|
||||||
// cleanup the effect
|
// cleanup the effect
|
||||||
effect->deleteLater();
|
effect->deleteLater();
|
||||||
_hyperion->unRegisterPriority(effect->getName());
|
|
||||||
}
|
}
|
||||||
|
1077
libsrc/effectengine/EffectModule.cpp
Normal file
1077
libsrc/effectengine/EffectModule.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
#include <grabber/AmlogicWrapper.h>
|
#include <grabber/AmlogicWrapper.h>
|
||||||
|
|
||||||
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
|
AmlogicWrapper::AmlogicWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz)
|
||||||
: GrabberWrapper("AmLogic", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
|
: GrabberWrapper("AmLogic", &_grabber, grabWidth, grabHeight, updateRate_Hz)
|
||||||
, _grabber(grabWidth, grabHeight)
|
, _grabber(grabWidth, grabHeight)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "grabber/DispmanxFrameGrabber.h"
|
#include "grabber/DispmanxFrameGrabber.h"
|
||||||
|
|
||||||
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height)
|
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height)
|
||||||
: Grabber("DISPMANXGRABBER", width, height)
|
: Grabber("DISPMANXGRABBER", 0, 0)
|
||||||
, _vc_display(0)
|
, _vc_display(0)
|
||||||
, _vc_resource(0)
|
, _vc_resource(0)
|
||||||
, _vc_flags(0)
|
, _vc_flags(0)
|
||||||
@ -20,7 +20,6 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
|
|||||||
// Initiase BCM
|
// Initiase BCM
|
||||||
bcm_host_init();
|
bcm_host_init();
|
||||||
|
|
||||||
{
|
|
||||||
// Check if the display can be opened and display the current resolution
|
// Check if the display can be opened and display the current resolution
|
||||||
// Open the connection to the display
|
// Open the connection to the display
|
||||||
_vc_display = vc_dispmanx_display_open(0);
|
_vc_display = vc_dispmanx_display_open(0);
|
||||||
@ -36,8 +35,31 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
|
|||||||
|
|
||||||
// Close the displaye
|
// Close the displaye
|
||||||
vc_dispmanx_display_close(_vc_display);
|
vc_dispmanx_display_close(_vc_display);
|
||||||
|
|
||||||
|
// init the resource and capture rectangle
|
||||||
|
setWidthHeight(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DispmanxFrameGrabber::~DispmanxFrameGrabber()
|
||||||
|
{
|
||||||
|
freeResources();
|
||||||
|
|
||||||
|
// De-init BCM
|
||||||
|
bcm_host_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DispmanxFrameGrabber::freeResources()
|
||||||
|
{
|
||||||
|
delete[] _captureBuffer;
|
||||||
|
// Clean up resources
|
||||||
|
vc_dispmanx_resource_delete(_vc_resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DispmanxFrameGrabber::setWidthHeight(int width, int height)
|
||||||
|
{
|
||||||
|
if(_width != width || _height != height)
|
||||||
|
{
|
||||||
|
freeResources();
|
||||||
// Create the resources for capturing image
|
// Create the resources for capturing image
|
||||||
uint32_t vc_nativeImageHandle;
|
uint32_t vc_nativeImageHandle;
|
||||||
_vc_resource = vc_dispmanx_resource_create(
|
_vc_resource = vc_dispmanx_resource_create(
|
||||||
@ -50,16 +72,6 @@ DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned
|
|||||||
// Define the capture rectangle with the same size
|
// Define the capture rectangle with the same size
|
||||||
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
|
vc_dispmanx_rect_set(&_rectangle, 0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
DispmanxFrameGrabber::~DispmanxFrameGrabber()
|
|
||||||
{
|
|
||||||
delete[] _captureBuffer;
|
|
||||||
|
|
||||||
// Clean up resources
|
|
||||||
vc_dispmanx_resource_delete(_vc_resource);
|
|
||||||
|
|
||||||
// De-init BCM
|
|
||||||
bcm_host_deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispmanxFrameGrabber::setFlags(const int vc_flags)
|
void DispmanxFrameGrabber::setFlags(const int vc_flags)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <grabber/DispmanxWrapper.h>
|
#include <grabber/DispmanxWrapper.h>
|
||||||
|
|
||||||
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
|
DispmanxWrapper::DispmanxWrapper(const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz)
|
||||||
: GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
|
: GrabberWrapper("Dispmanx", &_grabber, grabWidth, grabHeight, updateRate_Hz)
|
||||||
, _grabber(grabWidth, grabHeight)
|
, _grabber(grabWidth, grabHeight)
|
||||||
{
|
{
|
||||||
setImageProcessorEnabled(false);
|
setImageProcessorEnabled(false);
|
||||||
|
@ -16,31 +16,9 @@ FramebufferFrameGrabber::FramebufferFrameGrabber(const QString & device, const u
|
|||||||
: Grabber("FRAMEBUFFERGRABBER", width, height)
|
: Grabber("FRAMEBUFFERGRABBER", width, height)
|
||||||
, _fbfd(0)
|
, _fbfd(0)
|
||||||
, _fbp(0)
|
, _fbp(0)
|
||||||
, _fbDevice(device)
|
, _fbDevice()
|
||||||
{
|
{
|
||||||
int result;
|
setDevicePath(device);
|
||||||
struct fb_var_screeninfo vinfo;
|
|
||||||
|
|
||||||
// Check if the framebuffer device can be opened and display the current resolution
|
|
||||||
_fbfd = open(QSTRING_CSTR(_fbDevice), O_RDONLY);
|
|
||||||
if (_fbfd == 0)
|
|
||||||
{
|
|
||||||
Error(_log, "Error openning %s", QSTRING_CSTR(_fbDevice));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// get variable screen information
|
|
||||||
result = ioctl (_fbfd, FBIOGET_VSCREENINFO, &vinfo);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
Error(_log, "Could not get screen information");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Info(_log, "Display opened with resolution: %dx%d@%dbit", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
|
|
||||||
}
|
|
||||||
close(_fbfd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferFrameGrabber::~FramebufferFrameGrabber()
|
FramebufferFrameGrabber::~FramebufferFrameGrabber()
|
||||||
@ -92,3 +70,35 @@ int FramebufferFrameGrabber::grabFrame(Image<ColorRgb> & image)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramebufferFrameGrabber::setDevicePath(const QString& path)
|
||||||
|
{
|
||||||
|
if(_fbDevice != path)
|
||||||
|
{
|
||||||
|
_fbDevice = path;
|
||||||
|
int result;
|
||||||
|
struct fb_var_screeninfo vinfo;
|
||||||
|
|
||||||
|
// Check if the framebuffer device can be opened and display the current resolution
|
||||||
|
_fbfd = open(QSTRING_CSTR(_fbDevice), O_RDONLY);
|
||||||
|
if (_fbfd == 0)
|
||||||
|
{
|
||||||
|
Error(_log, "Error openning %s", QSTRING_CSTR(_fbDevice));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get variable screen information
|
||||||
|
result = ioctl (_fbfd, FBIOGET_VSCREENINFO, &vinfo);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
Error(_log, "Could not get screen information");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info(_log, "Display opened with resolution: %dx%d@%dbit", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
|
||||||
|
}
|
||||||
|
close(_fbfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <grabber/FramebufferWrapper.h>
|
#include <grabber/FramebufferWrapper.h>
|
||||||
|
|
||||||
FramebufferWrapper::FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
|
FramebufferWrapper::FramebufferWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz)
|
||||||
: GrabberWrapper("FrameBuffer", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
|
: GrabberWrapper("FrameBuffer", &_grabber, grabWidth, grabHeight, updateRate_Hz)
|
||||||
, _grabber(device, grabWidth, grabHeight)
|
, _grabber(device, grabWidth, grabHeight)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -7,30 +7,10 @@
|
|||||||
|
|
||||||
OsxFrameGrabber::OsxFrameGrabber(const unsigned display, const unsigned width, const unsigned height)
|
OsxFrameGrabber::OsxFrameGrabber(const unsigned display, const unsigned width, const unsigned height)
|
||||||
: Grabber("OSXGRABBER", width, height)
|
: Grabber("OSXGRABBER", width, height)
|
||||||
, _screenIndex(display)
|
, _screenIndex(100)
|
||||||
{
|
{
|
||||||
CGImageRef image;
|
// check if display is available
|
||||||
CGDisplayCount displayCount;
|
setDisplayIndex(display);
|
||||||
CGDirectDisplayID displays[8];
|
|
||||||
|
|
||||||
// get list of displays
|
|
||||||
CGGetActiveDisplayList(8, displays, &displayCount);
|
|
||||||
if (_screenIndex + 1 > displayCount)
|
|
||||||
{
|
|
||||||
Error(_log, "Display with index %d is not available. Using main display", _screenIndex);
|
|
||||||
_display = kCGDirectMainDisplay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_display = displays[_screenIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
image = CGDisplayCreateImage(_display);
|
|
||||||
assert(image != NULL);
|
|
||||||
|
|
||||||
Info(_log, "Display opened with resolution: %dx%d@%dbit", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image));
|
|
||||||
|
|
||||||
CGImageRelease(image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OsxFrameGrabber::~OsxFrameGrabber()
|
OsxFrameGrabber::~OsxFrameGrabber()
|
||||||
@ -78,3 +58,34 @@ int OsxFrameGrabber::grabFrame(Image<ColorRgb> & image)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OsxFrameGrabber::setDisplayIndex(int index)
|
||||||
|
{
|
||||||
|
if(_screenIndex != index)
|
||||||
|
{
|
||||||
|
_screenIndex = index;
|
||||||
|
|
||||||
|
CGImageRef image;
|
||||||
|
CGDisplayCount displayCount;
|
||||||
|
CGDirectDisplayID displays[8];
|
||||||
|
|
||||||
|
// get list of displays
|
||||||
|
CGGetActiveDisplayList(8, displays, &displayCount);
|
||||||
|
if (_screenIndex + 1 > displayCount)
|
||||||
|
{
|
||||||
|
Error(_log, "Display with index %d is not available. Using main display", _screenIndex);
|
||||||
|
_display = kCGDirectMainDisplay;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_display = displays[_screenIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
image = CGDisplayCreateImage(_display);
|
||||||
|
assert(image != NULL);
|
||||||
|
|
||||||
|
Info(_log, "Display opened with resolution: %dx%d@%dbit", CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerPixel(image));
|
||||||
|
|
||||||
|
CGImageRelease(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <grabber/OsxWrapper.h>
|
#include <grabber/OsxWrapper.h>
|
||||||
|
|
||||||
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz, const int priority)
|
OsxWrapper::OsxWrapper(const unsigned display, const unsigned grabWidth, const unsigned grabHeight, const unsigned updateRate_Hz)
|
||||||
: GrabberWrapper("OSX FrameGrabber", &_grabber, grabWidth, grabHeight, updateRate_Hz, priority, hyperion::COMP_GRABBER)
|
: GrabberWrapper("OSX FrameGrabber", &_grabber, grabWidth, grabHeight, updateRate_Hz)
|
||||||
, _grabber(display, grabWidth, grabHeight)
|
, _grabber(display, grabWidth, grabHeight)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user