From b6e33e057d278b3df0bb37f535b66e9fcaf31e2f Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sat, 14 Mar 2015 20:00:49 +0200 Subject: [PATCH] added support for extra motion options --- src/config.py | 28 ++++++++++++++++++++++++---- static/css/ui.css | 6 +++++- static/js/main.js | 45 ++++++++++++++++++++++++++++++++++++++++++--- templates/main.html | 5 +++++ 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/config.py b/src/config.py index 09a04e0..35420e3 100644 --- a/src/config.py +++ b/src/config.py @@ -797,6 +797,11 @@ def camera_ui_to_dict(ui): continue data['@' + name] = value + + # extra motion options + extra_options = ui.get('extra_options', []) + for name, value in extra_options: + data[name] = value or '' return data @@ -1119,6 +1124,22 @@ def camera_dict_to_ui(data): continue ui[name[1:]] = value + + # extra motion options + known_options = set([ + 'auto_brightness', 'brightness', 'contrast', 'emulate_motion', 'event_gap', 'ffmpeg_bps', 'ffmpeg_output_movies', 'ffmpeg_variable_bitrate', 'ffmpeg_video_codec', + 'framerate', 'height', 'hue', 'lightswitch', 'locate_motion_mode', 'locate_motion_style', 'minimum_motion_frames', 'movie_filename', 'noise_level', 'noise_tune', + 'on_event_end', 'on_event_start', 'output_pictures', 'picture_filename', 'post_capture', 'pre_capture', 'quality', 'rotate', 'saturation', + 'snapshot_filename', 'snapshot_interval', 'stream_auth_method', 'stream_authentication', 'stream_localhost', 'stream_maxrate', 'stream_motion', 'stream_port', 'stream_quality', + 'target_dir', 'text_changes', 'text_double', 'text_left', 'text_right', 'threshold', 'videodevice', 'width' + ]) + + extra_options = [] + for name, value in data.iteritems(): + if name not in known_options and not name.startswith('@'): + extra_options.append((name, value)) + + ui['extra_options'] = extra_options return ui @@ -1252,10 +1273,9 @@ def _dict_to_conf(lines, data, list_names=[]): new_value = data.get(name) if new_value is not None: value = _python_to_value(new_value) - - line = name + ' ' + value - conf_lines.append(line) - + line = name + ' ' + value + conf_lines.append(line) + remaining.pop(name, None) # add the remaining config values not covered by existing lines diff --git a/static/css/ui.css b/static/css/ui.css index 1da69b9..823f74b 100644 --- a/static/css/ui.css +++ b/static/css/ui.css @@ -130,7 +130,9 @@ div.check-box.on:HOVER div.check-box-button { /* input box */ input[type=password].styled, -input[type=text].styled { +input[type=text].styled, +textarea.styled, +[contenteditable=true].styled { width: 90%; border: 1px solid #317CAD; border-radius: 2px; @@ -141,6 +143,8 @@ input[type=text].styled { font-size: 0.8em; margin: 2px; transition: all 0.1s ease; + resize: none; + vertical-align: middle; } input[type=password].styled:FOCUS, diff --git a/static/js/main.js b/static/js/main.js index a3015ed..8e320d4 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -541,6 +541,19 @@ function initUI() { }, ''); }); + /* implement change events for [contenteditable=true] elements */ + $('[contenteditable=true]').each(function () { + var $this = $(this); + $this.focus(function () { + $this.data('val', $this.html()); + }); + $this.blur(function () { + if ($this.html() != $this.data('val')) { + $this.change(); + } + }); + }); + /* input value processors */ makeStrippedInput($('tr[strip=true] input[type=text]')); makeStrippedInput($('tr[strip=true] input[type=password]')); @@ -657,8 +670,8 @@ function initUI() { fetchCurrentCameraConfig(endProgress); } }); - $('input.main-config, select.main-config').change(pushMainConfig); - $('input.camera-config, select.camera-config').change(pushCameraConfig); + $('input.main-config, select.main-config, div[contenteditable=true].main-config').change(pushMainConfig); + $('input.camera-config, select.camera-config, div[contenteditable=true].camera-config').change(pushCameraConfig); /* preview controls */ $('#brightnessSlider').change(function () {pushPreview('brightness');}); @@ -1131,7 +1144,30 @@ function cameraUi2Dict() { 'uri': $('#deviceEntry')[0].uri, 'username': $('#deviceEntry')[0].username, 'password': $('#deviceEntry')[0].password, - + 'extra_options': $('#extraOptionsEntry').html().split(new RegExp('(]*>)|(
)|(

)')).map(function (o) { + if (!o) { + return null; + } + + o = o.replace(new RegExp('(<([^>]+)>)', 'ig'), ''); /* remove crappy HTML tags added by the browser */ + o = o.replace(new RegExp('&\\w+;', 'ig'), ''); /* remove crappy HTML entities added by the browser */ + o = o.trim(); + if (!o.length) { + return null; + } + + var parts = o.replace(new RegExp('\\s+', 'g'), ' ').split(' '); + if (parts.length < 2) { + return [parts[0], '']; + } + else if (parts.length == 2) { + return parts; + } + else { + return [parts[0], parts.slice(1).join(' ')]; + } + }).filter(function (e) {return e;}), + /* file storage */ 'storage_device': $('#storageDeviceSelect').val(), 'network_server': $('#networkServerEntry').val(), @@ -1342,6 +1378,9 @@ function dict2CameraUi(dict) { $('#rotationSelect').val(dict['rotation']); $('#framerateSlider').val(dict['framerate']); + $('#extraOptionsEntry').html(dict['extra_options'].map(function (o) { + return o.join(' '); + }).join('
')); /* file storage */ $('#storageDeviceSelect').empty(); diff --git a/templates/main.html b/templates/main.html index a18e4a4..dbc3f3a 100644 --- a/templates/main.html +++ b/templates/main.html @@ -249,6 +249,11 @@ ? + + Extra Motion Options +

+ ? + {% for config in camera_sections.get('device', {}).get('configs', []) %} {{config_item(config)}} {% endfor %} -- 2.39.5