Changeset - 3b3cc5f98a03
[Not reviewed]
default
0 2 0
drewp@bigasterisk.com - 12 years ago 2013-06-13 02:21:37
drewp@bigasterisk.com
vidref use async http client for talking to asco and CC. No more blocking the gst thread to learn curvecalc time
Ignore-this: d6564b13cb68581b3416fd4efaaf261b
2 files changed with 71 insertions and 30 deletions:
0 comments (0 inline, 0 general)
light9/vidref/musictime.py
Show inline comments
 
import restkit, time, json, logging
 
from light9 import networking
 
from threading import Thread
 
from twisted.internet import reactor
 
from cyclone.httpclient import fetch
 
from restkit.errors import ResourceNotFound
 
import http_parser.http
 
log = logging.getLogger()
 
@@ -21,18 +22,20 @@ class MusicTime(object):
 
        end of a song)
 
        """
 
        self.period = period
 
        self.hoverPeriod = .05
 
        self.onChange = onChange
 
        self.musicResource = restkit.Resource(networking.musicPlayer.url)
 
        self.curveCalc = restkit.Resource(networking.curveCalc.url)
 
        t = Thread(target=self._timeUpdate)
 
        t.setDaemon(True)
 
        t.start()
 

	
 
        self.position = {}
 
        self.lastHoverTime = None # None means "no recent value"
 
        self.pollMusicTime()
 
        self.pollCurvecalcTime()
 

	
 
    def getLatest(self):
 
        """
 
        dict with 't' and 'song', etc.
 

	
 
        Note that this may be called in a gst camera capture thread.
 
        Note that this may be called in a gst camera capture thread. Very often.
 
        """
 
        if not hasattr(self, 'position'):
 
            return {'t' : 0, 'song' : None}
 
@@ -40,34 +43,73 @@ class MusicTime(object):
 
        if pos['playing']:
 
            pos['t'] = pos['t'] + (time.time() - self.positionFetchTime)
 
        else:
 
            try:
 
                # todo: this is blocking for a long while if CC is
 
                # down. Either make a tiny timeout, or go async
 
                r = self.curveCalc.get("hoverTime")
 
            except (ResourceNotFound, http_parser.http.NoMoreData, Exception):
 
                pass
 
            else:
 
                pos['hoverTime'] = json.loads(r.body_string())['hoverTime']
 
            if self.lastHoverTime is not None:
 
                pos['hoverTime'] = self.lastHoverTime
 
        return pos
 

	
 
    def _timeUpdate(self):
 
        while True:
 
            try:
 
                position = json.loads(self.musicResource.get("time").body_string())
 
    def pollMusicTime(self):
 
        def cb(response):
 

	
 
            if response.code != 200:
 
                raise ValueError("%s %s", response.code, response.body)
 

	
 
            position = json.loads(response.body)
 

	
 
            # this is meant to be the time when the server gave me its
 
            # report, and I don't know if that's closer to the
 
            # beginning of my request or the end of it (or some
 
            # fraction of the way through)
 
            self.positionFetchTime = time.time()
 

	
 
            self.position = position
 
            self.onChange(position)
 

	
 
            reactor.callLater(self.period, self.pollMusicTime)
 
            
 
        def eb(err):
 
            log.warn("talking to ascoltami: %s", err.getErrorMessage())
 
            reactor.callLater(2, self.pollMusicTime)
 
            
 
        d = fetch(networking.musicPlayer.path("time"))
 
        d.addCallback(cb)
 
        d.addErrback(eb) # note this includes errors in cb()
 

	
 
    def pollCurvecalcTime(self):
 
        """
 
        poll the curvecalc position when music isn't playing, so replay
 
        can track it.
 

	
 
                # this is meant to be the time when the server gave me its
 
                # report, and I don't know if that's closer to the
 
                # beginning of my request or the end of it (or some
 
                # fraction of the way through)
 
                self.positionFetchTime = time.time()
 
        This would be better done via rdfdb sync, where changes to the
 
        curvecalc position are written to the curvecalc session and we
 
        can pick them up in here
 
        """
 
        if self.position.get('playing'):
 
            # don't need this position during playback
 
            self.lastHoverTime = None
 
            reactor.callLater(.2, self.pollCurvecalcTime)
 
            return
 
            
 
        def cb(response):
 
            if response.code == 404:
 
                # not hovering
 
                self.lastHoverTime = None
 
                reactor.callLater(.2, self.pollCurvecalcTime)
 
                return
 
            if response.code != 200:
 
                raise ValueError("%s %s" % (response.code, response.body))
 
            self.lastHoverTime = json.loads(response.body)['hoverTime']
 

	
 
                self.position = position
 
                self.onChange(position)
 
            except restkit.RequestError, e:
 
                log.error(e)
 
                time.sleep(1)
 
            time.sleep(self.period)
 
            reactor.callLater(self.hoverPeriod, self.pollCurvecalcTime)
 

	
 
        def eb(err):
 
            log.warn("talking to curveCalc: %s", err.getErrorMessage())
 
            self.lastHoverTime = None
 
            reactor.callLater(2, self.pollCurvecalcTime)
 

	
 
        d = fetch(networking.curveCalc.path("hoverTime"))
 
        d.addCallback(cb)
 
        d.addErrback(eb) # note this includes errors in cb()
 
        
 
    def sendTime(self, t):
 
        """request that the player go to this time"""
 
        self.musicResource.post("time", payload=json.dumps({"t" : t}),
light9/vidref/videorecorder.py
Show inline comments
 
@@ -159,7 +159,6 @@ class VideoRecordSink(gst.Element):
 

	
 
    def saveImg(self, position, img, bufferTimestamp):
 
        if not position['song']:
 
            print "no song"
 
            return 
 
        
 
        t1 = time.time()
0 comments (0 inline, 0 general)