mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
V4L2 enhanced (#766)
* fix v4l2 standard * ignore v4l2 meta devices * added resolution, framerate and device dropdown list to WebUI (thx to @Lord-Grey & @b1rdhous3) * Fix for kernels prior to v4.16 * Device names added & WebUI adapted
This commit is contained in:
parent
b92af63cef
commit
10f11c2d89
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "Klasický",
|
||||
"edt_conf_enum_bbosd": "OSD",
|
||||
"edt_conf_enum_automatic": "",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "Obecné nastavení",
|
||||
"edt_conf_gen_name_title": "Název konfigurace",
|
||||
"edt_conf_gen_name_expl": "Uživatelské jméno, které se používá k detekci Hyperionu. (Užitečné s více než jednou instancí Hyperion)",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "Cesta k Zachycení/Graber usb.",
|
||||
"edt_conf_v4l2_standard_title": "Video standard",
|
||||
"edt_conf_v4l2_standard_expl": "Vyberte standard videa pro vaši oblast.",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "Velikost decimace",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "Faktor velikosti decimace",
|
||||
"edt_conf_v4l2_cropLeft_title": "Ořezat zleva",
|
||||
|
@ -470,7 +470,7 @@
|
||||
"edt_conf_enum_PAL": "PAL",
|
||||
"edt_conf_enum_NTSC": "NTSC",
|
||||
"edt_conf_enum_SECAM": "SECAM",
|
||||
"edt_conf_enum_NO_CHANGE": "Auto",
|
||||
"edt_conf_enum_NO_CHANGE": "Automatisch",
|
||||
"edt_conf_enum_logsilent": "Stille",
|
||||
"edt_conf_enum_logwarn": "Warnung",
|
||||
"edt_conf_enum_logverbose": "Ausführlich",
|
||||
@ -479,6 +479,7 @@
|
||||
"edt_conf_enum_bbclassic": "Klassisch",
|
||||
"edt_conf_enum_bbosd": "OSD",
|
||||
"edt_conf_enum_automatic": "Automatisch",
|
||||
"edt_conf_enum_custom": "Benutzerdefiniert",
|
||||
"edt_conf_gen_heading_title": "Allgemeine Einstellungen",
|
||||
"edt_conf_gen_name_title": "Name der Konfiguration",
|
||||
"edt_conf_gen_name_expl": "Der Name wird verwendet, um Hyperion besser zu identifizieren. (Hilfreich bei mehreren Instanzen)",
|
||||
@ -539,9 +540,13 @@
|
||||
"edt_conf_smooth_continuousOutput_expl": "Aktualisiere die LEDs, auch wenn das Bild sich nicht geändert hat.",
|
||||
"edt_conf_v4l2_heading_title": "USB Aufnahme",
|
||||
"edt_conf_v4l2_device_title": "Gerät",
|
||||
"edt_conf_v4l2_device_expl": "Der Pfad zum USB (v4l) Aufnahmegerät. Wähle 'auto' für automatische Erkennung. Beispiel: '/dev/video0'",
|
||||
"edt_conf_v4l2_device_expl": "Eine Liste von USB (v4l) Aufnahmegeräten. Wähle 'Automatisch' für automatische Erkennung. Benutzerdefiniert z.b.: '/dev/video0'",
|
||||
"edt_conf_v4l2_standard_title": "Videoformat",
|
||||
"edt_conf_v4l2_standard_expl": "Wähle das passende Videoformat deiner Region. Auf 'Auto' wird der gewählte Modus vom v4l interface beibehalten.",
|
||||
"edt_conf_v4l2_standard_expl": "Wähle das passende Videoformat deiner Region. Auf 'Automatisch' wird der gewählte Modus vom v4l interface beibehalten.",
|
||||
"edt_conf_v4l2_resolution_title": "Auflösung",
|
||||
"edt_conf_v4l2_resolution_expl": "Eine Liste von unterstützten Auflösungen des aktiven Gerätes. Auf 'Automatisch' wird der gewählte Modus vom v4l interface beibehalten.",
|
||||
"edt_conf_v4l2_framerate_title": "Bilder pro Sekunde",
|
||||
"edt_conf_v4l2_framerate_expl": "Die unterstützten Bilder pro Sekunde des aktiven Gerätes. Auf 'Automatisch' wird der gewählte Modus vom v4l interface beibehalten.",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "Bildverkleinerung Faktor",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "Der Faktor der Bildverkleinerung ausgehend von der ursprünglichen Größe, 1 bedeutet keine Änderung (originales Bild).",
|
||||
"edt_conf_v4l2_cropLeft_title": "Entferne links",
|
||||
@ -570,9 +575,9 @@
|
||||
"edt_conf_v4l2_sDHOffsetMax_expl": "Signal Erkennungs-Bereich horizontal maximum (0.0-1.0)",
|
||||
"edt_conf_instCapture_heading_title": "Instance Aufnahme",
|
||||
"edt_conf_instC_systemEnable_title": "Aktiviere Plattform Aufnahme",
|
||||
"edt_conf_instC_systemEnable_expl": "Aktiviert die Plattform Aufnahme für diese LED Hardware Instanz",
|
||||
"edt_conf_instC_systemEnable_expl": "Aktiviert die Plattform Aufnahme für diese LED Hardware Instanz.",
|
||||
"edt_conf_instC_v4lEnable_title": "Aktiviere USB Aufnahme",
|
||||
"edt_conf_instC_v4lEnable_expl": "Aktiviert die USB Aufnahme für diese LED Hardware Instanz",
|
||||
"edt_conf_instC_v4lEnable_expl": "Aktiviert die USB Aufnahme für diese LED Hardware Instanz.",
|
||||
"edt_conf_fg_heading_title": "Plattform Aufnahme",
|
||||
"edt_conf_fg_type_title": "Typ",
|
||||
"edt_conf_fg_type_expl": "Art der Plattform Aufnahme, standard ist 'auto'",
|
||||
|
@ -469,7 +469,7 @@
|
||||
"edt_conf_enum_PAL" : "PAL",
|
||||
"edt_conf_enum_NTSC" : "NTSC",
|
||||
"edt_conf_enum_SECAM" : "SECAM",
|
||||
"edt_conf_enum_NO_CHANGE" : "Auto",
|
||||
"edt_conf_enum_NO_CHANGE" : "Automatic",
|
||||
"edt_conf_enum_logsilent" : "Silent",
|
||||
"edt_conf_enum_logwarn" : "Warning",
|
||||
"edt_conf_enum_logverbose" : "Verbose",
|
||||
@ -478,6 +478,7 @@
|
||||
"edt_conf_enum_bbclassic" : "Classic",
|
||||
"edt_conf_enum_bbosd" : "OSD",
|
||||
"edt_conf_enum_automatic" : "Automatic",
|
||||
"edt_conf_enum_custom": "Custom",
|
||||
"edt_conf_gen_heading_title" : "General Settings",
|
||||
"edt_conf_gen_name_title" : "Configuration name",
|
||||
"edt_conf_gen_name_expl" : "A user defined name which is used to identify Hyperion. (Helpful if you have more than one Hyperion instance)",
|
||||
@ -538,9 +539,13 @@
|
||||
"edt_conf_smooth_continuousOutput_expl" : "Update the leds even if there is no change in the picture.",
|
||||
"edt_conf_v4l2_heading_title" : "USB Capture",
|
||||
"edt_conf_v4l2_device_title" : "Device",
|
||||
"edt_conf_v4l2_device_expl" : "The path to the USB capture interface. Set to 'auto' for automatic detection. Example: '/dev/video0'",
|
||||
"edt_conf_v4l2_device_expl" : "The path to the USB capture interface. Set to 'Automatic' for automatic detection. Example: '/dev/video0'",
|
||||
"edt_conf_v4l2_standard_title" : "Video standard",
|
||||
"edt_conf_v4l2_standard_expl" : "Select the video standard for your region. 'Auto' keeps the value chosen by the v4l2 interface",
|
||||
"edt_conf_v4l2_standard_expl" : "Select the video standard for your region. 'Automatic' keeps the value chosen by the v4l2 interface",
|
||||
"edt_conf_v4l2_resolution_title" : "Device Resolution",
|
||||
"edt_conf_v4l2_resolution_expl" : "A list of supported resolutions of the active device",
|
||||
"edt_conf_v4l2_framerate_title": "Frames per second",
|
||||
"edt_conf_v4l2_framerate_expl": "The supported frames per second of the active device",
|
||||
"edt_conf_v4l2_sizeDecimation_title" : "Size decimation",
|
||||
"edt_conf_v4l2_sizeDecimation_expl" : "The factor of size decimation. 1 means no decimation (keep original size)",
|
||||
"edt_conf_v4l2_cropLeft_title" : "Crop left",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "Clásico",
|
||||
"edt_conf_enum_bbosd": "OSD",
|
||||
"edt_conf_enum_automatic": "Automático",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "Configuración General",
|
||||
"edt_conf_gen_name_title": "Nombre de configuración",
|
||||
"edt_conf_gen_name_expl": "Un nombre definido por el usuario que se utiliza para detectar Hyperion. (Útil con más de una instancia de Hyperion)",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "La ruta a la captura USB.",
|
||||
"edt_conf_v4l2_standard_title": "Estándar de vídeo",
|
||||
"edt_conf_v4l2_standard_expl": "Selecciona el estándar de vídeo para tu región.",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "Diezmación de tamaño",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "El factor de diezmación del tamaño",
|
||||
"edt_conf_v4l2_cropLeft_title": "Cortar izquierda",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "Classico",
|
||||
"edt_conf_enum_bbosd": "OSD",
|
||||
"edt_conf_enum_automatic": "Automatico",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "impostazioni Generali",
|
||||
"edt_conf_gen_name_title": "Nome configurazione",
|
||||
"edt_conf_gen_name_expl": "Un nome definito dall'utente che viene utilizzato per riconoscere Hyperion. (Utile con più di un'istanza di Hyperion)",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "Percorso del dispositivo di cattura usb.",
|
||||
"edt_conf_v4l2_standard_title": "Standard video",
|
||||
"edt_conf_v4l2_standard_expl": "Seleziona lo standard video per la tua regione",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "Decimazione dimensione",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "Il fattore di decimazione della dimensione",
|
||||
"edt_conf_v4l2_cropLeft_title": "Ritaglia sinistra",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "",
|
||||
"edt_conf_enum_bbosd": "",
|
||||
"edt_conf_enum_automatic": "",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "",
|
||||
"edt_conf_gen_name_title": "",
|
||||
"edt_conf_gen_name_expl": "",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "",
|
||||
"edt_conf_v4l2_standard_title": "",
|
||||
"edt_conf_v4l2_standard_expl": "",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "",
|
||||
"edt_conf_v4l2_cropLeft_title": "",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "",
|
||||
"edt_conf_enum_bbosd": "",
|
||||
"edt_conf_enum_automatic": "",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "",
|
||||
"edt_conf_gen_name_title": "",
|
||||
"edt_conf_gen_name_expl": "",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "",
|
||||
"edt_conf_v4l2_standard_title": "",
|
||||
"edt_conf_v4l2_standard_expl": "",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "",
|
||||
"edt_conf_v4l2_cropLeft_title": "",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "",
|
||||
"edt_conf_enum_bbosd": "",
|
||||
"edt_conf_enum_automatic": "",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "",
|
||||
"edt_conf_gen_name_title": "",
|
||||
"edt_conf_gen_name_expl": "",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "",
|
||||
"edt_conf_v4l2_standard_title": "",
|
||||
"edt_conf_v4l2_standard_expl": "",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "",
|
||||
"edt_conf_v4l2_cropLeft_title": "",
|
||||
|
@ -431,6 +431,7 @@
|
||||
"edt_conf_enum_bbclassic": "Klassisk",
|
||||
"edt_conf_enum_bbosd": "OSD",
|
||||
"edt_conf_enum_automatic": "Automatisk",
|
||||
"edt_conf_enum_custom": "",
|
||||
"edt_conf_gen_heading_title": "Allmänna Inställningar",
|
||||
"edt_conf_gen_name_title": "Konfigurationsnamn",
|
||||
"edt_conf_gen_name_expl": "Ett användardefinierat namn som används för att identifiera Hyperion. (Hjälpsamt om du har mer än en Hyperion-instans)",
|
||||
@ -492,6 +493,10 @@
|
||||
"edt_conf_v4l2_device_expl": "Sökvägen till USB-fångstgränssnittet. Ställ in på 'auto' för automatisk upptäckt. Exempel: '/dev/video0'",
|
||||
"edt_conf_v4l2_standard_title": "Videostandard",
|
||||
"edt_conf_v4l2_standard_expl": "Välj videostandard för din region. 'Auto' behåller det värde som väljs av v4l2-gränssnittet",
|
||||
"edt_conf_v4l2_resolution_title": "",
|
||||
"edt_conf_v4l2_resolution_expl": "",
|
||||
"edt_conf_v4l2_framerate_title": "",
|
||||
"edt_conf_v4l2_framerate_expl": "",
|
||||
"edt_conf_v4l2_sizeDecimation_title": "Bildreduktionsfaktor",
|
||||
"edt_conf_v4l2_sizeDecimation_expl": "Faktorn för bildminskning baserad på originalstorleken, 1 betyder ingen förändring (originalbild).",
|
||||
"edt_conf_v4l2_cropLeft_title": "Beskär vänster",
|
||||
|
@ -4,39 +4,171 @@ $(document).ready( function() {
|
||||
var conf_editor_fg = null;
|
||||
var conf_editor_instCapt = null;
|
||||
|
||||
function hideEl(el)
|
||||
{
|
||||
for(var i = 0; i<el.length; i++)
|
||||
// Dynamic v4l2 enum schema
|
||||
var v4l2_dynamic_enum_schema = {
|
||||
"available_devices":
|
||||
{
|
||||
$('[data-schemapath*="root.framegrabber.'+el[i]+'"]').toggle(false);
|
||||
"type": "string",
|
||||
"title": "edt_conf_v4l2_device_title",
|
||||
"propertyOrder" : 1,
|
||||
"required" : true
|
||||
},
|
||||
"resolutions":
|
||||
{
|
||||
"type": "string",
|
||||
"title": "edt_conf_v4l2_resolution_title",
|
||||
"propertyOrder" : 4,
|
||||
"required" : true
|
||||
},
|
||||
"framerates":
|
||||
{
|
||||
"type": "string",
|
||||
"title": "edt_conf_v4l2_framerate_title",
|
||||
"propertyOrder" : 7,
|
||||
"required" : true
|
||||
}
|
||||
};
|
||||
|
||||
// Build dynamic v4l2 enum schema parts
|
||||
var buildSchemaPart = function(key, schema, device) {
|
||||
if (schema[key]) {
|
||||
var enumVals = [];
|
||||
var enumTitelVals = [];
|
||||
var v4l2_properties = JSON.parse(JSON.stringify(window.serverInfo.grabbers.v4l2_properties));
|
||||
|
||||
if (key === 'available_devices') {
|
||||
for (var i = 0; i < v4l2_properties.length; i++) {
|
||||
enumVals.push(v4l2_properties[i]['device']);
|
||||
|
||||
v4l2_properties[i].hasOwnProperty('name')
|
||||
? enumTitelVals.push(v4l2_properties[i]['name'])
|
||||
: enumTitelVals.push(v4l2_properties[i]['device']);
|
||||
}
|
||||
} else if (key == 'resolutions' || key == 'framerates') {
|
||||
for (var i = 0; i < v4l2_properties.length; i++) {
|
||||
if (v4l2_properties[i]['device'] == device) {
|
||||
enumVals = enumTitelVals = v4l2_properties[i][key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.schema.grabberV4L2.properties[key] = {
|
||||
"type": schema[key].type,
|
||||
"title": schema[key].title,
|
||||
"enum": [].concat(["auto"], enumVals, ["custom"]),
|
||||
"options" :
|
||||
{
|
||||
"enum_titles" : [].concat(["edt_conf_enum_automatic"], enumTitelVals, ["edt_conf_enum_custom"]),
|
||||
},
|
||||
"propertyOrder" : schema[key].propertyOrder,
|
||||
"required" : schema[key].required
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Switch between visible states
|
||||
function toggleOption(option, state) {
|
||||
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').toggle(state);
|
||||
if (state) (
|
||||
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').addClass('col-md-12'),
|
||||
$('label[for="root_grabberV4L2_'+option+'"]').css('left','10px'),
|
||||
$('[id="root_grabberV4L2_'+option+'"]').css('left','10px')
|
||||
);
|
||||
}
|
||||
|
||||
if(window.showOptHelp)
|
||||
{
|
||||
//fg
|
||||
// Watch all v4l2 dynamic fields
|
||||
var setWatchers = function(schema) {
|
||||
var path = 'root.grabberV4L2.';
|
||||
Object.keys(schema).forEach(function(key) {
|
||||
conf_editor_v4l2.watch(path + key, function() {
|
||||
var ed = conf_editor_v4l2.getEditor(path + key);
|
||||
var val = ed.getValue();
|
||||
|
||||
if (key == 'available_devices') {
|
||||
var V4L2properties = ['resolutions', 'framerates'];
|
||||
if (val == 'custom') {
|
||||
var grabberV4L2 = ed.parent;
|
||||
V4L2properties.forEach(function(item) {
|
||||
buildSchemaPart(item, v4l2_dynamic_enum_schema, 'none');
|
||||
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
|
||||
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
|
||||
|
||||
grabberV4L2.removeObjectProperty(item);
|
||||
delete grabberV4L2.cached_editors[item];
|
||||
grabberV4L2.addObjectProperty(item);
|
||||
|
||||
conf_editor_v4l2.getEditor(path + item).enable();
|
||||
});
|
||||
|
||||
toggleOption('device', true);
|
||||
} else if (val == 'auto') {
|
||||
V4L2properties.forEach(function(item) {
|
||||
conf_editor_v4l2.getEditor(path + item).setValue('auto');
|
||||
conf_editor_v4l2.getEditor(path + item).disable();
|
||||
});
|
||||
|
||||
(toggleOption('device', false), toggleOption('width', false),
|
||||
toggleOption('height', false), toggleOption('fps', false));
|
||||
} else {
|
||||
var grabberV4L2 = ed.parent;
|
||||
V4L2properties.forEach(function(item) {
|
||||
buildSchemaPart(item, v4l2_dynamic_enum_schema, val);
|
||||
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
|
||||
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
|
||||
|
||||
grabberV4L2.removeObjectProperty(item);
|
||||
delete grabberV4L2.cached_editors[item];
|
||||
grabberV4L2.addObjectProperty(item);
|
||||
|
||||
conf_editor_v4l2.getEditor(path + item).enable();
|
||||
});
|
||||
|
||||
toggleOption('device', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (key == 'resolutions')
|
||||
val != 'custom'
|
||||
? (toggleOption('width', false), toggleOption('height', false))
|
||||
: (toggleOption('width', true), toggleOption('height', true));
|
||||
|
||||
if (key == 'framerates')
|
||||
val != 'custom'
|
||||
? toggleOption('fps', false)
|
||||
: toggleOption('fps', true);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Insert dynamic v4l2 enum schema parts
|
||||
Object.keys(v4l2_dynamic_enum_schema).forEach(function(key) {
|
||||
buildSchemaPart(key, v4l2_dynamic_enum_schema, window.serverConfig.grabberV4L2.device);
|
||||
});
|
||||
|
||||
if(window.showOptHelp) {
|
||||
// Instance Capture
|
||||
$('#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(window.schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title")));
|
||||
|
||||
//fg
|
||||
// Framegrabber
|
||||
$('#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(createHelpTable(window.schema.framegrabber.properties, $.i18n("edt_conf_fg_heading_title")));
|
||||
|
||||
//v4l
|
||||
// V4L2
|
||||
$('#conf_cont').append(createRow('conf_cont_v4l'));
|
||||
$('#conf_cont_v4l').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
|
||||
$('#conf_cont_v4l').append(createHelpTable(window.schema.grabberV4L2.properties, $.i18n("edt_conf_v4l2_heading_title")));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$('#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_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
|
||||
}
|
||||
//instCapt
|
||||
|
||||
// Instance Capture
|
||||
conf_editor_instCapt = createJsonEditor('editor_container_instCapt', {
|
||||
instCapture: window.schema.instCapture
|
||||
}, true, true);
|
||||
@ -49,8 +181,7 @@ $(document).ready( function() {
|
||||
requestWriteConfig(conf_editor_instCapt.getValue());
|
||||
});
|
||||
|
||||
|
||||
//fg
|
||||
// Framegrabber
|
||||
conf_editor_fg = createJsonEditor('editor_container_fg', {
|
||||
framegrabber: window.schema.framegrabber
|
||||
}, true, true);
|
||||
@ -63,7 +194,6 @@ $(document).ready( function() {
|
||||
requestWriteConfig(conf_editor_fg.getValue());
|
||||
});
|
||||
|
||||
//vl4
|
||||
conf_editor_v4l2 = createJsonEditor('editor_container_v4l2', {
|
||||
grabberV4L2 : window.schema.grabberV4L2
|
||||
}, true, true);
|
||||
@ -72,28 +202,80 @@ $(document).ready( function() {
|
||||
conf_editor_v4l2.validate().length ? $('#btn_submit_v4l2').attr('disabled', true) : $('#btn_submit_v4l2').attr('disabled', false);
|
||||
});
|
||||
|
||||
$('#btn_submit_v4l2').off().on('click',function() {
|
||||
requestWriteConfig(conf_editor_v4l2.getValue());
|
||||
conf_editor_v4l2.on('ready', function() {
|
||||
setWatchers(v4l2_dynamic_enum_schema);
|
||||
|
||||
if (window.serverConfig.grabberV4L2.available_devices == 'custom' && window.serverConfig.grabberV4L2.device != 'auto')
|
||||
toggleOption('device', true);
|
||||
|
||||
if (window.serverConfig.grabberV4L2.device == 'auto')
|
||||
conf_editor_v4l2.getEditor('root.grabberV4L2.available_devices').setValue('auto');
|
||||
|
||||
if (window.serverConfig.grabberV4L2.available_devices == 'auto') {
|
||||
['resolutions', 'framerates'].forEach(function(item) {
|
||||
conf_editor_v4l2.getEditor('root.grabberV4L2.' + item).setValue('auto');
|
||||
conf_editor_v4l2.getEditor('root.grabberV4L2.' + item).disable();
|
||||
});
|
||||
}
|
||||
|
||||
if (window.serverConfig.grabberV4L2.resolutions == 'custom' && window.serverConfig.grabberV4L2.device != 'auto')
|
||||
(toggleOption('width', true), toggleOption('height', true));
|
||||
|
||||
if (window.serverConfig.grabberV4L2.framerates == 'custom' && window.serverConfig.grabberV4L2.device != 'auto')
|
||||
toggleOption('fps', true);
|
||||
|
||||
});
|
||||
|
||||
$('#btn_submit_v4l2').off().on('click',function() {
|
||||
var v4l2Options = conf_editor_v4l2.getValue()
|
||||
|
||||
if (v4l2Options.grabberV4L2.available_devices != 'custom' && v4l2Options.grabberV4L2.available_devices != 'auto')
|
||||
v4l2Options.grabberV4L2.device = v4l2Options.grabberV4L2.available_devices;
|
||||
|
||||
if (v4l2Options.grabberV4L2.available_devices == 'auto')
|
||||
v4l2Options.grabberV4L2.device = 'auto';
|
||||
|
||||
if (v4l2Options.grabberV4L2.resolutions != 'custom' && v4l2Options.grabberV4L2.resolutions != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto')
|
||||
(v4l2Options.grabberV4L2.width = parseInt(v4l2Options.grabberV4L2.resolutions.split('x')[0]),
|
||||
v4l2Options.grabberV4L2.height = parseInt(v4l2Options.grabberV4L2.resolutions.split('x')[1]));
|
||||
|
||||
if (v4l2Options.grabberV4L2.resolutions == 'auto')
|
||||
(v4l2Options.grabberV4L2.width = 0, v4l2Options.grabberV4L2.height = 0);
|
||||
|
||||
if (v4l2Options.grabberV4L2.framerates != 'custom' && v4l2Options.grabberV4L2.framerates != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto')
|
||||
v4l2Options.grabberV4L2.fps = parseInt(v4l2Options.grabberV4L2.framerates);
|
||||
|
||||
if (v4l2Options.grabberV4L2.framerates == 'auto')
|
||||
v4l2Options.grabberV4L2.fps = 15;
|
||||
|
||||
requestWriteConfig(v4l2Options);
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
//create introduction
|
||||
if(window.showOptHelp)
|
||||
{
|
||||
if(window.showOptHelp) {
|
||||
createHint("intro", $.i18n('conf_grabber_fg_intro'), "editor_container_fg");
|
||||
createHint("intro", $.i18n('conf_grabber_v4l_intro'), "editor_container_v4l2");
|
||||
}
|
||||
|
||||
function hideEl(el) {
|
||||
for(var i = 0; i<el.length; i++) {
|
||||
$('[data-schemapath*="root.framegrabber.'+el[i]+'"]').toggle(false);
|
||||
}
|
||||
}
|
||||
|
||||
//hide specific options
|
||||
conf_editor_fg.on('ready',function() {
|
||||
var grabbers = window.serverInfo.grabbers.available;
|
||||
|
||||
if(grabbers.indexOf('dispmanx') > -1)
|
||||
if (grabbers.indexOf('dispmanx') > -1)
|
||||
hideEl(["device","pixelDecimation"]);
|
||||
else if(grabbers.indexOf('x11') > -1)
|
||||
else if (grabbers.indexOf('x11') > -1)
|
||||
hideEl(["device","width","height"]);
|
||||
else if(grabbers.indexOf('osx') > -1 )
|
||||
else if (grabbers.indexOf('osx') > -1 )
|
||||
hideEl(["device","pixelDecimation"]);
|
||||
else if(grabbers.indexOf('amlogic') > -1)
|
||||
else if (grabbers.indexOf('amlogic') > -1)
|
||||
hideEl(["pixelDecimation"]);
|
||||
});
|
||||
|
||||
|
@ -216,7 +216,7 @@ private:
|
||||
///
|
||||
void handleConfigCommand(const QJsonObject &message, const QString &command, const int tan);
|
||||
|
||||
/// Handle an incoming JSON GetConfig message from handleConfigCommand()
|
||||
/// Handle an incoming JSON GetSchema message from handleConfigCommand()
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <QObject>
|
||||
#include <QSocketNotifier>
|
||||
#include <QRectF>
|
||||
#include <QMap>
|
||||
|
||||
// util includes
|
||||
#include <utils/PixelFormat.h>
|
||||
@ -40,6 +41,13 @@ class V4L2Grabber : public Grabber
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct DeviceProperties
|
||||
{
|
||||
QString name = QString();
|
||||
QStringList resolutions = QStringList();
|
||||
QStringList framerates = QStringList();
|
||||
};
|
||||
|
||||
V4L2Grabber(const QString & device,
|
||||
const unsigned width,
|
||||
const unsigned height,
|
||||
@ -48,7 +56,7 @@ public:
|
||||
PixelFormat pixelFormat,
|
||||
int pixelDecimation
|
||||
);
|
||||
virtual ~V4L2Grabber();
|
||||
~V4L2Grabber() override;
|
||||
|
||||
QRectF getSignalDetectionOffset()
|
||||
{
|
||||
@ -63,44 +71,64 @@ public:
|
||||
/// @brief set new PixelDecimation value to ImageResampler
|
||||
/// @param pixelDecimation The new pixelDecimation value
|
||||
///
|
||||
virtual void setPixelDecimation(int pixelDecimation);
|
||||
void setPixelDecimation(int pixelDecimation) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual void setSignalThreshold(
|
||||
void setSignalThreshold(
|
||||
double redSignalThreshold,
|
||||
double greenSignalThreshold,
|
||||
double blueSignalThreshold,
|
||||
int noSignalCounterThreshold = 50);
|
||||
int noSignalCounterThreshold = 50) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual void setSignalDetectionOffset(
|
||||
void setSignalDetectionOffset(
|
||||
double verticalMin,
|
||||
double horizontalMin,
|
||||
double verticalMax,
|
||||
double horizontalMax);
|
||||
double horizontalMax) override;
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual void setSignalDetectionEnable(bool enable);
|
||||
void setSignalDetectionEnable(bool enable) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard);
|
||||
void setDeviceVideoStandard(QString device, VideoStandard videoStandard) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual bool setFramerate(int fps);
|
||||
bool setFramerate(int fps) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
virtual bool setWidthHeight(int width, int height);
|
||||
bool setWidthHeight(int width, int height) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
QStringList getV4L2devices() override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
QString getV4L2deviceName(QString devicePath) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
QStringList getResolutions(QString devicePath) override;
|
||||
|
||||
///
|
||||
/// @brief overwrite Grabber.h implementation
|
||||
///
|
||||
QStringList getFramerates(QString devicePath) override;
|
||||
|
||||
public slots:
|
||||
|
||||
@ -145,6 +173,8 @@ private:
|
||||
|
||||
int xioctl(int request, void *arg);
|
||||
|
||||
int xioctl(int fileDescriptor, int request, void *arg);
|
||||
|
||||
void throw_exception(const QString & error)
|
||||
{
|
||||
Error(_log, "Throws error: %s", QSTRING_CSTR(error));
|
||||
@ -198,12 +228,13 @@ private:
|
||||
|
||||
private:
|
||||
QString _deviceName;
|
||||
std::map<QString,QString> _v4lDevices;
|
||||
int _input;
|
||||
VideoStandard _videoStandard;
|
||||
io_method _ioMethod;
|
||||
int _fileDescriptor;
|
||||
std::vector<buffer> _buffers;
|
||||
std::map<QString, QString> _v4lDevices;
|
||||
QMap<QString, V4L2Grabber::DeviceProperties> _deviceProperties;
|
||||
int _input;
|
||||
VideoStandard _videoStandard;
|
||||
io_method _ioMethod;
|
||||
int _fileDescriptor;
|
||||
std::vector<buffer> _buffers;
|
||||
|
||||
PixelFormat _pixelFormat;
|
||||
int _pixelDecimation;
|
||||
@ -225,4 +256,7 @@ private:
|
||||
|
||||
bool _initialized;
|
||||
bool _deviceAutoDiscoverEnabled;
|
||||
|
||||
protected:
|
||||
void enumFrameIntervals(QStringList &framerates, int fileDescriptor, int pixelformat, int width, int height);
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ class Grabber : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Grabber(QString grabberName, int width=0, int height=0, int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0);
|
||||
Grabber(QString grabberName = "", int width=0, int height=0, int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0);
|
||||
virtual ~Grabber();
|
||||
|
||||
///
|
||||
@ -42,14 +42,14 @@ public:
|
||||
|
||||
///
|
||||
/// @brief Apply new framerate (used from v4l)
|
||||
/// @param fps framesPerSecond
|
||||
/// @param fps framesPerSecond
|
||||
///
|
||||
virtual bool setFramerate(int fps);
|
||||
|
||||
///
|
||||
/// @brief Apply new pixelDecimation (used from x11 and qt)
|
||||
///
|
||||
virtual void setPixelDecimation(int pixelDecimation) {};
|
||||
virtual void setPixelDecimation(int pixelDecimation) {}
|
||||
|
||||
///
|
||||
/// @brief Apply new signalThreshold (used from v4l)
|
||||
@ -58,7 +58,7 @@ public:
|
||||
double redSignalThreshold,
|
||||
double greenSignalThreshold,
|
||||
double blueSignalThreshold,
|
||||
int noSignalCounterThreshold = 50) {};
|
||||
int noSignalCounterThreshold = 50) {}
|
||||
///
|
||||
/// @brief Apply new SignalDetectionOffset (used from v4l)
|
||||
///
|
||||
@ -66,43 +66,70 @@ public:
|
||||
double verticalMin,
|
||||
double horizontalMin,
|
||||
double verticalMax,
|
||||
double horizontalMax) {};
|
||||
double horizontalMax) {}
|
||||
|
||||
///
|
||||
/// @brief Apply SignalDetectionEnable (used from v4l)
|
||||
///
|
||||
virtual void setSignalDetectionEnable(bool enable) {};
|
||||
virtual void setSignalDetectionEnable(bool enable) {}
|
||||
|
||||
///
|
||||
/// @brief Apply device and videoStanded (used from v4l)
|
||||
///
|
||||
virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard) {};
|
||||
virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard) {}
|
||||
|
||||
///
|
||||
/// @brief Apply display index (used from qt)
|
||||
///
|
||||
virtual void setDisplayIndex(int index) {};
|
||||
virtual void setDisplayIndex(int index) {}
|
||||
|
||||
///
|
||||
/// @brief Apply path for device (used from framebuffer)
|
||||
///
|
||||
virtual void setDevicePath(const QString& path) {};
|
||||
virtual void setDevicePath(const QString& path) {}
|
||||
|
||||
///
|
||||
/// @brief get current resulting height of image (after crop)
|
||||
///
|
||||
virtual int getImageWidth() { return _width; };
|
||||
virtual int getImageWidth() { return _width; }
|
||||
|
||||
///
|
||||
/// @brief get current resulting width of image (after crop)
|
||||
///
|
||||
virtual int getImageHeight() { return _height; };
|
||||
virtual int getImageHeight() { return _height; }
|
||||
|
||||
///
|
||||
/// @brief Prevent the real capture implementation from capturing if disabled
|
||||
///
|
||||
void setEnabled(bool enable);
|
||||
|
||||
///
|
||||
/// @brief Get a list of all available V4L devices
|
||||
/// @return List of all available V4L devices on success else empty List
|
||||
///
|
||||
virtual QStringList getV4L2devices() { return QStringList(); }
|
||||
|
||||
///
|
||||
/// @brief Get the V4L device name
|
||||
/// @param devicePath The device path
|
||||
/// @return The name of the V4L device on success else empty String
|
||||
///
|
||||
virtual QString getV4L2deviceName(QString devicePath) { return QString(); }
|
||||
|
||||
///
|
||||
/// @brief Get a list of supported device resolutions
|
||||
/// @param devicePath The device path
|
||||
/// @return List of resolutions on success else empty List
|
||||
///
|
||||
virtual QStringList getResolutions(QString devicePath) { return QStringList(); }
|
||||
|
||||
///
|
||||
/// @brief Get a list of supported device framerates
|
||||
/// @param devicePath The device path
|
||||
/// @return List of framerates on success else empty List
|
||||
///
|
||||
virtual QStringList getFramerates(QString devicePath) { return QStringList(); }
|
||||
|
||||
protected:
|
||||
ImageResampler _imageResampler;
|
||||
|
||||
|
@ -32,6 +32,9 @@ public:
|
||||
|
||||
virtual ~GrabberWrapper();
|
||||
|
||||
static GrabberWrapper* instance;
|
||||
static GrabberWrapper* getInstance(){ return instance; }
|
||||
|
||||
///
|
||||
/// Starts the grabber wich produces led values with the specified update rate
|
||||
///
|
||||
@ -47,6 +50,33 @@ public:
|
||||
///
|
||||
virtual void stop();
|
||||
|
||||
///
|
||||
/// @brief Get a list of all available V4L devices
|
||||
/// @return List of all available V4L devices on success else empty List
|
||||
///
|
||||
virtual QStringList getV4L2devices();
|
||||
|
||||
///
|
||||
/// @brief Get the V4L device name
|
||||
/// @param devicePath The device path
|
||||
/// @return The name of the V4L device on success else empty String
|
||||
///
|
||||
virtual QString getV4L2deviceName(QString devicePath);
|
||||
|
||||
///
|
||||
/// @brief Get a list of supported device resolutions
|
||||
/// @param devicePath The device path
|
||||
/// @return List of resolutions on success else empty List
|
||||
///
|
||||
virtual QStringList getResolutions(QString devicePath);
|
||||
|
||||
///
|
||||
/// @brief Get a list of supported device framerates
|
||||
/// @param devicePath The device path
|
||||
/// @return List of framerates on success else empty List
|
||||
///
|
||||
virtual QStringList getFramerates(QString devicePath);
|
||||
|
||||
static QStringList availableGrabbers();
|
||||
|
||||
public:
|
||||
|
@ -469,14 +469,51 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
|
||||
|
||||
QJsonObject grabbers;
|
||||
QJsonArray availableGrabbers;
|
||||
QJsonObject availableProperties;
|
||||
|
||||
#if defined(ENABLE_DISPMANX) || defined(ENABLE_V4L2) || defined(ENABLE_FB) || defined(ENABLE_AMLOGIC) || defined(ENABLE_OSX) || defined(ENABLE_X11)
|
||||
|
||||
// get available grabbers
|
||||
//grabbers["active"] = ????;
|
||||
for (auto grabber : GrabberWrapper::availableGrabbers())
|
||||
{
|
||||
availableGrabbers.append(grabber);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_V4L2)
|
||||
|
||||
QJsonArray availableV4L2devices;
|
||||
for (auto devicePath : GrabberWrapper::getInstance()->getV4L2devices())
|
||||
{
|
||||
|
||||
QJsonObject device;
|
||||
device["device"] = devicePath;
|
||||
device["name"] = GrabberWrapper::getInstance()->getV4L2deviceName(devicePath);
|
||||
|
||||
|
||||
QJsonArray availableResolutions;
|
||||
for (auto resolution : GrabberWrapper::getInstance()->getResolutions(devicePath))
|
||||
{
|
||||
availableResolutions.append(resolution);
|
||||
}
|
||||
device.insert("resolutions", availableResolutions);
|
||||
|
||||
QJsonArray availableFramerates;
|
||||
for (auto framerate : GrabberWrapper::getInstance()->getFramerates(devicePath))
|
||||
{
|
||||
availableFramerates.append(framerate);
|
||||
}
|
||||
device.insert("framerates", availableFramerates);
|
||||
|
||||
availableV4L2devices.append(device);
|
||||
}
|
||||
|
||||
grabbers["v4l2_properties"] = availableV4L2devices;
|
||||
|
||||
#endif
|
||||
|
||||
grabbers["available"] = availableGrabbers;
|
||||
info["videomode"] = QString(videoMode2String(_hyperion->getCurrentVideoMode()));
|
||||
info["grabbers"] = grabbers;
|
||||
|
@ -26,6 +26,10 @@
|
||||
|
||||
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
||||
|
||||
#ifndef V4L2_CAP_META_CAPTURE
|
||||
#define V4L2_CAP_META_CAPTURE 0x00800000 // Specified in kernel header v4.16. Required for backward compatibility.
|
||||
#endif
|
||||
|
||||
V4L2Grabber::V4L2Grabber(const QString & device
|
||||
, const unsigned width
|
||||
, const unsigned height
|
||||
@ -84,13 +88,13 @@ void V4L2Grabber::uninit()
|
||||
|
||||
bool V4L2Grabber::init()
|
||||
{
|
||||
if (! _initialized)
|
||||
if (!_initialized)
|
||||
{
|
||||
getV4Ldevices();
|
||||
QString v4lDevices_str;
|
||||
|
||||
// show list only once
|
||||
if ( ! QString(QSTRING_CSTR(_deviceName)).startsWith("/dev/") )
|
||||
if (!QString(QSTRING_CSTR(_deviceName)).startsWith("/dev/"))
|
||||
{
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
@ -100,7 +104,7 @@ bool V4L2Grabber::init()
|
||||
Info(_log, "available V4L2 devices:\n%s", QSTRING_CSTR(v4lDevices_str));
|
||||
}
|
||||
|
||||
if ( _deviceName == "auto" )
|
||||
if (_deviceName == "auto")
|
||||
{
|
||||
_deviceAutoDiscoverEnabled = true;
|
||||
_deviceName = "unknown";
|
||||
@ -108,20 +112,20 @@ bool V4L2Grabber::init()
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
_deviceName = dev.first;
|
||||
if ( init() )
|
||||
if (init())
|
||||
{
|
||||
Info(_log, "found usable v4l2 device: %s (%s)",QSTRING_CSTR(dev.first), QSTRING_CSTR(dev.second));
|
||||
_deviceAutoDiscoverEnabled = false;
|
||||
return _initialized;
|
||||
}
|
||||
}
|
||||
Info( _log, "no usable device found" );
|
||||
Info(_log, "no usable device found");
|
||||
}
|
||||
else if ( ! _deviceName.startsWith("/dev/") )
|
||||
else if (!_deviceName.startsWith("/dev/"))
|
||||
{
|
||||
for (auto& dev: _v4lDevices)
|
||||
{
|
||||
if ( _deviceName.toLower() == dev.second.toLower() )
|
||||
if (_deviceName.toLower() == dev.second.toLower())
|
||||
{
|
||||
_deviceName = dev.first;
|
||||
Info(_log, "found v4l2 device with configured name: %s (%s)", QSTRING_CSTR(dev.second), QSTRING_CSTR(dev.first) );
|
||||
@ -138,7 +142,7 @@ bool V4L2Grabber::init()
|
||||
try
|
||||
{
|
||||
// do not init with unknown device
|
||||
if(_deviceName != "unknown")
|
||||
if (_deviceName != "unknown")
|
||||
{
|
||||
if (open_device())
|
||||
{
|
||||
@ -165,22 +169,96 @@ bool V4L2Grabber::init()
|
||||
void V4L2Grabber::getV4Ldevices()
|
||||
{
|
||||
QDirIterator it("/sys/class/video4linux/", QDirIterator::NoIteratorFlags);
|
||||
_deviceProperties.clear();
|
||||
while(it.hasNext())
|
||||
{
|
||||
//_v4lDevices
|
||||
QString dev = it.next();
|
||||
if (it.fileName().startsWith("video"))
|
||||
{
|
||||
QString devName = "/dev/" + it.fileName();
|
||||
int fd = open(QSTRING_CSTR(devName), O_RDWR | O_NONBLOCK, 0);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
throw_errno_exception("Cannot open '" + devName + "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct v4l2_capability cap;
|
||||
CLEAR(cap);
|
||||
|
||||
if (xioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
|
||||
{
|
||||
throw_errno_exception("'" + devName + "' is no V4L2 device");
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cap.device_caps & V4L2_CAP_META_CAPTURE) // this device has bit 23 set (and bit 1 reset), so it doesn't have capture.
|
||||
{
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the current settings
|
||||
struct v4l2_format fmt;
|
||||
CLEAR(fmt);
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (xioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
|
||||
{
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
V4L2Grabber::DeviceProperties properties;
|
||||
|
||||
// collect available device resolutions & frame rates
|
||||
struct v4l2_frmsizeenum frmsizeenum;
|
||||
CLEAR(frmsizeenum);
|
||||
|
||||
frmsizeenum.index = 0;
|
||||
frmsizeenum.pixel_format = fmt.fmt.pix.pixelformat;
|
||||
while (xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
|
||||
{
|
||||
switch (frmsizeenum.type)
|
||||
{
|
||||
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
||||
{
|
||||
properties.resolutions << QString::number(frmsizeenum.discrete.width) + "x" + QString::number(frmsizeenum.discrete.height);
|
||||
enumFrameIntervals(properties.framerates, fd, fmt.fmt.pix.pixelformat, frmsizeenum.discrete.width, frmsizeenum.discrete.height);
|
||||
}
|
||||
break;
|
||||
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
||||
case V4L2_FRMSIZE_TYPE_STEPWISE:
|
||||
{
|
||||
for(unsigned int y = frmsizeenum.stepwise.min_height; y <= frmsizeenum.stepwise.max_height; y += frmsizeenum.stepwise.step_height)
|
||||
{
|
||||
for(unsigned int x = frmsizeenum.stepwise.min_width; x <= frmsizeenum.stepwise.max_width; x += frmsizeenum.stepwise.step_width)
|
||||
{
|
||||
properties.resolutions << QString::number(x) + "x" + QString::number(y);
|
||||
enumFrameIntervals(properties.framerates, fd, fmt.fmt.pix.pixelformat, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
frmsizeenum.index++;
|
||||
}
|
||||
|
||||
if (close(fd) < 0) continue;
|
||||
|
||||
QFile devNameFile(dev+"/name");
|
||||
QString devName;
|
||||
if ( devNameFile.exists())
|
||||
if (devNameFile.exists())
|
||||
{
|
||||
devNameFile.open(QFile::ReadOnly);
|
||||
devName = devNameFile.readLine();
|
||||
devName = devName.trimmed();
|
||||
properties.name = devName;
|
||||
devNameFile.close();
|
||||
}
|
||||
_v4lDevices.emplace("/dev/"+it.fileName(), devName);
|
||||
_deviceProperties.insert("/dev/"+it.fileName(), properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,6 +315,7 @@ void V4L2Grabber::stop()
|
||||
uninit_device();
|
||||
close_device();
|
||||
_initialized = false;
|
||||
_deviceProperties.clear();
|
||||
Info(_log, "Stopped");
|
||||
}
|
||||
}
|
||||
@ -409,6 +488,8 @@ void V4L2Grabber::init_userp(unsigned int buffer_size)
|
||||
void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
CLEAR(cap);
|
||||
|
||||
if (-1 == xioctl(VIDIOC_QUERYCAP, &cap))
|
||||
{
|
||||
if (EINVAL == errno)
|
||||
@ -484,6 +565,8 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
|
||||
// set input if needed and supported
|
||||
struct v4l2_input v4l2Input;
|
||||
CLEAR(v4l2Input);
|
||||
|
||||
v4l2Input.index = input;
|
||||
|
||||
if (input >= 0 && 0 == xioctl(VIDIOC_ENUMINPUT,&v4l2Input))
|
||||
@ -496,41 +579,46 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
}
|
||||
|
||||
// set the video standard if needed and supported
|
||||
v4l2_std_id std_id;
|
||||
if (-1 != xioctl(VIDIOC_ENUMSTD, &std_id))
|
||||
struct v4l2_standard standard;
|
||||
CLEAR(standard);
|
||||
|
||||
if (-1 != xioctl(VIDIOC_ENUMSTD, &standard))
|
||||
{
|
||||
switch (videoStandard)
|
||||
{
|
||||
case VIDEOSTANDARD_PAL:
|
||||
{
|
||||
std_id = V4L2_STD_PAL;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &std_id))
|
||||
standard.id = V4L2_STD_PAL;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &standard.id))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_STD");
|
||||
break;
|
||||
}
|
||||
Debug(_log, "Video standard=PAL");
|
||||
}
|
||||
break;
|
||||
|
||||
case VIDEOSTANDARD_NTSC:
|
||||
{
|
||||
std_id = V4L2_STD_NTSC;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &std_id))
|
||||
standard.id = V4L2_STD_NTSC;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &standard.id))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_STD");
|
||||
break;
|
||||
}
|
||||
Debug(_log, "Video standard=NTSC");
|
||||
}
|
||||
break;
|
||||
|
||||
case VIDEOSTANDARD_SECAM:
|
||||
{
|
||||
std_id = V4L2_STD_SECAM;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &std_id))
|
||||
standard.id = V4L2_STD_SECAM;
|
||||
if (-1 == xioctl(VIDIOC_S_STD, &standard.id))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_STD");
|
||||
break;
|
||||
}
|
||||
Debug(_log, "Video standard=SECAM");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -544,6 +632,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
// get the current settings
|
||||
struct v4l2_format fmt;
|
||||
CLEAR(fmt);
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == xioctl(VIDIOC_G_FMT, &fmt))
|
||||
{
|
||||
@ -581,42 +670,14 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
break;
|
||||
}
|
||||
|
||||
// collect available device resolutions
|
||||
QString v4lDevice_res;
|
||||
v4l2_frmsizeenum frmsizeenum;
|
||||
CLEAR(frmsizeenum);
|
||||
frmsizeenum.index = 0;
|
||||
frmsizeenum.pixel_format = fmt.fmt.pix.pixelformat;
|
||||
while (xioctl(VIDIOC_ENUM_FRAMESIZES, &frmsizeenum) >= 0)
|
||||
// set custom resolution for width and height if they are not zero
|
||||
if(_width && _height)
|
||||
{
|
||||
switch (frmsizeenum.type)
|
||||
{
|
||||
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
||||
v4lDevice_res += "\t"+ QString::number(frmsizeenum.discrete.width) + "x" + QString::number(frmsizeenum.discrete.height) + "\n";
|
||||
break;
|
||||
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
||||
case V4L2_FRMSIZE_TYPE_STEPWISE:
|
||||
{
|
||||
for(unsigned int y = frmsizeenum.stepwise.min_height; y <= frmsizeenum.stepwise.max_height; y += frmsizeenum.stepwise.step_height)
|
||||
{
|
||||
for(unsigned int x = frmsizeenum.stepwise.min_width; x <= frmsizeenum.stepwise.max_width; x += frmsizeenum.stepwise.step_width)
|
||||
{
|
||||
v4lDevice_res += "\t"+ QString::number(x) + "x" + QString::number(y) + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
frmsizeenum.index++;
|
||||
fmt.fmt.pix.width = _width;
|
||||
fmt.fmt.pix.height = _height;
|
||||
}
|
||||
|
||||
// print available device resolutions in debug mode
|
||||
if (!v4lDevice_res.isEmpty())
|
||||
Debug(_log, "available V4L2 resolutions:\n%s", QSTRING_CSTR(v4lDevice_res));
|
||||
|
||||
// set the settings
|
||||
fmt.fmt.pix.width = _width;
|
||||
fmt.fmt.pix.height = _height;
|
||||
|
||||
if (-1 == xioctl(VIDIOC_S_FMT, &fmt))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_FMT");
|
||||
@ -633,30 +694,19 @@ void V4L2Grabber::init_device(VideoStandard videoStandard, int input)
|
||||
// Trying to set frame rate
|
||||
struct v4l2_streamparm streamparms;
|
||||
CLEAR(streamparms);
|
||||
|
||||
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (-1 == xioctl(VIDIOC_G_PARM, &streamparms))
|
||||
// Check that the driver knows about framerate get/set
|
||||
if (xioctl(VIDIOC_G_PARM, &streamparms) >= 0)
|
||||
{
|
||||
Debug(_log, "Frame rate settings not supported");
|
||||
// continue
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the capability flag is set to V4L2_CAP_TIMEPERFRAME
|
||||
// Check if the device is able to accept a capture framerate set.
|
||||
if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME)
|
||||
{
|
||||
// Driver supports the feature. Set required framerate
|
||||
CLEAR(streamparms);
|
||||
streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
streamparms.parm.capture.timeperframe.numerator = 1;
|
||||
streamparms.parm.capture.timeperframe.denominator = _fps;
|
||||
if(-1 == xioctl(VIDIOC_S_PARM, &streamparms))
|
||||
{
|
||||
throw_errno_exception("VIDIOC_S_PARM");
|
||||
// continue
|
||||
}
|
||||
else
|
||||
// display the used framerate
|
||||
Debug(_log, "Set framerate to %d fps", _fps);
|
||||
(-1 == xioctl(VIDIOC_S_PARM, &streamparms))
|
||||
? Debug(_log, "Frame rate settings not supported.")
|
||||
: Debug(_log, "Set framerate to %d fps", streamparms.parm.capture.timeperframe.denominator);
|
||||
}
|
||||
}
|
||||
|
||||
@ -883,7 +933,11 @@ int V4L2Grabber::read_frame()
|
||||
|
||||
case EIO: /* Could ignore EIO, see spec. */
|
||||
default:
|
||||
{
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
stop();
|
||||
getV4Ldevices();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -916,7 +970,11 @@ int V4L2Grabber::read_frame()
|
||||
|
||||
case EIO: /* Could ignore EIO, see spec. */
|
||||
default:
|
||||
{
|
||||
throw_errno_exception("VIDIOC_DQBUF");
|
||||
stop();
|
||||
getV4Ldevices();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -953,9 +1011,9 @@ bool V4L2Grabber::process_image(const void *p, int size)
|
||||
{
|
||||
// We do want a new frame...
|
||||
#ifdef HAVE_JPEG_DECODER
|
||||
if (size != _frameByteSize && _pixelFormat != PIXELFORMAT_MJPEG)
|
||||
if (size < _frameByteSize && _pixelFormat != PIXELFORMAT_MJPEG)
|
||||
#else
|
||||
if (size != _frameByteSize)
|
||||
if (size < _frameByteSize)
|
||||
#endif
|
||||
{
|
||||
Error(_log, "Frame too small: %d != %d", size, _frameByteSize);
|
||||
@ -1100,7 +1158,7 @@ void V4L2Grabber::process_image(const uint8_t * data, int size)
|
||||
* ------------ END of JPEG decoder related code ------------
|
||||
* --------------------------------------------------------*/
|
||||
|
||||
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
|
||||
_imageResampler.processImage(data, _width, _height, _lineLength, _pixelFormat, image);
|
||||
|
||||
if (_signalDetectionEnabled)
|
||||
{
|
||||
@ -1168,6 +1226,60 @@ int V4L2Grabber::xioctl(int request, void *arg)
|
||||
return r;
|
||||
}
|
||||
|
||||
int V4L2Grabber::xioctl(int fileDescriptor, int request, void *arg)
|
||||
{
|
||||
int r;
|
||||
|
||||
do
|
||||
{
|
||||
r = ioctl(fileDescriptor, request, arg);
|
||||
}
|
||||
while (r < 0 && errno == EINTR );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void V4L2Grabber::enumFrameIntervals(QStringList &framerates, int fileDescriptor, int pixelformat, int width, int height)
|
||||
{
|
||||
// collect available frame rates
|
||||
struct v4l2_frmivalenum frmivalenum;
|
||||
CLEAR(frmivalenum);
|
||||
|
||||
frmivalenum.index = 0;
|
||||
frmivalenum.pixel_format = pixelformat;
|
||||
frmivalenum.width = width;
|
||||
frmivalenum.height = height;
|
||||
|
||||
while (xioctl(fileDescriptor, VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) >= 0)
|
||||
{
|
||||
int rate;
|
||||
switch (frmivalenum.type)
|
||||
{
|
||||
case V4L2_FRMSIZE_TYPE_DISCRETE:
|
||||
{
|
||||
if (frmivalenum.discrete.numerator != 0)
|
||||
{
|
||||
rate = frmivalenum.discrete.denominator / frmivalenum.discrete.numerator;
|
||||
if (!framerates.contains(QString::number(rate)))
|
||||
framerates.append(QString::number(rate));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case V4L2_FRMSIZE_TYPE_CONTINUOUS:
|
||||
case V4L2_FRMSIZE_TYPE_STEPWISE:
|
||||
{
|
||||
if (frmivalenum.stepwise.min.denominator != 0)
|
||||
{
|
||||
rate = frmivalenum.stepwise.min.denominator / frmivalenum.stepwise.min.numerator;
|
||||
if (!framerates.contains(QString::number(rate)))
|
||||
framerates.append(QString::number(rate));
|
||||
}
|
||||
}
|
||||
}
|
||||
frmivalenum.index++;
|
||||
}
|
||||
}
|
||||
|
||||
void V4L2Grabber::setSignalDetectionEnable(bool enable)
|
||||
{
|
||||
if (_signalDetectionEnabled != enable)
|
||||
@ -1227,3 +1339,28 @@ bool V4L2Grabber::setWidthHeight(int width, int height)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList V4L2Grabber::getV4L2devices()
|
||||
{
|
||||
QStringList result = QStringList();
|
||||
for (auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it)
|
||||
{
|
||||
result << it.key();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QString V4L2Grabber::getV4L2deviceName(QString devicePath)
|
||||
{
|
||||
return _deviceProperties.value(devicePath).name;
|
||||
}
|
||||
|
||||
QStringList V4L2Grabber::getResolutions(QString devicePath)
|
||||
{
|
||||
return _deviceProperties.value(devicePath).resolutions;
|
||||
}
|
||||
|
||||
QStringList V4L2Grabber::getFramerates(QString devicePath)
|
||||
{
|
||||
return _deviceProperties.value(devicePath).framerates;
|
||||
}
|
||||
|
@ -90,8 +90,8 @@ bool Grabber::setWidthHeight(int width, int height)
|
||||
|
||||
bool Grabber::setFramerate(int fps)
|
||||
{
|
||||
if(fps > 0)
|
||||
if((fps > 0) && (_fps != fps))
|
||||
_fps = fps;
|
||||
|
||||
return fps > 0;
|
||||
return (fps > 0) && (_fps != fps);
|
||||
}
|
@ -9,6 +9,8 @@
|
||||
// qt
|
||||
#include <QTimer>
|
||||
|
||||
GrabberWrapper* GrabberWrapper::instance = nullptr;
|
||||
|
||||
GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned width, unsigned height, const unsigned updateRate_Hz)
|
||||
: _grabberName(grabberName)
|
||||
, _timer(new QTimer(this))
|
||||
@ -17,6 +19,8 @@ GrabberWrapper::GrabberWrapper(QString grabberName, Grabber * ggrabber, unsigned
|
||||
, _ggrabber(ggrabber)
|
||||
, _image(0,0)
|
||||
{
|
||||
GrabberWrapper::instance = this;
|
||||
|
||||
// Configure the timer to generate events every n milliseconds
|
||||
_timer->setInterval(_updateInterval_ms);
|
||||
|
||||
@ -89,7 +93,6 @@ QStringList GrabberWrapper::availableGrabbers()
|
||||
return grabbers;
|
||||
}
|
||||
|
||||
|
||||
void GrabberWrapper::setVideoMode(const VideoMode& mode)
|
||||
{
|
||||
if (_ggrabber != nullptr)
|
||||
@ -216,3 +219,35 @@ void GrabberWrapper::tryStart()
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList GrabberWrapper::getV4L2devices()
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
return _ggrabber->getV4L2devices();
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString GrabberWrapper::getV4L2deviceName(QString devicePath)
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
return _ggrabber->getV4L2deviceName(devicePath);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList GrabberWrapper::getResolutions(QString devicePath)
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
return _ggrabber->getResolutions(devicePath);
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList GrabberWrapper::getFramerates(QString devicePath)
|
||||
{
|
||||
if(_grabberName.startsWith("V4L"))
|
||||
return _ggrabber->getFramerates(devicePath);
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
@ -7,10 +7,14 @@
|
||||
"device" :
|
||||
{
|
||||
"type" : "string",
|
||||
"title" : "edt_conf_v4l2_device_title",
|
||||
"title" : "edt_conf_enum_custom",
|
||||
"default" : "auto",
|
||||
"options" : {
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 1
|
||||
"propertyOrder" : 2,
|
||||
"comment" : "The 'available_device' settings are dynamically inserted into the WebUI under PropertyOrder '1'."
|
||||
},
|
||||
"standard" :
|
||||
{
|
||||
@ -22,7 +26,7 @@
|
||||
"enum_titles" : ["edt_conf_enum_NO_CHANGE", "edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM"]
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 2
|
||||
"propertyOrder" : 3
|
||||
},
|
||||
"width" :
|
||||
{
|
||||
@ -30,9 +34,13 @@
|
||||
"title" : "edt_conf_fg_width_title",
|
||||
"default" : 0,
|
||||
"minimum" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"options" : {
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"access" : "expert",
|
||||
"propertyOrder" : 3
|
||||
"propertyOrder" : 5,
|
||||
"comment" : "The 'resolution' settings are dynamically inserted into the WebUI under PropertyOrder '4'."
|
||||
},
|
||||
"height" :
|
||||
{
|
||||
@ -40,19 +48,26 @@
|
||||
"title" : "edt_conf_fg_height_title",
|
||||
"default" : 0,
|
||||
"minimum" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"options" : {
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"access" : "expert",
|
||||
"propertyOrder" : 4
|
||||
"propertyOrder" : 6
|
||||
},
|
||||
"fps" :
|
||||
{
|
||||
"type" : "integer",
|
||||
"title" : "Framerate",
|
||||
"title" : "edt_conf_enum_custom",
|
||||
"default" : 15,
|
||||
"minimum" : 1,
|
||||
"append" : "fps",
|
||||
"options" : {
|
||||
"hidden":true
|
||||
},
|
||||
"required" : true,
|
||||
"access" : "expert",
|
||||
"propertyOrder" : 5
|
||||
"propertyOrder" : 8,
|
||||
"comment" : "The 'frames per second' setting is dynamically inserted into the WebUI under PropertyOrder '7'."
|
||||
},
|
||||
"sizeDecimation" :
|
||||
{
|
||||
@ -62,7 +77,7 @@
|
||||
"maximum" : 30,
|
||||
"default" : 6,
|
||||
"required" : true,
|
||||
"propertyOrder" : 6
|
||||
"propertyOrder" : 9
|
||||
},
|
||||
"cropLeft" :
|
||||
{
|
||||
@ -72,7 +87,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 7
|
||||
"propertyOrder" : 10
|
||||
},
|
||||
"cropRight" :
|
||||
{
|
||||
@ -82,7 +97,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 8
|
||||
"propertyOrder" : 11
|
||||
},
|
||||
"cropTop" :
|
||||
{
|
||||
@ -92,7 +107,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 9
|
||||
"propertyOrder" : 12
|
||||
},
|
||||
"cropBottom" :
|
||||
{
|
||||
@ -102,7 +117,7 @@
|
||||
"default" : 0,
|
||||
"append" : "edt_append_pixel",
|
||||
"required" : true,
|
||||
"propertyOrder" : 10
|
||||
"propertyOrder" : 13
|
||||
},
|
||||
"signalDetection" :
|
||||
{
|
||||
@ -110,7 +125,7 @@
|
||||
"title" : "edt_conf_v4l2_signalDetection_title",
|
||||
"default" : false,
|
||||
"required" : true,
|
||||
"propertyOrder" : 11
|
||||
"propertyOrder" : 14
|
||||
},
|
||||
"redSignalThreshold" :
|
||||
{
|
||||
@ -126,7 +141,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 12
|
||||
"propertyOrder" : 15
|
||||
},
|
||||
"greenSignalThreshold" :
|
||||
{
|
||||
@ -142,7 +157,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 13
|
||||
"propertyOrder" : 16
|
||||
},
|
||||
"blueSignalThreshold" :
|
||||
{
|
||||
@ -158,7 +173,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 14
|
||||
"propertyOrder" : 17
|
||||
},
|
||||
"sDVOffsetMin" :
|
||||
{
|
||||
@ -174,7 +189,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 15
|
||||
"propertyOrder" : 18
|
||||
},
|
||||
"sDVOffsetMax" :
|
||||
{
|
||||
@ -190,7 +205,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 16
|
||||
"propertyOrder" : 19
|
||||
},
|
||||
"sDHOffsetMin" :
|
||||
{
|
||||
@ -206,7 +221,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 17
|
||||
"propertyOrder" : 20
|
||||
},
|
||||
"sDHOffsetMax" :
|
||||
{
|
||||
@ -222,7 +237,7 @@
|
||||
}
|
||||
},
|
||||
"required" : true,
|
||||
"propertyOrder" : 18
|
||||
"propertyOrder" : 21
|
||||
}
|
||||
},
|
||||
"additionalProperties" : true
|
||||
|
@ -138,7 +138,7 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
||||
; // references have already been collected
|
||||
else if (attribute == "title" || attribute == "description" || attribute == "default" || attribute == "format"
|
||||
|| attribute == "defaultProperties" || attribute == "propertyOrder" || attribute == "append" || attribute == "step"
|
||||
|| attribute == "access" || attribute == "options" || attribute == "script" || attribute == "allowEmptyArray")
|
||||
|| attribute == "access" || attribute == "options" || attribute == "script" || attribute == "allowEmptyArray" || attribute == "comment")
|
||||
; // nothing to do.
|
||||
else
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user