changeset 1100:1583e997fe0e

pull EffectLoop to another module Ignore-this: 6880f3f0b2aed3107c871296ad6cfbb9
author Drew Perttula <drewp@bigasterisk.com>
date Mon, 09 Jun 2014 03:55:50 +0000
parents a58e8408f563
children 3074f635ee23
files bin/effecteval light9/effecteval/effectloop.py
diffstat 2 files changed, 110 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/bin/effecteval	Mon Jun 09 03:07:15 2014 +0000
+++ b/bin/effecteval	Mon Jun 09 03:55:50 2014 +0000
@@ -11,6 +11,7 @@
 from light9 import networking, showconfig, Submaster, dmxclient
 from light9.curvecalc.curve import CurveResource
 from light9.effecteval.effect import EffectNode
+from light9.effecteval.effectloop import EffectLoop
 from light9.greplin_cyclone import StatsForCyclone
 from light9.namespaces import L9, RDF, RDFS
 from light9.rdfdb.patch import Patch
@@ -122,103 +123,6 @@
         self.write(maxDict(effectDmxDict(e) for e in effects))
         # return dmx dict for all effects in the song, already combined
 
-class EffectLoop(object):
-    """maintains a collection of the current EffectNodes, gets time from
-    music player, sends dmx"""
-    def __init__(self, graph, stats):
-        self.graph, self.stats = graph, stats
-        self.currentSong = None
-        self.currentEffects = []
-        self.lastLogTime = 0
-        self.lastLogMsg = ""
-        self.graph.addHandler(self.setEffects)
-        self.period = 1 / 30
-        self.coastSecs = .3 # main reason to keep this low is to notice play/pause
-
-        self.songTimeFromRequest = 0
-        self.requestTime = 0 # unix sec for when we fetched songTime
-        reactor.callLater(self.period, self.sendLevels)
-
-    def setEffects(self):
-        self.currentEffects = []
-        if self.currentSong is None:
-            return
-        
-        for effectUri in self.graph.objects(self.currentSong, L9['effect']):
-            self.currentEffects.append(EffectNode(self.graph, effectUri))
-        
-    @inlineCallbacks
-    def getSongTime(self):
-        now = time.time()
-        if now - self.requestTime < self.coastSecs:
-            estimated = self.songTimeFromRequest
-            if self.currentSong is not None and self.currentPlaying:
-                estimated += now - self.requestTime
-            returnValue((estimated, self.currentSong))
-        else:
-            response = json.loads((yield cyclone.httpclient.fetch(
-                networking.musicPlayer.path('time'))).body)
-            self.requestTime = now
-            self.currentPlaying = response['playing']
-            self.songTimeFromRequest = response['t']
-            returnValue(
-                (response['t'], (response['song'] and URIRef(response['song']))))
-            
-    @inlineCallbacks
-    def sendLevels(self):
-        t1 = time.time()
-        try:
-            with self.stats.sendLevels.time():
-                with self.stats.getMusic.time():
-                    songTime, song = yield self.getSongTime()
-
-                if song != self.currentSong:
-                    self.currentSong = song
-                    # this may be piling on the handlers
-                    self.graph.addHandler(self.setEffects)
-
-                if song is None:
-                    return
-
-                outSubs = []
-                for e in self.currentEffects:
-                    try:
-                        outSubs.append(e.eval(songTime))
-                    except Exception as exc:
-                        log.error("effect %s: %s" % (e.uri, exc))
-                out = Submaster.sub_maxes(*outSubs)
-
-                self.logLevels(t1, out)
-                dmx = out.get_dmx_list()
-                with self.stats.writeDmx.time():
-                    yield dmxclient.outputlevels(dmx, twisted=True)
-
-                elapsed = time.time() - t1
-                dt = max(0, self.period - elapsed)
-        except Exception:
-            self.stats.errors += 1
-            traceback.print_exc()
-            dt = 1
-
-        reactor.callLater(dt, self.sendLevels)
-        
-    def logLevels(self, now, out):
-        # this would look nice on the top of the effecteval web pages too
-        if log.isEnabledFor(logging.DEBUG):
-            log.debug(self.logMessage(out))
-        else:
-            if now > self.lastLogTime + 5:
-                msg = self.logMessage(out)
-                if msg != self.lastLogMsg:
-                    log.info(msg)
-                    self.lastLogMsg = msg
-                self.lastLogTime = now
-                
-    def logMessage(self, out):
-        return ("send dmx: {%s}" %
-                ", ".join("%r: %.3g" % (str(k), v)
-                          for k,v in out.get_levels().items()))
-        
 class App(object):
     def __init__(self, show):
         self.show = show
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/light9/effecteval/effectloop.py	Mon Jun 09 03:55:50 2014 +0000
@@ -0,0 +1,109 @@
+import time, json, logging, traceback
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue
+from rdflib import URIRef, Literal
+import cyclone.httpclient
+from light9.namespaces import L9, RDF, RDFS
+from light9.effecteval.effect import EffectNode
+from light9 import networking
+from light9 import Submaster
+from light9 import dmxclient
+log = logging.getLogger('effectloop')
+
+class EffectLoop(object):
+    """maintains a collection of the current EffectNodes, gets time from
+    music player, sends dmx"""
+    def __init__(self, graph, stats):
+        self.graph, self.stats = graph, stats
+        self.currentSong = None
+        self.currentEffects = []
+        self.lastLogTime = 0
+        self.lastLogMsg = ""
+        self.graph.addHandler(self.setEffects)
+        self.period = 1 / 30
+        self.coastSecs = .3 # main reason to keep this low is to notice play/pause
+
+        self.songTimeFromRequest = 0
+        self.requestTime = 0 # unix sec for when we fetched songTime
+        reactor.callLater(self.period, self.sendLevels)
+
+    def setEffects(self):
+        self.currentEffects = []
+        if self.currentSong is None:
+            return
+        
+        for effectUri in self.graph.objects(self.currentSong, L9['effect']):
+            self.currentEffects.append(EffectNode(self.graph, effectUri))
+        
+    @inlineCallbacks
+    def getSongTime(self):
+        now = time.time()
+        if now - self.requestTime < self.coastSecs:
+            estimated = self.songTimeFromRequest
+            if self.currentSong is not None and self.currentPlaying:
+                estimated += now - self.requestTime
+            returnValue((estimated, self.currentSong))
+        else:
+            response = json.loads((yield cyclone.httpclient.fetch(
+                networking.musicPlayer.path('time'))).body)
+            self.requestTime = now
+            self.currentPlaying = response['playing']
+            self.songTimeFromRequest = response['t']
+            returnValue(
+                (response['t'], (response['song'] and URIRef(response['song']))))
+            
+    @inlineCallbacks
+    def sendLevels(self):
+        t1 = time.time()
+        try:
+            with self.stats.sendLevels.time():
+                with self.stats.getMusic.time():
+                    songTime, song = yield self.getSongTime()
+
+                if song != self.currentSong:
+                    self.currentSong = song
+                    # this may be piling on the handlers
+                    self.graph.addHandler(self.setEffects)
+
+                if song is None:
+                    return
+
+                outSubs = []
+                for e in self.currentEffects:
+                    try:
+                        outSubs.append(e.eval(songTime))
+                    except Exception as exc:
+                        log.error("effect %s: %s" % (e.uri, exc))
+                out = Submaster.sub_maxes(*outSubs)
+
+                self.logLevels(t1, out)
+                dmx = out.get_dmx_list()
+                with self.stats.writeDmx.time():
+                    yield dmxclient.outputlevels(dmx, twisted=True)
+
+                elapsed = time.time() - t1
+                dt = max(0, self.period - elapsed)
+        except Exception:
+            self.stats.errors += 1
+            traceback.print_exc()
+            dt = 1
+
+        reactor.callLater(dt, self.sendLevels)
+        
+    def logLevels(self, now, out):
+        # this would look nice on the top of the effecteval web pages too
+        if log.isEnabledFor(logging.DEBUG):
+            log.debug(self.logMessage(out))
+        else:
+            if now > self.lastLogTime + 5:
+                msg = self.logMessage(out)
+                if msg != self.lastLogMsg:
+                    log.info(msg)
+                    self.lastLogMsg = msg
+                self.lastLogTime = now
+                
+    def logMessage(self, out):
+        return ("send dmx: {%s}" %
+                ", ".join("%r: %.3g" % (str(k), v)
+                          for k,v in out.get_levels().items()))
+