]> www.vanbest.org Git - motioneye-debian/commitdiff
implemented v4l2ctl
authorCalin Crisan <ccrisan@gmail.com>
Sat, 28 Sep 2013 16:42:04 +0000 (19:42 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Sat, 28 Sep 2013 16:42:04 +0000 (19:42 +0300)
doc/todo.txt
src/handlers.py
src/server.py
src/v4l2ctl.py

index 05005c79e098eb9fffd311409f5b82b3dbab8abd..2ff1d97d5e0b935d2d9ff2da6f89a15f1d43268e 100644 (file)
@@ -1,5 +1,6 @@
 -> group @config rules to top
 -> browser compatibility test
+-> requirements test
 -> hint text next to section titles
 -> clickable hints
 -> authentication
index 2278593273f4eaf94cea90c26af94e7f4f586fdd..2453173f34f05762e79e5f75f5ca80ecd74696a7 100644 (file)
@@ -6,6 +6,7 @@ from tornado.web import RequestHandler, HTTPError
 
 import config
 import template
+import v4l2ctl
 
 
 class BaseHandler(RequestHandler):
@@ -36,6 +37,9 @@ class ConfigHandler(BaseHandler):
         elif op == 'list':
             self.list_cameras()
         
+        elif op == 'list_devices':
+            self.list_devices()
+        
         else:
             raise HTTPError(400, 'unknown operation')
     
@@ -116,6 +120,11 @@ class ConfigHandler(BaseHandler):
 
         self.finish_json({'cameras': cameras})
     
+    def list_devices(self):
+        logging.debug('listing devices')
+        
+        self.finish_json({'devices': v4l2ctl.list_devices()})
+    
     def add_camera(self):
         logging.debug('adding new camera')
         
index 864507c07039ccde5c00f22875a19f33460e3e94..de0edb0da38eb0abcb2a56df848ec2b73acccf39 100644 (file)
@@ -11,7 +11,7 @@ application = Application(
         (r'^/$', handlers.MainHandler),
         (r'^/config/main/(?P<op>set|get)/?$', handlers.ConfigHandler),
         (r'^/config/(?P<camera_id>\d+)/(?P<op>get|set|rem)/?$', handlers.ConfigHandler),
-        (r'^/config/(?P<op>add|list)/?$', handlers.ConfigHandler),
+        (r'^/config/(?P<op>add|list|list_devices)/?$', handlers.ConfigHandler),
         (r'^/snapshot/(?P<camera_id>\d+)/(?P<op>current|list)/?$', handlers.SnapshotHandler),
         (r'^/snapshot/(?P<camera_id>\d+)/(?P<op>download)/(?P<filename>.+)/?$', handlers.SnapshotHandler),
         (r'^/movie/(?P<camera_id>\d+)/(?P<op>list)/?$', handlers.MovieHandler),
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e634b9d340e0ac457e2c214b6fca87800b68c54e 100644 (file)
@@ -0,0 +1,113 @@
+
+import logging
+import re
+import subprocess
+
+
+def list_devices():
+    logging.debug('listing v4l devices...')
+    
+    devices = []
+    
+    output = subprocess.check_output('v4l2-ctl --list-devices', shell=True)
+    
+    name = None
+    for line in output.split('\n'):
+        if line.startswith('\t'):
+            device = line.strip()
+            devices.append((device, name))
+        
+            logging.debug('found device %(name)s: %(device)s' % {
+                    'name': name, 'device': device})
+            
+        else:
+            name = line.split('(')[0].strip()
+
+    return devices
+
+
+def list_resolutions(device):
+    logging.debug('listing resolutions of device %(device)s...' % {'device': device})
+    
+    resolutions = set()
+    output = subprocess.check_output('v4l2-ctl -d %(device)s --list-formats-ext | grep -oE "[0-9]+x[0-9]+"' % {
+            'device': device}, shell=True)
+
+    for pair in output.split('\n'):
+        pair = pair.strip()
+        if not pair:
+            continue
+        
+        width, height = pair.split('x')
+        width = int(width)
+        height = int(height)
+        
+        resolutions.add((width, height))
+        
+        logging.debug('found resolution %(width)sx%(height)s for device %(device)s' % {
+                'device': device, 'width': width, 'height': height})
+    
+    return list(sorted(resolutions, key=lambda r: (r[0], r[1])))
+
+
+def set_brightness(device, value):
+    _set_ctrl(device, 'brightness', value)
+
+
+def set_contrast(device, value):
+    _set_ctrl(device, 'contrast', value)
+
+
+def set_saturation(device, value):
+    _set_ctrl(device, 'saturation', value)
+
+
+def set_hue(device, value):
+    _set_ctrl(device, 'hue', value)
+
+
+def _set_ctrl(device, control, value):
+    controls = _list_ctrls(device)
+    properties = controls.get(control)
+    if properties is None:
+        logging.warn('control %(control)s not found for device %(device)s' % {
+                'control': control, 'device': device})
+        
+        return
+    
+    # adjust the value range
+    if 'min' in properties and 'max' in properties:
+        min_value = int(properties['min'])
+        max_value = int(properties['max'])
+        
+        value = min_value + value * float(max_value - min_value) / 255
+    
+    else:
+        logging.warn('min and max values not found for control %(control)s of device %(device)s' % {
+                'control': control, 'device': device})
+    
+    logging.debug('setting control %(control)s of device %(device)s to %(value)s' % {
+            'control': control, 'device': device, 'value': value})
+        
+    subprocess.call('v4l2-ctl -d %(device)s --set-ctrl %(control)s=%(value)s' % {
+            'device': device, 'control': control, 'value': value}, shell=True)
+
+
+def _list_ctrls(device):
+    output = subprocess.call('v4l2-ctl -d %(device)s --list-ctrls' % {
+            'device': device}, shell=True)
+
+    controls = {}
+    for line in output:
+        if not line:
+            continue
+        
+        match = re.match('^\s*(\w+)\s+\(\w+\)\s+\:\s*(.+)', line)
+        if not match:
+            continue
+        
+        (control, properties) = match.groups()
+        properties = dict([v.split('=') for v in properties.split(' ')])
+        controls[control] = properties
+    
+    return controls