From a862509fa816049d1fa6d7da1712b2a6c5e34519 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sat, 11 Jan 2014 17:31:24 +0200 Subject: [PATCH] camera controls are set now individually rather than all at once --- src/config.py | 26 +++---- static/css/main.css | 17 ++++- static/css/ui.css | 14 ++-- static/js/main.js | 160 ++++++++++++++++++++------------------------ templates/main.html | 5 +- 5 files changed, 112 insertions(+), 110 deletions(-) diff --git a/src/config.py b/src/config.py index 3d894be..1bcbcf3 100644 --- a/src/config.py +++ b/src/config.py @@ -28,9 +28,7 @@ import v4l2ctl _CAMERA_CONFIG_FILE_NAME = 'thread-%(id)s.conf' - -_MAIN_CONFIG_FILE_PATH = os.path.join(settings.CONF_PATH, 'motion.conf') -_CAMERA_CONFIG_FILE_PATH = os.path.join(settings.CONF_PATH, _CAMERA_CONFIG_FILE_NAME) +_MAIN_CONFIG_FILE_NAME = 'motion.conf' _main_config_cache = None _camera_config_cache = None @@ -43,7 +41,7 @@ def get_main(as_lines=False): if not as_lines and _main_config_cache is not None: return _main_config_cache - config_file_path = os.path.join(settings.PROJECT_PATH, _MAIN_CONFIG_FILE_PATH) + config_file_path = os.path.join(settings.CONF_PATH, _MAIN_CONFIG_FILE_NAME) logging.debug('reading main config from file %(path)s...' % {'path': config_file_path}) @@ -69,7 +67,7 @@ def get_main(as_lines=False): except Exception as e: logging.error('could not read main config file %(path)s: %(msg)s' % { - 'path': _MAIN_CONFIG_FILE_PATH, 'msg': unicode(e)}) + 'path': config_file_path, 'msg': unicode(e)}) raise @@ -92,6 +90,8 @@ def set_main(data): _set_default_motion(data) + config_file_path = os.path.join(settings.CONF_PATH, _MAIN_CONFIG_FILE_NAME) + # read the actual configuration from file lines = get_main(as_lines=True) @@ -104,14 +104,14 @@ def set_main(data): threads.append(match.groups()[0]) # write the configuration to file - logging.debug('writing main config to %(path)s...' % {'path': _MAIN_CONFIG_FILE_PATH}) + logging.debug('writing main config to %(path)s...' % {'path': config_file_path}) try: - file = open(_MAIN_CONFIG_FILE_PATH, 'w') + file = open(config_file_path, 'w') except Exception as e: logging.error('could not open main config file %(path)s for writing: %(msg)s' % { - 'path': _MAIN_CONFIG_FILE_PATH, 'msg': unicode(e)}) + 'path': config_file_path, 'msg': unicode(e)}) raise @@ -122,7 +122,7 @@ def set_main(data): except Exception as e: logging.error('could not write main config file %(path)s: %(msg)s' % { - 'path': _MAIN_CONFIG_FILE_PATH, 'msg': unicode(e)}) + 'path': config_file_path, 'msg': unicode(e)}) raise @@ -187,7 +187,7 @@ def get_camera(camera_id, as_lines=False): if not as_lines and _camera_config_cache is not None and camera_id in _camera_config_cache: return _camera_config_cache[camera_id] - camera_config_path = _CAMERA_CONFIG_FILE_PATH % {'id': camera_id} + camera_config_path = os.path.join(settings.CONF_PATH, _CAMERA_CONFIG_FILE_NAME) % {'id': camera_id} logging.debug('reading camera config from %(path)s...' % {'path': camera_config_path}) @@ -266,7 +266,7 @@ def set_camera(camera_id, data): logging.warn('failed to create target directory: %(msg)s' % {'msg': unicode(e)}) # read the actual configuration from file - config_file_path = _CAMERA_CONFIG_FILE_PATH % {'id': camera_id} + config_file_path = os.path.join(settings.CONF_PATH, _CAMERA_CONFIG_FILE_NAME) % {'id': camera_id} if os.path.isfile(config_file_path): lines = get_camera(camera_id, as_lines=True) @@ -274,7 +274,7 @@ def set_camera(camera_id, data): lines = [] # write the configuration to file - camera_config_path = _CAMERA_CONFIG_FILE_PATH % {'id': camera_id} + camera_config_path = os.path.join(settings.CONF_PATH, _CAMERA_CONFIG_FILE_NAME) % {'id': camera_id} logging.debug('writing camera config to %(path)s...' % {'path': camera_config_path}) try: @@ -358,7 +358,7 @@ def rem_camera(camera_id): global _camera_config_cache camera_config_name = _CAMERA_CONFIG_FILE_NAME % {'id': camera_id} - camera_config_path = _CAMERA_CONFIG_FILE_PATH % {'id': camera_id} + camera_config_path = os.path.join(settings.CONF_PATH, _CAMERA_CONFIG_FILE_NAME) % {'id': camera_id} # remove the camera from the main config main_config = get_main() diff --git a/static/css/main.css b/static/css/main.css index 8471257..6d14543 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -176,6 +176,7 @@ div.settings.open { } div.settings-container { + position: relative; padding-top: 10px; display: none; white-space: nowrap; @@ -185,6 +186,17 @@ div.settings.open div.settings-container { display: block; } +div.settings-progress { + position: absolute; + top: 0px; + width: 0px; + bottom: 0px; + left: 0px; + background-color: #313131; + opacity: 0; + transition: opacity 0.1s linear; +} + div.settings-top-bar { position: relative; display: inline-block; @@ -197,6 +209,10 @@ div.settings-top-bar.open { min-width: 360px; } +div.settings-top-bar.closed div.apply-button { + display: none !important; +} + div.settings-section-title { position: relative; text-align: right; @@ -261,7 +277,6 @@ div.apply-button { background-color: #FF6F00; border-radius: 3px; transition: all 0.1s linear; - transition: opacity 0s; } div.apply-button:HOVER { diff --git a/static/css/ui.css b/static/css/ui.css index 6b55a69..ac5a54f 100644 --- a/static/css/ui.css +++ b/static/css/ui.css @@ -1,16 +1,16 @@ /* general */ -::selection { - background: #3498db; -} - -::-moz-selection { +::selection, +::-moz-selection, +::-webkit-selection { background: #3498db; } -::-webkit-selection { - background: #3498db; +option::selection, +option::-moz-selection, +option::-webkit-selection { + background: transparent; } input[type=checkbox].styled { diff --git a/static/js/main.js b/static/js/main.js index c6c95fd..dc383b0 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -3,6 +3,7 @@ var pushConfigs = {}; var refreshDisabled = 0; var fullScreenCameraId = null; var thresholdSlider = null; +var inProgress = false; /* utils */ @@ -250,7 +251,8 @@ function initUI() { updateConfigUi(); } else { - fetchCurrentCameraConfig(); + showProgress(); + fetchCurrentCameraConfig(endProgress); } }); $('input.general').change(pushMainConfig); @@ -265,10 +267,10 @@ function initUI() { 'input.working-schedule, select.working-schedule').change(pushCameraConfig); /* preview controls */ - $('#brightnessSlider').change(pushPreview); - $('#contrastSlider').change(pushPreview); - $('#saturationSlider').change(pushPreview); - $('#hueSlider').change(pushPreview); + $('#brightnessSlider').change(function () {pushPreview('brightness');}); + $('#contrastSlider').change(function () {pushPreview('contrast');}); + $('#saturationSlider').change(function () {pushPreview('saturation');}); + $('#hueSlider').change(function () {pushPreview('hue');}); /* apply button */ $('#applyButton').click(function () { @@ -295,9 +297,9 @@ function openSettings(cameraId) { $('#videoDeviceSelect').val(cameraId).change(); } - $('div.settings').addClass('open'); + $('div.settings').addClass('open').removeClass('closed'); $('div.page-container').addClass('stretched'); - $('div.settings-top-bar').addClass('open'); + $('div.settings-top-bar').addClass('open').removeClass('closed'); updateConfigUi(); } @@ -305,9 +307,9 @@ function openSettings(cameraId) { function closeSettings() { hideApply(); - $('div.settings').removeClass('open'); + $('div.settings').removeClass('open').addClass('closed'); $('div.page-container').removeClass('stretched'); - $('div.settings-top-bar').removeClass('open'); + $('div.settings-top-bar').removeClass('open').addClass('closed'); } function isSettingsOpen() { @@ -712,59 +714,60 @@ function dict2CameraUi(dict) { /* apply button */ function showApply() { - if (!$('div.settings-container').is(':visible')) { - return; /* settings panel is not open */ - } - var applyButton = $('#applyButton'); applyButton.html('Apply'); applyButton.css('display', 'inline-block'); - applyButton.animate({'opacity': '1'}, 100); applyButton.removeClass('progress'); + setTimeout(function () { + applyButton.css('opacity', '1'); + }, 10); } function showProgress() { + if (inProgress) { + return; /* already in progress */ + } + + inProgress = true; refreshDisabled++; /* replace the main page message with a progress indicator */ $('div.add-camera-message').html(''); - if (!$('div.settings-container').is(':visible')) { - return; /* settings panel is not open */ - } - - var applyButton = $('#applyButton'); - - if (applyButton.hasClass('progress')) { - return; /* progress already visible */ - } - - applyButton.html(''); - applyButton.css('display', 'inline-block'); - applyButton.animate({'opacity': '1'}, 100); - applyButton.addClass('progress'); + /* show the apply button progress indicator */ + $('#applyButton').html(''); + /* show the camera progress indicators */ $('div.camera-progress').css('opacity', '0.5'); + + /* remove the settings progress lock */ + $('div.settings-progress').css('width', '100%').css('opacity', '0.9'); } function hideApply() { - if (!$('div.settings-container').is(':visible')) { - return; /* settings panel is not open */ - } - var applyButton = $('#applyButton'); - applyButton.animate({'opacity': '0'}, 100, function () { - applyButton.removeClass('progress'); + applyButton.css('opacity', '0'); + applyButton.removeClass('progress'); + + setTimeout(function () { applyButton.css('display', 'none'); - }); + }, 500); } function endProgress() { + if (!inProgress) { + return; /* not in progress */ + } + + inProgress = false; refreshDisabled--; - $('div.add-camera-message').remove(); /* remove any existing message on the main page */ + /* remove any existing message on the main page */ + $('div.add-camera-message').remove(); + + /* deal with the apply button */ if (Object.keys(pushConfigs).length === 0) { hideApply(); } @@ -772,13 +775,15 @@ function endProgress() { showApply(); } + /* hide the settings progress lock */ + $('div.settings-progress').css('opacity', '0'); + + /* hide the camera progress indicator */ $('div.camera-progress').css('opacity', '0'); -} -function isProgress() { - var applyButton = $('#applyButton'); - - return applyButton.hasClass('progress'); + setTimeout(function () { + $('div.settings-progress').css('width', '0px'); + }, 500); } function isApplyVisible() { @@ -840,7 +845,7 @@ function doRemCamera() { var deviceName = $('#videoDeviceSelect').find('option[value=' + cameraId + ']').text(); - runConfirmDialog('Remove device ' + deviceName + '?', function () { + runConfirmDialog('Remove camera ' + deviceName + '?', function () { showProgress(); ajax('POST', '/config/' + cameraId + '/rem/', null, function (data) { if (data == null || data.error) { @@ -849,8 +854,7 @@ function doRemCamera() { return; } - endProgress(); - fetchCurrentConfig(); + fetchCurrentConfig(endProgress); }); }); } @@ -892,13 +896,16 @@ function doUpdate() { /* fetch & push */ -function fetchCurrentConfig() { +function fetchCurrentConfig(onFetch) { function fetchCameraList() { /* fetch the camera list */ ajax('GET', '/config/list/', null, function (data) { if (data == null || data.error) { showErrorMessage(data && data.error); data = {cameras: []}; + if (onFetch) { + onFetch(null); + } } var i, cameras = data.cameras; @@ -933,6 +940,10 @@ function fetchCurrentConfig() { else { recreateCameraFrames(cameras); } + + if (onFetch) { + onFetch(data); + } }); } @@ -953,17 +964,23 @@ function fetchCurrentConfig() { } } -function fetchCurrentCameraConfig() { +function fetchCurrentCameraConfig(onFetch) { var cameraId = $('#videoDeviceSelect').val(); if (cameraId != null) { ajax('GET', '/config/' + cameraId + '/get/', null, function (data) { if (data == null || data.error) { showErrorMessage(data && data.error); dict2CameraUi(null); + if (onFetch) { + onFetch(null); + } return; } dict2CameraUi(data); + if (onFetch) { + onFetch(data); + } }); } else { @@ -990,8 +1007,9 @@ function pushCameraConfig() { } } -function pushPreview() { +function pushPreview(control) { var cameraId = $('#videoDeviceSelect').val(); + var brightness = $('#brightnessSlider').val(); var contrast= $('#contrastSlider').val(); var saturation = $('#saturationSlider').val(); @@ -999,19 +1017,19 @@ function pushPreview() { var data = {}; - if (brightness !== '') { + if (brightness !== '' && (!control || control == 'brightness')) { data.brightness = brightness; } - if (contrast !== '') { + if (contrast !== '' && (!control || control == 'contrast')) { data.contrast = contrast; } - if (saturation !== '') { + if (saturation !== '' && (!control || control == 'saturation')) { data.saturation = saturation; } - if (hue !== '') { + if (hue !== '' && (!control || control == 'hue')) { data.hue = hue; } @@ -1756,48 +1774,15 @@ function recreateCameraFrames(cameras) { function doConfigureCamera(cameraId) { - if (isProgress()) { + if (inProgress) { return; } openSettings(cameraId); } - /* not used anymore */ -function doCloseCamera(cameraId) { - if (isProgress()) { - return; - } - - remCameraFrameUi(cameraId); - showProgress(); - ajax('GET', '/config/' + cameraId + '/get/', null, function (data) { - if (data == null || data.error) { - endProgress(); - showErrorMessage(data && data.error); - return; - } - - data['enabled'] = false; - ajax('POST', '/config/' + cameraId + '/set/', data, function (data) { - if (data == null || data.error) { - showErrorMessage(data && data.error); - return; - } - - endProgress(); - - /* if the current camera in the settings panel is the closed camera, - * we refresh its settings and update the UI */ - if ($('#videoDeviceSelect').val() === '' + cameraId) { - fetchCurrentCameraConfig(); - } - }); - }); -} - function doFullScreenCamera(cameraId) { - if (isProgress()) { + if (inProgress) { return; } @@ -1947,7 +1932,8 @@ $(document).ready(function () { }); initUI(); - fetchCurrentConfig(); + showProgress(); + fetchCurrentConfig(endProgress); refreshCameraFrames(); checkCameraErrors(); }); diff --git a/templates/main.html b/templates/main.html index b5abb87..e90128f 100644 --- a/templates/main.html +++ b/templates/main.html @@ -16,7 +16,7 @@
{% if USER == 'admin' %} -
+
@@ -33,7 +33,7 @@
{% if USER == 'admin' %} -
+
General Settings
@@ -447,6 +447,7 @@
?
+
-- 2.39.5