@@ -348,7 +348,7 @@ $(document).ready(function () {
348348 updateJsonEditorRange ( conf_editor_video , "root.grabberV4L2" , key ,
349349 properties . minValue ,
350350 properties . maxValue ,
351- properties . current ,
351+ properties . default ,
352352 properties . step ,
353353 true ) ;
354354
@@ -411,73 +411,84 @@ $(document).ready(function () {
411411 } ) ;
412412
413413 conf_editor_video . watch ( 'root.grabberV4L2.available_devices' , ( ) => {
414- var deviceSelected = conf_editor_video . getEditor ( "root.grabberV4L2.available_devices" ) . getValue ( ) ;
415- if ( deviceSelected === "SELECT" || deviceSelected === "NONE" || deviceSelected === "" ) {
414+ const editor = conf_editor_video . getEditor ( "root.grabberV4L2.available_devices" ) ;
415+ const deviceSelected = editor . getValue ( ) ;
416+ const invalidSelections = [ "SELECT" , "NONE" , "" ] ;
417+
418+ if ( invalidSelections . includes ( deviceSelected ) ) {
416419 $ ( '#btn_submit_videograbber' ) . prop ( 'disabled' , true ) ;
417420 showInputOptionsForKey ( conf_editor_video , "grabberV4L2" , [ "enable" , "available_devices" ] , false ) ;
421+ return ;
418422 }
419- else {
420- showInputOptionsForKey ( conf_editor_video , "grabberV4L2" , [ "enable" , "available_devices" ] , true ) ;
421- var addSchemaElements = { } ;
422- var enumVals = [ ] ;
423- var enumTitelVals = [ ] ;
424- var enumDefaultVal = "" ;
425423
426- var deviceProperties = getPropertiesOfDevice ( "video" , deviceSelected ) ;
424+ showInputOptionsForKey ( conf_editor_video , "grabberV4L2" , [ "enable" , "available_devices" ] , true ) ;
427425
428- //Update hidden input element
429- conf_editor_video . getEditor ( "root.grabberV4L2.device" ) . setValue ( deviceProperties . device ) ;
426+ const deviceProperties = getPropertiesOfDevice ( "video" , deviceSelected ) ;
427+ conf_editor_video . getEditor ( "root.grabberV4L2.device" ) . setValue ( deviceProperties . device ) ;
430428
431- if ( deviceProperties . hasOwnProperty ( 'default' ) && ! jQuery . isEmptyObject ( deviceProperties . default . properties ) ) {
432- $ ( '#btn_videograbber_set_defaults' ) . prop ( 'disabled' , false ) ;
433- } else {
434- $ ( '#btn_videograbber_set_defaults' ) . prop ( 'disabled' , true ) ;
435- }
429+ const defaultProperties = deviceProperties . default ?. properties ?? { } ;
430+ const hasDefaults = Object . keys ( defaultProperties ) . length > 0 ;
431+ $ ( '#btn_videograbber_set_defaults' ) . prop ( 'disabled' , ! hasDefaults ) ;
436432
437- //If configured device is selected, use the saved values as current values
438- if ( deviceSelected === configuredDevice ) {
439- // Only if the device reported properties, use the configured values. In case no properties are presented, the device properties cannot be controlled.
440- if ( deviceProperties . hasOwnProperty ( 'properties' ) && ! jQuery . isEmptyObject ( deviceProperties . properties ) ) {
441- let properties = {
442- brightness : { current : window . serverConfig . grabberV4L2 . hardware_brightness } ,
443- contrast : { current : window . serverConfig . grabberV4L2 . hardware_contrast } ,
444- saturation : { current : window . serverConfig . grabberV4L2 . hardware_saturation } ,
445- hue : { current : window . serverConfig . grabberV4L2 . hardware_hue }
446- } ;
447- deviceProperties . properties = properties ;
448- }
449- }
433+ const isConfiguredDevice = ( deviceSelected === configuredDevice ) ;
434+ const { grabberV4L2 } = window . serverConfig ;
435+ const currentProps = deviceProperties . properties ;
450436
451- updateDeviceProperties ( deviceProperties . properties , "brightness" , "hardware_brightness" ) ;
452- updateDeviceProperties ( deviceProperties . properties , "contrast" , "hardware_contrast" ) ;
453- updateDeviceProperties ( deviceProperties . properties , "saturation" , "hardware_saturation" ) ;
454- updateDeviceProperties ( deviceProperties . properties , "hue" , "hardware_hue" ) ;
437+ const propMappings = {
438+ brightness : 'hardware_brightness' ,
439+ contrast : 'hardware_contrast' ,
440+ saturation : 'hardware_saturation' ,
441+ hue : 'hardware_hue'
442+ } ;
455443
456- var video_inputs = deviceProperties . video_inputs ;
457- if ( video_inputs . length <= 1 ) {
458- addSchemaElements . access = "expert" ;
444+ for ( const prop in propMappings ) {
445+ if ( hasDefaults ) {
446+ currentProps [ prop ] . default = defaultProperties [ prop ] ;
459447 }
448+ // Ensure min,max and step values are set inline with the selected grabber to ensure valid input
449+ updateDeviceProperties ( currentProps , prop , [ propMappings [ prop ] ] ) ;
460450
461- for ( const video_input of video_inputs ) {
462- enumVals . push ( video_input . inputIdx . toString ( ) ) ;
463- enumTitelVals . push ( video_input . name ) ;
451+ let currentValue = 0 ;
452+ if ( isConfiguredDevice ) {
453+ currentValue = window . serverConfig . grabberV4L2 [ propMappings [ prop ] ] ;
454+ } else if ( hasDefaults ) {
455+ currentValue = currentProps . default ;
464456 }
465457
466- if ( enumVals . length > 0 ) {
467- if ( deviceSelected === configuredDevice ) {
468- var configuredVideoInput = window . serverConfig . grabberV4L2 . input . toString ( ) ;
469- if ( $ . inArray ( configuredVideoInput , enumVals ) != - 1 ) {
470- enumDefaultVal = configuredVideoInput ;
471- }
472- }
473-
474- updateJsonEditorSelection ( conf_editor_video , 'root.grabberV4L2' ,
475- 'device_inputs' , addSchemaElements , enumVals , enumTitelVals , enumDefaultVal , false , false ) ;
458+ if ( currentValue !== undefined ) {
459+ conf_editor_video . getEditor ( "root.grabberV4L2." + propMappings [ prop ] ) . setValue ( currentValue ) ;
476460 }
461+ }
477462
478- if ( conf_editor_video . validate ( ) . length && ! window . readOnlyMode ) {
479- $ ( '#btn_submit_videograbber' ) . prop ( 'disabled' , false ) ;
463+ const { video_inputs = [ ] } = deviceProperties ;
464+
465+ const addSchemaElements = { } ;
466+
467+ if ( video_inputs . length <= 1 ) {
468+ addSchemaElements . access = "expert" ;
469+ }
470+
471+ const enumVals = video_inputs . map ( input => input . inputIdx . toString ( ) ) ;
472+ const enumTitelVals = video_inputs . map ( input => input . name ) ;
473+
474+ if ( enumVals . length > 0 ) {
475+ let enumDefaultVal = "" ;
476+ if ( isConfiguredDevice ) {
477+ const configuredInput = grabberV4L2 . input . toString ( ) ;
478+ if ( enumVals . includes ( configuredInput ) ) {
479+ enumDefaultVal = configuredInput ;
480+ }
480481 }
482+
483+ updateJsonEditorSelection (
484+ conf_editor_video , 'root.grabberV4L2' , 'device_inputs' ,
485+ addSchemaElements , enumVals , enumTitelVals , enumDefaultVal , false , false
486+ ) ;
487+ }
488+
489+ const isValid = conf_editor_video . validate ( ) . length === 0 ;
490+ if ( isValid && ! window . readOnlyMode ) {
491+ $ ( '#btn_submit_videograbber' ) . prop ( 'disabled' , false ) ;
481492 }
482493 } ) ;
483494
@@ -983,14 +994,16 @@ $(document).ready(function () {
983994 }
984995
985996 function getPropertiesOfDevice ( type , deviceName ) {
986- deviceProperties = { } ;
987- for ( const deviceRecord of discoveredInputSources [ type ] ) {
997+ let props = { } ;
998+ const sourceList = discoveredInputSources [ type ] || [ ] ;
999+ for ( const deviceRecord of sourceList ) {
9881000 if ( deviceRecord . device_name === deviceName ) {
989- deviceProperties = deviceRecord ;
1001+ // Deep copy to prevent modifying the original object in discoveredInputSources
1002+ props = structuredClone ( deviceRecord ) ;
9901003 break ;
9911004 }
9921005 }
993- return deviceProperties ;
1006+ return props ;
9941007 }
9951008
9961009} ) ;
0 commit comments