Changeset - feafbe49ca0b
[Not reviewed]
default
0 2 0
Drew Perttula - 6 years ago 2019-06-01 23:45:25
drewp@bigasterisk.com
type fixes
Ignore-this: 7f9003a6097a2b56c6767ded3360d8ec
2 files changed with 15 insertions and 14 deletions:
0 comments (0 inline, 0 general)
light9/collector/collector_client.py
Show inline comments
 
@@ -32,28 +32,28 @@ def toCollectorJson(client, session, set
 
        'settings': settings.asList(),
 
        'client': client,
 
        'clientSession': session,
 
        'sendTime': time.time(),
 
    })
 

	
 

	
 
def sendToCollectorZmq(msg):
 
    global _zmqClient
 
    if _zmqClient is None:
 
        _zmqClient = TwistedZmqClient(networking.collectorZmq)
 
    _zmqClient.send(msg)
 
    return defer.succeed(0)
 
    return defer.succeed(0.0)
 

	
 

	
 
def sendToCollector(client, session, settings: DeviceSettings, useZmq=False):
 
def sendToCollector(client, session, settings: DeviceSettings, useZmq=False) -> defer.Deferred:
 
    """deferred to the time in seconds it took to get a response from collector"""
 
    sendTime = time.time()
 
    msg = toCollectorJson(client, session, settings).encode('utf8')
 

	
 
    if useZmq:
 
        d = sendToCollectorZmq(msg)
 
    else:
 
        d = treq.put(networking.collector.path('attrs'), data=msg, timeout=1)
 

	
 
    def onDone(result):
 
        dt = time.time() - sendTime
 
        stats.send = dt
light9/effect/sequencer.py
Show inline comments
 
@@ -2,25 +2,25 @@
 
copies from effectloop.py, which this should replace
 
'''
 

	
 
from louie import dispatcher
 
from rdflib import URIRef
 
from twisted.internet import reactor
 
from twisted.internet import defer
 
from twisted.internet.inotify import INotify
 
from twisted.python.filepath import FilePath
 
import cyclone.sse
 
import logging, bisect, time
 
import traceback
 
from typing import Any, Callable, Dict, List, Tuple, cast
 
from typing import Any, Callable, Dict, List, Tuple, cast, Union
 

	
 
from light9.namespaces import L9, RDF
 
from light9.newtypes import DeviceUri, DeviceAttr, NoteUri, Curve, Song
 
from light9.vidref.musictime import MusicTime
 
from light9.effect import effecteval
 
from light9.effect.settings import DeviceSettings
 
from light9.effect.simple_outputs import SimpleOutputs
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
from greplin import scales
 
import imp
 

	
 
@@ -100,29 +100,34 @@ class Note(object):
 
        frac = (t - p1[0]) / (p2[0] - p1[0])
 
        y = p1[1] + (p2[1] - p1[1]) * frac
 
        return y
 

	
 
    def outputSettings(self, t: float) -> Tuple[List[Tuple[DeviceUri, DeviceAttr, float]], Dict]:
 
        """
 
        list of (device, attr, value), and a report for web
 
        """
 
        report = {
 
            'note': str(self.uri),
 
            'effectClass': self.effectEval.effect,
 
        }
 
        effectSettings = self.baseEffectSettings.copy()
 
        effectSettings: Dict[DeviceAttr, Union[float, str]] = dict(
 
            (DeviceAttr(da), v.toPython()) for da, v in self.baseEffectSettings.items())
 
        effectSettings[L9['strength']] = self.evalCurve(t)
 
        def prettyFormat(x: Union[float, str]):
 
            if isinstance(x, float):
 
                return round(x, 4)
 
            return x
 
        report['effectSettings'] = dict(
 
            (str(k), str(round(v, 4))) for k, v in sorted(effectSettings.items()))
 
        report['nonZero'] = effectSettings[L9['strength']] > 0
 
            (str(k), prettyFormat(v)) for k, v in sorted(effectSettings.items()))
 
        report['nonZero'] = cast(float, effectSettings[L9['strength']]) > 0
 
        out, evalReport = self.effectEval.outputFromEffect(
 
            list(effectSettings.items()),
 
            songTime=t,
 
            # note: not using origin here since it's going away
 
            noteTime=t - self.points[0][0])
 
        report['devicesAffected'] = len(out.devices())
 
        return out, report
 

	
 

	
 
class CodeWatcher(object):
 

	
 
    def __init__(self, onChange):
 
@@ -140,51 +145,48 @@ class CodeWatcher(object):
 
            log.info("reload effecteval")
 
            imp.reload(effecteval)
 
            self.onChange()
 

	
 
        # in case we got an event at the start of the write
 
        reactor.callLater(.1, go)
 

	
 

	
 
class Sequencer(object):
 

	
 
    def __init__(self,
 
                 graph: SyncedGraph,
 
                 sendToCollector: Callable[[DeviceSettings], None],
 
                 sendToCollector: Callable[[DeviceSettings], defer.Deferred[float]],
 
                 fps=40):
 
        self.graph = graph
 
        self.fps = fps
 
        updateStats.goalFps = self.fps
 
        updateStats.updateLoopLatencyGoal = 1 / self.fps
 
        self.sendToCollector = sendToCollector
 
        self.music = MusicTime(period=.2, pollCurvecalc=False)
 

	
 
        self.recentUpdateTimes: List[float] = []
 
        self.lastStatLog = 0.0
 
        self._compileGraphCall = None
 
        self.notes: Dict[URIRef, List[Note]] = {}  # song: [notes]
 
        self.notes: Dict[Song, List[Note]] = {}  # song: [notes]
 
        self.simpleOutputs = SimpleOutputs(self.graph)
 
        self.graph.addHandler(self.compileGraph)
 
        self.updateLoop()
 

	
 
        self.codeWatcher = CodeWatcher(
 
            onChange=lambda: self.graph.addHandler(self.compileGraph))
 

	
 
    @compileStats.graph.time()
 
    def compileGraph(self) -> None:
 
        """rebuild our data from the graph"""
 
        t1 = time.time()
 
        g = self.graph
 

	
 
        for song in g.subjects(RDF.type, L9['Song']):
 
        for song in self.graph.subjects(RDF.type, L9['Song']):
 
            def compileSong(song: Song = cast(Song, song)) -> None:
 
                self.compileSong(song)
 
            self.graph.addHandler(compileSong)
 

	
 
    @compileStats.song.time()
 
    def compileSong(self, song: Song) -> None:
 
        self.notes[song] = []
 
        for note in self.graph.objects(song, L9['note']):
 
            self.notes[song].append(
 
                Note(self.graph, NoteUri(note), effecteval, self.simpleOutputs))
 

	
 
    def updateLoop(self) -> None:
 
@@ -201,26 +203,25 @@ class Sequencer(object):
 
            if isinstance(sec, float): # sometimes None, not sure why, and neither is mypy
 
                updateStats.s3_send = sec
 

	
 
            # time to send to collector, measured in this function,
 
            # from after sendToCollector returned its deferred until
 
            # when the deferred was called.
 
            updateStats.sendPhase = time.time() - sendStarted
 
            reactor.callLater(delay, self.updateLoop)
 

	
 
        def err(e):
 
            log.warn('updateLoop: %r', e)
 
            reactor.callLater(2, self.updateLoop)
 

	
 
        d = self.update()
 
        
 
        d.addCallbacks(done, err)
 

	
 
    @updateStats.updateFps.rate()
 
    def update(self) -> defer.Deferred:
 
        try:
 
            with updateStats.s0_getMusic.time():
 
                musicState = self.music.getLatest()
 
                if not musicState.get('song') or not isinstance(musicState.get('t'), float):
 
                    return defer.succeed(0.0)
 
                song = Song(URIRef(musicState['song']))
 
                dispatcher.send('state', update={'song': str(song), 't': musicState['t']})
 

	
0 comments (0 inline, 0 general)