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
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
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
/* 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;
font-size: 0.8em;
margin: 2px;
transition: all 0.1s ease;
+ resize: none;
+ vertical-align: middle;
}
input[type=password].styled:FOCUS,
}, '');
});
+ /* 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]'));
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');});
'uri': $('#deviceEntry')[0].uri,
'username': $('#deviceEntry')[0].username,
'password': $('#deviceEntry')[0].password,
-
+ 'extra_options': $('#extraOptionsEntry').html().split(new RegExp('(<br[^>]*>)|(<div>)|(<p>)')).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(),
$('#rotationSelect').val(dict['rotation']);
$('#framerateSlider').val(dict['framerate']);
+ $('#extraOptionsEntry').html(dict['extra_options'].map(function (o) {
+ return o.join(' ');
+ }).join('<br>'));
/* file storage */
$('#storageDeviceSelect').empty();
<td class="settings-item-value"><input type="text" class="range styled device camera-config" id="framerateSlider"></td>
<td><span class="help-mark" title="sets the number of frames captured by the camera every second (higher values produce smoother videos but require larger storage space and bandwidth)">?</span></td>
</tr>
+ <tr class="settings-item advanced-setting">
+ <td class="settings-item-label"><span class="settings-item-label">Extra Motion Options</span></td>
+ <td class="settings-item-value"><div class="styled device camera-config" id="extraOptionsEntry" contenteditable="true"></div></td>
+ <td><span class="help-mark" title="you can add here any extra options for the motion daemon (use the "name value" format, one option per line)">?</span></td>
+ </tr>
{% for config in camera_sections.get('device', {}).get('configs', []) %}
{{config_item(config)}}
{% endfor %}