# HG changeset patch # User Drew Perttula # Date 2014-06-08 09:30:03 # Node ID 087f6cbe4b222fc3e3af271911e51570459d98f0 # Parent f6c5b9b94daef68f3e9697472892c06eea59e5a0 vidrefsetup tool now prepares a url that vidref will use for rpi camera requests Ignore-this: 3b10bb845aa51811f21f63d4a280d2bd diff --git a/bin/picamserve b/bin/picamserve --- a/bin/picamserve +++ b/bin/picamserve @@ -33,7 +33,7 @@ def setCameraParams(c, arg): c.exposure_mode = arg('exposure_mode', 'fixedfps') c.awb_mode = arg('awb_mode', 'off') c.brightness = int(arg('brightness', 50)) - + c.exposure_compensation= int(arg('exposure_compensation', 0)) c.awb_gains = (float(arg('redgain', 1)), float(arg('bluegain', 1))) c.ISO = int(arg('iso', 250)) diff --git a/bin/vidref b/bin/vidref --- a/bin/vidref +++ b/bin/vidref @@ -9,11 +9,11 @@ import gobject gobject.threads_init() import gtk import sys, logging, optparse, json -sys.path.append(".") -from light9 import networking +import cyclone.web, cyclone.httpclient, cyclone.websocket +from light9 import networking, showconfig from light9.vidref.main import Gui from light9.vidref.replay import snapshotDir -import cyclone.web, cyclone.httpclient, cyclone.websocket +from light9.rdfdb.syncedgraph import SyncedGraph # find replay dirs correctly. show multiple # replays. trash. reorder/pin. dump takes that are too short; they're @@ -50,11 +50,15 @@ class Snapshot(cyclone.web.RequestHandle class SnapshotPic(cyclone.web.StaticFileHandler): pass - -gui = Gui() +graph = SyncedGraph("vidref") + +gui = Gui(graph) port = networking.vidref.port reactor.listenTCP(port, cyclone.web.Application(handlers=[ + (r'/()', cyclone.web.StaticFileHandler, + {'path': 'light9/vidref', 'default_filename': 'vidref.html'}), + (r'/static/(.*)', cyclone.web.StaticFileHandler, {'path': 'static/'}), (r'/snapshot', Snapshot), (r'/snapshot/(.*)', SnapshotPic, {"path": snapshotDir()}), ], debug=True, gui=gui)) diff --git a/bin/vidrefsetup b/bin/vidrefsetup new file mode 100644 --- /dev/null +++ b/bin/vidrefsetup @@ -0,0 +1,70 @@ +#!bin/python +""" this should be part of vidref, but I haven't worked out sharing +camera captures with a continuous camera capture yet """ + +from run_local import log +import sys, optparse, logging, json, subprocess, datetime +from dateutil.tz import tzlocal +from twisted.internet import reactor, defer +import cyclone.web, cyclone.httpclient, cyclone.websocket +from rdflib import RDF, URIRef, Literal +import pyjade.utils +from light9.rdfdb.syncedgraph import SyncedGraph +from light9.rdfdb.patch import Patch +from light9.namespaces import L9, DCTERMS +from light9 import networking, showconfig + +from lib.cycloneerr import PrettyErrorHandler + +class RedirToCamera(PrettyErrorHandler, cyclone.web.RequestHandler): + def get(self): + return self.redirect(networking.picamserve.path( + 'pic?' + self.request.query)) + +class UrlToCamera(PrettyErrorHandler, cyclone.web.RequestHandler): + def get(self): + self.set_header('Content-Type', 'text/plain') + self.write(networking.picamserve.path('pic')) + +class VidrefCamRequest(PrettyErrorHandler, cyclone.web.RequestHandler): + def get(self): + graph = self.settings.graph + show = showconfig.showUri() + with graph.currentState(tripleFilter=(show, None, None)) as g: + ret = g.value(show, L9['vidrefCamRequest']) + if ret is None: + self.send_error(404) + self.redirect(ret) + + def put(self): + graph = self.settings.graph + show = showconfig.showUri() + graph.patchObject(context=URIRef(show + '/vidrefConfig'), + subject=show, + predicate=L9['vidrefCamRequest'], + newObject=URIRef(self.get_argument('uri'))) + self.send_error(202) + +def main(): + parser = optparse.OptionParser() + parser.add_option("-v", "--verbose", action="store_true", + help="logging.DEBUG") + (options, args) = parser.parse_args() + + log.setLevel(logging.DEBUG if options.verbose else logging.INFO) + graph = SyncedGraph("vidrefsetup") + + # deliberately conflict with vidref since they can't talk at once to cam + port = networking.vidref.port + + reactor.listenTCP(port, cyclone.web.Application(handlers=[ + (r'/pic', RedirToCamera), + (r'/picUrl', UrlToCamera), + (r'/vidrefCamRequest', VidrefCamRequest), + (r'/static/(.*)', cyclone.web.StaticFileHandler, {'path': 'static/'}), + (r'/()', cyclone.web.StaticFileHandler, {'path': 'light9/vidref/', 'default_filename': 'vidref.html'}), + ], debug=True, graph=graph)) + log.info("serving on %s" % port) + reactor.run() + +main() diff --git a/light9/vidref/main.py b/light9/vidref/main.py --- a/light9/vidref/main.py +++ b/light9/vidref/main.py @@ -17,7 +17,7 @@ from light9.vidref import remotepivideo log = logging.getLogger() class Gui(object): - def __init__(self): + def __init__(self, graph): wtree = gtk.Builder() wtree.add_from_file(sibpath(__file__, "vidref.glade")) mainwin = wtree.get_object("MainWindow") @@ -51,7 +51,7 @@ class Gui(object): liveVideo=vid3, musicTime=self.musicTime, recordingTo=self.recordingTo, - picsUrl=networking.picamserve.path('pics?res=1080&resize=450&x=0&y=.3&w=1&h=.5&awb_mode=auto&exposure_mode=auto')) + graph=graph) vid3.props.width_request = 360 vid3.props.height_request = 220 diff --git a/light9/vidref/remotepivideo.py b/light9/vidref/remotepivideo.py --- a/light9/vidref/remotepivideo.py +++ b/light9/vidref/remotepivideo.py @@ -7,23 +7,34 @@ import numpy import treq from twisted.internet import defer from light9.vidref.replay import framerate, songDir, takeDir, snapshotDir -from light9 import prof +from light9 import prof, showconfig +from light9.namespaces import L9 from PIL import Image from StringIO import StringIO log = logging.getLogger('remotepi') class Pipeline(object): - def __init__(self, liveVideo, musicTime, recordingTo, picsUrl): + def __init__(self, liveVideo, musicTime, recordingTo, graph): self.musicTime = musicTime self.recordingTo = recordingTo self.liveVideo = self._replaceLiveVideoWidget(liveVideo) - self._startRequest(picsUrl) - self._buffer = '' + self._snapshotRequests = [] + self.graph = graph + self.graph.addHandler(self.updateCamUrl) - self._snapshotRequests = [] - + def updateCamUrl(self): + show = showconfig.showUri() + self.picsUrl = self.graph.value(show, L9['vidrefCamRequest']) + log.info("picsUrl now %r", self.picsUrl) + if not self.picsUrl: + return + + # this cannot yet survive being called a second time + self._startRequest(str(self.picsUrl.replace('/pic', '/pics')) + + '&res=1080&resize=450') + def _replaceLiveVideoWidget(self, liveVideo): aspectFrame = liveVideo.get_parent() liveVideo.destroy() @@ -34,6 +45,7 @@ class Pipeline(object): return img def _startRequest(self, url): + self._buffer = '' d = treq.get(url) d.addCallback(treq.collect, self._dataReceived) # not sure how to stop this diff --git a/light9/vidref/vidref.html b/light9/vidref/vidref.html new file mode 100644 --- /dev/null +++ b/light9/vidref/vidref.html @@ -0,0 +1,180 @@ + + + + vidref + + + + + +

video setup

+ +
Camera view
+
+
+ +
+
+
+ +
+ set these +
+
+
+
+
+
+
+
+ + + + + + + + + +
See picamera attribute docs
+
+ +
Resulting url:
+ +
Resulting crop image:
+
+ + + + + + + + +