]> www.vanbest.org Git - motioneye-debian/commitdiff
an intial working version of simple mjpeg camera
authorCalin Crisan <ccrisan@gmail.com>
Sat, 16 May 2015 13:35:37 +0000 (16:35 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Sat, 16 May 2015 13:35:37 +0000 (16:35 +0300)
src/config.py
src/handlers.py
static/js/frame.js
static/js/main.js
templates/main.html

index 0a63012a77b89c6cf0b4fcd755d2fd6aff2d2216..e3a098620d61f97c5339fccd3419a8ba3e26c16c 100644 (file)
@@ -489,6 +489,7 @@ def add_camera(device_details):
     else: # assuming mjpeg
         camera_config['@proto'] = 'mjpeg'
         camera_config['@url'] = device_details['url']
+        _set_default_simple_mjpeg_camera(camera_id, camera_config)
 
     # write the configuration to file
     set_camera(camera_id, camera_config)
@@ -574,7 +575,7 @@ def main_dict_to_ui(data):
     return ui
 
 
-def camera_ui_to_dict(ui, old_config=None):
+def motion_camera_ui_to_dict(ui, old_config=None):
     old_config = dict(old_config or {})
     main_config = get_main() # needed for surveillance password
 
@@ -849,7 +850,7 @@ def camera_ui_to_dict(ui, old_config=None):
     return old_config
 
 
-def camera_dict_to_ui(data):
+def motion_camera_dict_to_ui(data):
     ui = {
         # device
         'name': data['@name'],
@@ -1162,6 +1163,32 @@ def camera_dict_to_ui(data):
     return ui
 
 
+def simple_mjpeg_camera_ui_to_dict(ui, old_config=None):
+    old_config = dict(old_config or {})
+
+    data = {
+        # device
+        '@name': ui['name'],
+        '@enabled': ui['enabled'],
+    }
+    
+    old_config.update(data)
+
+    return old_config
+
+
+def simple_mjpeg_camera_dict_to_ui(data):
+    ui = {
+        'name': data['@name'],
+        'enabled': data['@enabled'],
+        'id': data['@id'],
+        'proto': 'mjpeg',
+        'url': data['@url']
+    }
+    
+    return ui
+
+
 def backup():
     logging.debug('generating config backup file')
 
@@ -1545,6 +1572,12 @@ def _set_default_motion_camera(camera_id, data, old_motion=False):
     data.setdefault('on_event_end', '')
 
 
+def _set_default_simple_mjpeg_camera(camera_id, data):
+    data.setdefault('@name', 'Camera' + str(camera_id))
+    data.setdefault('@enabled', False)
+    data.setdefault('@id', camera_id)
+
+    
 def get_additional_structure(camera, separators=False):
     if _additional_structure_cache.get((camera, separators)) is None:
         logging.debug('loading additional config structure for %s' % ('camera' if camera else 'main'))
index 0a7aee129d9dc9561135f26c97cf821b1d9ba1d5..d05dcbaa30e6e7132ee25e6bc2b74174bad1898f 100644 (file)
@@ -216,7 +216,7 @@ class ConfigHandler(BaseHandler):
             
             local_config = config.get_camera(camera_id)
             if utils.local_motion_camera(local_config):
-                ui_config = config.camera_dict_to_ui(local_config)
+                ui_config = config.motion_camera_dict_to_ui(local_config)
                     
                 self.finish_json(ui_config)
             
@@ -236,7 +236,9 @@ class ConfigHandler(BaseHandler):
                 remote.get_config(local_config, on_response)
                 
             else: # assuming simple mjpeg camera
-                pass # TODO implement me
+                ui_config = config.simple_mjpeg_camera_dict_to_ui(local_config)
+                    
+                self.finish_json(ui_config)
             
         else:
             logging.debug('getting main config')
@@ -264,7 +266,7 @@ class ConfigHandler(BaseHandler):
             
             local_config = config.get_camera(camera_id)
             if utils.local_motion_camera(local_config):
-                local_config = config.camera_ui_to_dict(ui_config, local_config)
+                local_config = config.motion_camera_ui_to_dict(ui_config, local_config)
 
                 config.set_camera(camera_id, local_config)
             
@@ -289,7 +291,11 @@ class ConfigHandler(BaseHandler):
                     on_finish(None, False)
                     
             else: # assuming simple mjpeg camera
-                pass # TODO implement me
+                local_config = config.simple_mjpeg_camera_ui_to_dict(ui_config, local_config)
+
+                config.set_camera(camera_id, local_config)
+            
+                on_finish(None, False) # (no error, motion doesn't need restart)
 
         def set_main_config(ui_config):
             logging.debug('setting main config...')
@@ -327,8 +333,8 @@ class ConfigHandler(BaseHandler):
                     if not utils.local_motion_camera(local_config):
                         continue
                     
-                    ui_config = config.camera_dict_to_ui(local_config)
-                    local_config = config.camera_ui_to_dict(ui_config, local_config)
+                    ui_config = config.motion_camera_dict_to_ui(local_config)
+                    local_config = config.motion_camera_ui_to_dict(ui_config, local_config)
 
                     config.set_camera(camera_id, local_config)
                     
@@ -564,7 +570,7 @@ class ConfigHandler(BaseHandler):
                     continue
                 
                 if utils.local_motion_camera(local_config):
-                    ui_config = config.camera_dict_to_ui(local_config)
+                    ui_config = config.motion_camera_dict_to_ui(local_config)
                     cameras.append(ui_config)
                     check_finished()
 
@@ -576,7 +582,9 @@ class ConfigHandler(BaseHandler):
                         on_response_builder(camera_id, local_config)(error=True)
                         
                 else: # assuming simple mjpeg camera
-                    pass # TODO implement me
+                    ui_config = config.simple_mjpeg_camera_dict_to_ui(local_config)
+                    cameras.append(ui_config)
+                    check_finished()
             
             if length[0] == 0:        
                 self.finish_json({'cameras': []})
@@ -622,7 +630,7 @@ class ConfigHandler(BaseHandler):
             else:
                 motionctl.start()
             
-            ui_config = config.camera_dict_to_ui(camera_config)
+            ui_config = config.motion_camera_dict_to_ui(camera_config)
             
             self.finish_json(ui_config)
         
@@ -639,8 +647,8 @@ class ConfigHandler(BaseHandler):
             remote.get_config(camera_config, on_response)
         
         else: # assuming simple mjpeg camera
-            #ui_config = config.camera_dict_to_ui(camera_config)
-            # TODO use a special mjpeg function to generate ui_config
+            ui_config = config.simple_mjpeg_camera_dict_to_ui(camera_config)
+            
             self.finish_json(ui_config)
     
     @BaseHandler.auth(admin=True)
@@ -837,7 +845,7 @@ class PictureHandler(BaseHandler):
     def frame(self, camera_id):
         camera_config = config.get_camera(camera_id)
         
-        if utils.local_motion_camera(camera_config) or self.get_argument('title', None) is not None:
+        if utils.local_motion_camera(camera_config) or utils.simple_mjpeg_camera(camera_config) or self.get_argument('title', None) is not None:
             self.render('main.html',
                     frame=True,
                     camera_id=camera_id,
@@ -854,9 +862,9 @@ class PictureHandler(BaseHandler):
                             camera_config=camera_config,
                             title=self.get_argument('title', ''))
 
-                # issue a fake camera_ui_to_dict() call to transform
+                # issue a fake motion_camera_ui_to_dict() call to transform
                 # the remote UI values into motion config directives
-                remote_config = config.camera_ui_to_dict(remote_ui_config)
+                remote_config = config.motion_camera_ui_to_dict(remote_ui_config)
                 
                 self.render('main.html',
                         frame=True,
@@ -867,9 +875,6 @@ class PictureHandler(BaseHandler):
 
             remote.get_config(camera_config, on_response)
         
-        else: # assuming simple mjpeg camera
-            pass # TODO implement me
-
     @BaseHandler.auth()
     def download(self, camera_id, filename):
         logging.debug('downloading picture %(filename)s of camera %(id)s' % {
index 3d77c514859e7aca131efce8d91ee75541c7a03f..86209228fd175f1f4c9ce338ad9287536757e6b2 100644 (file)
@@ -16,6 +16,8 @@ function setupCameraFrame() {
     cameraFrameDiv[0].refreshDivider = 0;
     cameraFrameDiv[0].streamingFramerate = parseInt(cameraFrameDiv.attr('streaming_framerate')) || 1;
     cameraFrameDiv[0].streamingServerResize = cameraFrameDiv.attr('streaming_server_resize') == 'True';
+    cameraFrameDiv[0].proto = cameraFrameDiv.attr('proto');
+    cameraFrameDiv[0].url = cameraFrameDiv.attr('url');
     progressImg.attr('src', staticUrl + 'img/camera-progress.gif');
     
     cameraProgress.addClass('visible');
@@ -78,6 +80,12 @@ function refreshCameraFrame() {
     var img = $cameraFrame.find('img.camera')[0];
     var cameraId = cameraFrame.id.substring(6);
     
+    if (cameraFrame.proto == 'mjpeg') {
+        /* no manual refresh for simple mjpeg cameras */
+        img.src = cameraFrame.url;
+        return; 
+    }
+    
     /* at a refresh interval of 50ms, the refresh rate is limited to 20 fps */
     var count = 1000 / (refreshInterval * cameraFrame.streamingFramerate);
     if (count <= 2) {
index d3f6a306d9c621c91bfb2c84362222de377a7f65..619be9856fa7bfdffdd65b1cd804b3b524bb0c0f 100644 (file)
@@ -1163,9 +1163,11 @@ function cameraUi2Dict() {
     }
     
     var dict = {
-        /* video device */
         'enabled': $('#videoDeviceSwitch')[0].checked,
         'name': $('#deviceNameEntry').val(),
+        'proto': $('#deviceTypeEntry')[0].proto,
+        
+        /* video device */
         'light_switch_detect': $('#lightSwitchDetectSwitch')[0].checked,
         'auto_brightness': $('#autoBrightnessSwitch')[0].checked,
         'rotation': $('#rotationSelect').val(),
@@ -1355,15 +1357,15 @@ function dict2CameraUi(dict) {
     }
 
     function markHideIfNull(field, elemId) {
-        if (field == null || dict[field] == null) {
-            var elem = $('#' + elemId);
-            var sectionDiv = elem.parents('tr:eq(0), div.settings-section-title:eq(0)');
-            if (sectionDiv.length) { /* element is a section */
-                sectionDiv.add(sectionDiv.next()).each(function () {this._hideNull = true;});
-            }
-            else { /* element is a config option */
-                elem.parents('tr:eq(0)').each(function () {this._hideNull = true;});
-            }
+        var elem = $('#' + elemId);
+        var sectionDiv = elem.parents('tr:eq(0), div.settings-section-title:eq(0)');
+        var hideNull = field == null || dict[field] == null;
+
+        if (sectionDiv.length) { /* element is a section */
+            sectionDiv.add(sectionDiv.next()).each(function () {this._hideNull = hideNull;});
+        }
+        else { /* element is a config option */
+            elem.parents('tr:eq(0)').each(function () {this._hideNull = hideNull;});
         }
     }
     
@@ -1391,6 +1393,7 @@ function dict2CameraUi(dict) {
     $('#deviceNameEntry').val(dict['name']); markHideIfNull('name', 'deviceNameEntry');
     $('#deviceUriEntry').val(dict['device_url']); markHideIfNull('device_url', 'deviceUriEntry');
     $('#deviceTypeEntry').val(prettyType); markHideIfNull(prettyType, 'deviceTypeEntry');
+    $('#deviceTypeEntry')[0].proto = dict['proto'];
     $('#lightSwitchDetectSwitch')[0].checked = dict['light_switch_detect']; markHideIfNull('light_switch_detect', 'lightSwitchDetectSwitch');
     $('#autoBrightnessSwitch')[0].checked = dict['auto_brightness']; markHideIfNull('auto_brightness', 'autoBrightnessSwitch');
     
@@ -2342,12 +2345,15 @@ function getCameraIdsByInstance() {
         if (this.config.proto == 'netcam' || this.config.proto == 'v4l2') {
             instance = '';
         }
-        else { /* motioneye */
+        else if (this.config.proto == 'motioneye') {
             instance = this.config.host || '';
             if (this.config.port) {
                 instance += ':' + this.config.port;
             }
         }
+        else { /* assuming simple mjpeg camera */
+            return;
+        }
         
         (cameraIdsByInstance[instance] = cameraIdsByInstance[instance] || []).push(this.config.id);
     });
@@ -3407,6 +3413,12 @@ function addCameraFrameUi(cameraConfig) {
         configureButton.hide();
     }
     
+    /* no media buttons for simple mjpeg cameras */
+    if (cameraConfig['proto'] == 'mjpeg') {
+        picturesButton.hide();
+        moviesButton.hide();
+    }
+    
     cameraFrameDiv.attr('id', 'camera' + cameraId);
     cameraFrameDiv[0].refreshDivider = 0;
     cameraFrameDiv[0].config = cameraConfig;
@@ -3633,6 +3645,11 @@ function doFullScreenCamera(cameraId) {
             }
         });
     });
+    
+    if (cameraFrameDiv[0].config['proto'] == 'mjpeg') {
+        /* manually trigger the load event on simple mjpeg cameras */
+        cameraImg.load();
+    }
 }
 
 function refreshCameraFrames() {
@@ -3678,6 +3695,13 @@ function refreshCameraFrames() {
     cameraFrames.each(function () {
         if (!this.img) {
             this.img = $(this).find('img.camera')[0];
+            if (this.config['proto'] == 'mjpeg') {
+                this.img.src = this.config['url'];
+            }
+        }
+        
+        if (this.config['proto'] == 'mjpeg') {
+            return; /* no manual refresh for simple mjpeg cameras */
         }
         
         /* at a refresh interval of 50ms, the refresh rate is limited to 20 fps */
index d7133e6a6fa7196384da628370f14183745171da..184bd968b8f2df9716d31c7829b24e59cea0250c 100644 (file)
     </div>
     {% else %}
         <div class="camera-frame" id="camera{{camera_id}}"
-                streaming_framerate="{{camera_config['stream_maxrate']}}" streaming_server_resize="{{camera_config['@webcam_server_resize']}}">
+                streaming_framerate="{{camera_config['stream_maxrate']}}" streaming_server_resize="{{camera_config['@webcam_server_resize']}}"
+                proto="{{camera_config['@proto']}}" url="{{camera_config['@url']}}">
             
             <div class="camera-container">
                 <div class="camera-placeholder"><img class="no-camera" src="{{STATIC_URL}}img/no-camera.svg"></div><img