diff --git a/bin/picamserve b/bin/picamserve
--- a/bin/picamserve
+++ b/bin/picamserve
@@ -20,7 +20,7 @@ except ImportError:
def capture_continuous(self, *a, **kw):
for i in range(1000):
time.sleep(1)
- yield i
+ yield str(i)
def setCameraParams(c, arg):
res = int(arg('res', 480))
diff --git a/bin/vidref b/bin/vidref
--- a/bin/vidref
+++ b/bin/vidref
@@ -25,11 +25,7 @@ parser.add_option("-v", "--verbose", act
(options, args) = parser.parse_args()
-log.setLevel(logging.DEBUG)
-# limit the stdout one, but leave debug messages for the gtk logger
-log.handlers[0].setLevel(logging.DEBUG if options.verbose else logging.WARN)
-logging.getLogger("restkit.client").setLevel(logging.WARN)
-
+log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
class Snapshot(cyclone.web.RequestHandler):
@defer.inlineCallbacks
diff --git a/light9/vidref/main.py b/light9/vidref/main.py
--- a/light9/vidref/main.py
+++ b/light9/vidref/main.py
@@ -12,6 +12,7 @@ from twisted.python.util import sibpath
from light9.vidref.replay import ReplayViews, framerate
from light9.vidref.musictime import MusicTime
from light9.vidref.videorecorder import Pipeline
+from light9.vidref import remotepivideo
log = logging.getLogger()
class Gui(object):
@@ -39,8 +40,17 @@ class Gui(object):
mainwin.show_all()
vid3 = wtree.get_object("vid3")
- self.pipeline = Pipeline(vid3.window.xid, self.musicTime,
- self.recordingTo)
+ if 0:
+ self.pipeline = Pipeline(
+ liveVideoXid=vid3.window.xid,
+ musicTime=self.musicTime,
+ recordingTo=self.recordingTo)
+ else:
+ self.pipeline = remotepivideo.Pipeline(
+ 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')
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
@@ -40,7 +40,7 @@ class MusicTime(object):
if not hasattr(self, 'position'):
return {'t' : 0, 'song' : None}
pos = self.position.copy()
- if pos['playing']:
+ if pos.get('playing'):
pos['t'] = pos['t'] + (time.time() - self.positionFetchTime)
else:
if self.lastHoverTime is not None:
diff --git a/light9/vidref/remotepivideo.py b/light9/vidref/remotepivideo.py
new file mode 100644
--- /dev/null
+++ b/light9/vidref/remotepivideo.py
@@ -0,0 +1,115 @@
+"""
+like videorecorder.py, but talks to a bin/picamserve instance
+"""
+import os, time, logging
+import gtk
+import numpy
+import treq
+from light9.vidref.replay import framerate, songDir, takeDir, snapshotDir
+from light9 import prof
+from PIL import Image
+from StringIO import StringIO
+log = logging.getLogger('remotepi')
+
+class Pipeline(object):
+ def __init__(self, liveVideo, musicTime, recordingTo, picsUrl):
+ self.musicTime = musicTime
+ self.recordingTo = recordingTo
+
+ self.liveVideo = self._replaceLiveVideoWidget(liveVideo)
+
+ self._startRequest(picsUrl)
+ self._buffer = ''
+
+ def _replaceLiveVideoWidget(self, liveVideo):
+ aspectFrame = liveVideo.get_parent()
+ liveVideo.destroy()
+ img = gtk.Image()
+ img.set_visible(True)
+ #img.set_size_request(320, 240)
+ aspectFrame.add(img)
+ return img
+
+ def _startRequest(self, url):
+ d = treq.get(url)
+ d.addCallback(treq.collect, self._dataReceived)
+ # not sure how to stop this
+ return d
+
+ def _dataReceived(self, chunk):
+ self._buffer += chunk
+ if len(self._buffer) < 100:
+ return
+ i = self._buffer.index('\n')
+ size, frameTime = self._buffer[:i].split()
+ size = int(size)
+ if len(self._buffer) - i - 1 < size:
+ return
+ jpg = self._buffer[i+1:i+1+size]
+ self.onFrame(jpg, float(frameTime))
+ self._buffer = self._buffer[i+1+size:]
+
+ def snapshot(self):
+ """
+ returns deferred to the path (which is under snapshotDir()) where
+ we saved the image.
+ """
+ filename = "%s/%s.jpg" % (snapshotDir(), time.time())
+ return
+
+ def setInput(self, name):
+ pass
+
+ def setLiveVideo(self, on):
+ print "setLiveVideo", on
+
+ def onFrame(self, jpg, frameTime):
+ position = self.musicTime.getLatest()
+ if not position['song']:
+ self.updateLiveFromTemp(jpg)
+ return
+ outDir = takeDir(songDir(position['song']), position['started'])
+ outFilename = "%s/%08.03f.jpg" % (outDir, position['t'])
+ if os.path.exists(outFilename): # we're paused on one time
+ self.updateLiveFromTemp(jpg)
+ return
+ try:
+ os.makedirs(outDir)
+ except OSError:
+ pass
+ with open(outFilename, 'w') as out:
+ out.write(jpg)
+
+ self.updateLiveFromFile(outFilename)
+
+ # if you're selecting the text while gtk is updating it,
+ # you can get a crash in xcb_io
+ if getattr(self, '_lastRecText', None) != outDir:
+ with gtk.gdk.lock:
+ self.recordingTo.set_text(outDir)
+ self._lastRecText = outDir
+
+ def updateLiveFromFile(self, outFilename):
+ self.liveVideo.set_from_file(outFilename)
+
+ def updateLiveFromTemp(self, jpg):
+ try:
+ img = Image.open(StringIO(jpg))
+ if not hasattr(self, 'livePixBuf'):
+ self.livePixBuf = gtk.gdk.pixbuf_new_from_data(
+ img.tostring(),
+ gtk.gdk.COLORSPACE_RGB,
+ False, 8,
+ img.size[0], img.size[1],
+ img.size[0]*3)
+ log.info("live images are %r", img.size)
+ else:
+ # don't leak pixbufs; update the one we have
+ a = self.livePixBuf.pixel_array
+ newImg = numpy.fromstring(img.tostring(), dtype=numpy.uint8)
+ a[:,:,:] = newImg.reshape(a.shape)
+ self.liveVideo.set_from_pixbuf(self.livePixBuf)
+
+ except Exception:
+ import traceback
+ traceback.print_exc()
diff --git a/light9/vidref/replay.py b/light9/vidref/replay.py
--- a/light9/vidref/replay.py
+++ b/light9/vidref/replay.py
@@ -117,14 +117,11 @@ class ReplayView(object):
if True:
af = gtk.AspectFrame()
af.set_visible(True)
- w,h = (640-140-110), (480-130-70)
- af.set_size_request(w, h)
af.set_shadow_type(gtk.SHADOW_OUT)
af.props.obey_child = True
img = gtk.Image()
img.set_visible(True)
- img.set_size_request(w, h)
self.picWidget = img
af.add(img)
diff --git a/light9/vidref/vidref.glade b/light9/vidref/vidref.glade
--- a/light9/vidref/vidref.glade
+++ b/light9/vidref/vidref.glade
@@ -3,28 +3,34 @@
False
+ True
1
False
+ True
0
@@ -205,6 +248,7 @@ to:
336
259
True
+ False
0
out
@@ -219,10 +263,12 @@ to:
True
+ False
queue
True
+ False
@@ -241,28 +287,35 @@ to:
True
+ False
<b>Playback 1</b>
True
+ True
+ True
1
+ True
+ True
0
True
+ False
0
none
True
+ False
12
@@ -276,6 +329,7 @@ to:
True
+ False
<b>Music position</b>
True
@@ -283,21 +337,34 @@ to:
False
+ True
1
+
+ True
+ False
+ gtk-delete
+
+
+
+ /home/drewp/light9-vidref/play-light9.bigasterisk.com_show_dance2010_song6/1276582699
+
+ False
True
+ False
320
240
True
+ False
0
out
1.3300000429153442
@@ -306,24 +373,29 @@ to:
320
240
True
+ False
gtk-missing-image
False
+ True
0
True
+ False
True
+ False
True
+ False
Started:
@@ -340,6 +412,10 @@ to:
●
12
Sat 14:22:25
+ False
+ False
+ True
+ True
False
@@ -350,6 +426,7 @@ to:
False
+ True
0
@@ -359,9 +436,11 @@ to:
True
True
True
+ False
False
+ True
1
@@ -371,10 +450,12 @@ to:
True
True
True
+ False
image2
False
+ True
2
@@ -384,28 +465,23 @@ to:
True
True
False
+ False
True
False
+ True
3
False
+ True
1
-
- True
- gtk-delete
-
-
- /home/drewp/light9-vidref/play-light9.bigasterisk.com_show_dance2010_song6/1276582699
-
-
diff --git a/pydeps b/pydeps
--- a/pydeps
+++ b/pydeps
@@ -17,4 +17,5 @@ python-dateutil==2.2
txosc==0.2.0
service_identity==0.2
Pillow==2.4.0
-faulthandler==2.3
\ No newline at end of file
+faulthandler==2.3
+treq==0.2.1
\ No newline at end of file