-> camera not available background and icon design
-> remove current snapshot GET logs
--> a nice shadow behind the header
-> add a motion running status indicator (and maybe a start/stop button)
-
+-> add a timeout checker to check the running status of motion
-> group @config rules to top
-> browser compatibility test
-> requirements test
+-> style scroll bars
-> hint text next to section titles
-> clickable hints
-> authentication
-> click to zoom on cameras
-> add a previewer for movies
-> add a previewer for snapshots
--> other todos
\ No newline at end of file
+-> other todos
+-> use svg instead of pngs for icons
\ No newline at end of file
import tornado.ioloop
import settings
+
sys.path.append(os.path.join(settings.PROJECT_PATH, 'src'))
+import config
import server
def _start_motion():
- if not motionctl.running():
+ if not motionctl.running() and len(config.get_enabled_cameras()) > 0:
motionctl.start()
logging.info('motion started')
return camera_ids
+def get_enabled_cameras():
+ camera_ids = get_camera_ids()
+ cameras = [get_camera(camera_id) for camera_id in camera_ids]
+ return [c for c in cameras if c['@enabled']]
+
+
def get_camera(camera_id, as_lines=False):
# TODO use a cache
data.setdefault('text_left', '')
data.setdefault('text_right', '')
- data.setdefault('text_double', True)
+ data.setdefault('text_double', False)
data.setdefault('text_changes', False)
data.setdefault('locate', False)
finally:
if restart:
- motionctl.start()
+ if len(config.get_enabled_cameras()) > 0:
+ motionctl.start()
def set_preview(self, camera_id):
try:
# text overlay
'text_left': '',
'text_right': '',
+ 'text_double': False,
# streaming
'webcam_localhost': not ui.get('video_streaming', True),
else:
data['text_right'] = ui.get('custom_right_text', '')
+
+ if data['width'] > 320:
+ data['text_double'] = True
if not ui.get('video_streaming', True):
data['webcam_maxrate'] = 5
data['jpeg_filename'] = ui.get('image_file_name', '%Y-%m-%d-%H-%M-%S-%q')
elif capture_mode == 'interval-snapshots':
- data['snapshot_interval'] = int(ui.get('snapshot_interval'), 300)
+ data['snapshot_interval'] = int(ui.get('snapshot_interval', 300))
data['snapshot_filename'] = ui.get('image_file_name', '%Y-%m-%d-%H-%M-%S-%q')
elif capture_mode == 'all-frames':
'preserve_images': data['@preserve_images'],
# motion movies
- 'motion_movies': False,
- 'movie_quality': 75,
- 'movie_file_name': '%Y-%m-%d-%H-%M-%S-%q',
+ 'motion_movies': data['motion_movies'],
+ 'movie_quality': int((max(2, data['ffmpeg_variable_bitrate']) - 2) / 0.29),
+ 'movie_file_name': data['movie_filename'],
'preserve_movies': data['@preserve_movies'],
-
+
# motion detection
'show_frame_changes': data.get('text_changes') or data.get('locate'),
'frame_change_threshold': data['threshold'],
ui['image_quality'] = ui.get('quality', 75)
- movie_filename = data.get('movie_filename')
- if movie_filename:
- ui['motion_movies'] = True
- ui['movie_quality'] = int((max(2, data['ffmpeg_variable_bitrate']) - 2) / 0.29)
- ui['movie_file_name'] = movie_filename
-
working_schedule = data.get('@working_schedule')
if working_schedule:
days = working_schedule.split('|')
def start():
if running():
raise Exception('motion is already running')
-
+
program = find_program()
if not program:
raise Exception('motion executable could not be found')
div.header {
background-color: rgba(64, 64, 64, 0.5);
+ box-shadow: 0px 0px 5px rgba(0,0,0,0.3);
top: 0px;
width: 100%;
height: 50px;
}
function closeSettings() {
+ hideApply();
+
$('div.settings').removeClass('open');
$('div.page-container').removeClass('stretched');
$('div.settings-top-bar').removeClass('open');
else { /* existing, update params */
cameraFrame[0].framerate = camera.streaming_framerate;
}
-
}
}