Changeset - 87d9db21ba98
[Not reviewed]
default
0 1 0
Drew Perttula - 6 years ago 2019-05-28 08:42:14
drewp@bigasterisk.com
treq content() deferred api fix
Ignore-this: a2a3f8fa02cd7fe25a1ecb749ed8faf
1 file changed with 4 insertions and 2 deletions:
0 comments (0 inline, 0 general)
light9/vidref/musictime.py
Show inline comments
 
import time, json, logging
 
from typing import Dict
 

	
 
from twisted.internet import reactor
 
from twisted.internet.defer import inlineCallbacks
 
import treq
 

	
 
from light9 import networking
 

	
 
log = logging.getLogger()
 

	
 

	
 
class MusicTime(object):
 
    """
 
    fetch times from ascoltami in a background thread; return times
 
    upon request, adjusted to be more precise with the system clock
 
    """
 

	
 
    def __init__(self,
 
                 period=.2,
 
                 onChange=lambda position: None,
 
                 pollCurvecalc=True):
 
        """period is the seconds between http time requests.
 

	
 
        We call onChange with the time in seconds and the total time
 

	
 
        The choice of period doesn't need to be tied to framerate,
 
        it's more the size of the error you can tolerate (since we
 
        make up times between the samples, and we'll just run off the
 
@@ -40,54 +41,55 @@ class MusicTime(object):
 
            self.pollCurvecalcTime()
 

	
 
    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'] + (now - self.positionFetchTime)
 
        else:
 
            if self.lastHoverTime is not None:
 
                pos['hoverTime'] = self.lastHoverTime
 
        return pos
 

	
 
    def pollMusicTime(self):
 

	
 
        @inlineCallbacks
 
        def cb(response):
 

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

	
 
            position = json.loads(response.body)
 
            position = yield response.json()
 

	
 
            # 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 = treq.get(networking.musicPlayer.path("time").toPython())
 
        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.
0 comments (0 inline, 0 general)