diff --git a/light9/networking.py b/light9/networking.py --- a/light9/networking.py +++ b/light9/networking.py @@ -41,3 +41,4 @@ keyboardComposer = ServiceAddress(L9['ke curveCalc = ServiceAddress(L9['curveCalc']) vidref = ServiceAddress(L9['vidref']) effectEval = ServiceAddress(L9['effectEval']) +picamserve = ServiceAddress(L9['picamserve']) diff --git a/light9/subserver/style.css b/light9/subserver/style.css --- a/light9/subserver/style.css +++ b/light9/subserver/style.css @@ -38,8 +38,8 @@ a.resource { background: rgb(44, 44, 44); } .sub img { - width: 180px; - height: 90px; + width: 196px; + min-height: 40px; margin: 6px; background: -webkit-gradient(linear,right top,left bottom,color-stop(0,rgb(121, 120, 120)),color-stop(1,rgb(54, 54, 54))); } diff --git a/light9/vidref/main.py b/light9/vidref/main.py --- a/light9/vidref/main.py +++ b/light9/vidref/main.py @@ -9,6 +9,7 @@ gst-launch dv1394src ! dvdemux name=d ! import gobject, logging, traceback import gtk from twisted.python.util import sibpath +from light9 import networking from light9.vidref.replay import ReplayViews, framerate from light9.vidref.musictime import MusicTime from light9.vidref.videorecorder import Pipeline @@ -50,7 +51,7 @@ class Gui(object): liveVideo=vid3, musicTime=self.musicTime, recordingTo=self.recordingTo, - picsUrl='http://10.1.0.125:8001/pics?res=1080&resize=450&x=0&y=.3&w=1&h=.5&awb_mode=auto&exposure_mode=auto') + picsUrl=networking.picamserve.path('pics?res=1080&resize=450&x=0&y=.3&w=1&h=.5&awb_mode=auto&exposure_mode=auto')) vid3.props.width_request = 360 vid3.props.height_request = 220 diff --git a/light9/vidref/musictime.py b/light9/vidref/musictime.py --- a/light9/vidref/musictime.py +++ b/light9/vidref/musictime.py @@ -31,17 +31,21 @@ class MusicTime(object): self.pollMusicTime() self.pollCurvecalcTime() - def getLatest(self): + def getLatest(self, frameTime=None): """ dict with 't' and 'song', etc. + frameTime is the timestamp from the camera, which will be used + instead of now. + Note that this may be called in a gst camera capture thread. Very often. """ if not hasattr(self, 'position'): return {'t' : 0, 'song' : None} pos = self.position.copy() + now = frameTime or time.time() if pos.get('playing'): - pos['t'] = pos['t'] + (time.time() - self.positionFetchTime) + pos['t'] = pos['t'] + (now - self.positionFetchTime) else: if self.lastHoverTime is not None: pos['hoverTime'] = self.lastHoverTime diff --git a/light9/vidref/remotepivideo.py b/light9/vidref/remotepivideo.py --- a/light9/vidref/remotepivideo.py +++ b/light9/vidref/remotepivideo.py @@ -5,6 +5,7 @@ import os, time, logging import gtk import numpy import treq +from twisted.internet import defer from light9.vidref.replay import framerate, songDir, takeDir, snapshotDir from light9 import prof from PIL import Image @@ -21,6 +22,8 @@ class Pipeline(object): self._startRequest(picsUrl) self._buffer = '' + self._snapshotRequests = [] + def _replaceLiveVideoWidget(self, liveVideo): aspectFrame = liveVideo.get_parent() liveVideo.destroy() @@ -55,7 +58,9 @@ class Pipeline(object): we saved the image. """ filename = "%s/%s.jpg" % (snapshotDir(), time.time()) - return + d = defer.Deferred() + self._snapshotRequests.append((d, filename)) + return d def setInput(self, name): pass @@ -64,7 +69,20 @@ class Pipeline(object): print "setLiveVideo", on def onFrame(self, jpg, frameTime): + # We could pass frameTime here to try to compensate for lag, + # but it ended up looking worse in a test. One suspect is the + # rpi clock drift might be worse than the lag. The value of + # (now - frameTime) stutters regularly between 40ms, 140ms, + # and 200ms. position = self.musicTime.getLatest() + + for d, filename in self._snapshotRequests: + with open(filename, 'w') as out: + out.write(jpg) + d.callback(filename) + self._snapshotRequests[:] = [] + + if not position['song']: self.updateLiveFromTemp(jpg) return diff --git a/show/dance2014/networking.n3 b/show/dance2014/networking.n3 --- a/show/dance2014/networking.n3 +++ b/show/dance2014/networking.n3 @@ -10,4 +10,5 @@ sh:netHome :oscDmxServer ; :curveCalc ; :keyboardComposer ; + :picamserve ; :vidref .