Changeset - dc474426845d
[Not reviewed]
default
0 3 0
Drew Perttula - 11 years ago 2014-06-03 07:11:12
drewp@bigasterisk.com
effecteval better logging. everyone put their curve files in the right place.
Ignore-this: 7cb0ea890a0602783eb581459f28b72d
3 files changed with 32 insertions and 18 deletions:
0 comments (0 inline, 0 general)
bin/effecteval
Show inline comments
 
@@ -24,44 +24,46 @@ class EffectEdit(PrettyErrorHandler, cyc
 
    def delete(self):
 
        graph = self.settings.graph
 
        uri = URIRef(self.get_argument('uri'))
 
        with graph.currentState(tripleFilter=(None, L9['effect'], uri)) as g:
 
            song = ctx = list(g.subjects(L9['effect'], uri))[0]
 
        self.settings.graph.patch(Patch(delQuads=[
 
            (song, L9['effect'], uri, ctx),
 
            ]))
 
        
 
class SongEffects(PrettyErrorHandler, cyclone.web.RequestHandler):
 
    def post(self):
 
        song = URIRef(self.get_argument('uri'))
 
        drop = URIRef(self.get_argument('drop'))
 
        dropped = URIRef(self.get_argument('drop'))
 
        ctx = song
 
        graph = self.settings.graph
 
        effect = graph.sequentialUri(song + "/effect/e-")
 
        curve = graph.sequentialUri(song + "/curve/c-")
 
        effect = graph.sequentialUri(song + "/effect-")
 
        curve = graph.sequentialUri(song + "/curve-")
 

	
 
        with graph.currentState(
 
                tripleFilter=(drop, RDFS.label, None)) as g:
 
            dropSubLabel = g.label(drop)
 
                tripleFilter=(dropped, RDFS.label, None)) as g:
 
            droppedSubLabel = g.label(dropped)
 
        
 
        graph.patch(Patch(addQuads=[
 
            (song, L9['curve'], curve, ctx),
 
            (song, L9['effect'], effect, ctx),
 
            (effect, RDF.type, L9['Effect'], ctx),
 
            (effect, L9['code'],
 
             Literal('out = sub(%s, intensity=%s)' % (drop.n3(), curve.n3())),
 
             Literal('out = sub(%s, intensity=%s)' % (dropped.n3(), curve.n3())),
 
             ctx),
 
            (curve, RDF.type, L9['Curve'], ctx),
 
            (curve, RDFS.label, Literal('sub %s' % dropSubLabel), ctx),
 
            (curve, L9['points'], Literal('0 0'), ctx),
 
            (curve, RDFS.label, Literal('sub %s' % droppedSubLabel), ctx),
 
            ]))
 
        graph.patch(Patch(addQuads=[
 
            (curve, L9['points'], Literal('0 0'), Curve(uri=curve).curvePointsContext()),
 
            ]))
 
        
 
class SongEffectsUpdates(cyclone.websocket.WebSocketHandler):
 
    def connectionMade(self, *args, **kwargs):
 
        self.graph = self.settings.graph
 
        self.graph.addHandler(self.updateClient)
 
        
 
    def updateClient(self):
 
        # todo: abort if client is gone
 
        playlist = self.graph.value(showconfig.showUri(), L9['playList'])
 
        songs = list(self.graph.items(playlist))
 
        out = []
 
@@ -118,24 +120,26 @@ class SongEffectsEval(PrettyErrorHandler
 
        effects = effectsForSong(self.settings.graph, song)
 
        raise NotImplementedError
 
        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
 
@@ -172,41 +176,55 @@ class EffectLoop(object):
 
                    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:
 
                    outSubs.append(e.eval(songTime))
 
                out = Submaster.sub_maxes(*outSubs)
 

	
 
                self.logLevels(t1, out)
 
                dmx = out.get_dmx_list()
 

	
 
                if log.isEnabledFor(logging.DEBUG):
 
                    log.debug("send dmx: %r", out.get_levels())
 

	
 
                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
 
        self.graph = SyncedGraph("effectEval")
 
        self.graph.initiallySynced.addCallback(self.launch)
 

	
 
        self.stats = scales.collection('/',
 
                                       scales.PmfStat('sendLevels'),
 
                                       scales.PmfStat('getMusic'),
 
                                       scales.PmfStat('writeDmx'),
 
                                       scales.IntStat('errors'),
 
                                       )
light9/curvecalc/curve.py
Show inline comments
 
@@ -322,25 +322,25 @@ class Curveset(object):
 

	
 
    def new_curve(self, name, renameIfExisting=True):
 
        if isinstance(name, Literal):
 
            name = str(name)
 
        if name=="":
 
            print "no name given"
 
            return
 
        if not renameIfExisting and name in self.curves:
 
            return
 
        while name in self.curves:
 
           name=name+"-1"
 

	
 
        uri = self.graph.sequentialUri(self.currentSong + '/curve/c-')
 
        uri = self.graph.sequentialUri(self.currentSong + '/curve-')
 
        c = Curve(uri)
 
        s, e = self.get_time_range()
 
        c.points.extend([(s, 0), (e, 0)])
 
        ctx = self.currentSong
 
        self.graph.patch(Patch(addQuads=[
 
            (self.currentSong, L9['curve'], uri, ctx),
 
            (uri, RDF.type, L9['Curve'], ctx),
 
            (uri, RDFS.label, Literal(name), ctx),
 
            ]))
 
        print "pts to", c.curvePointsContext()
 
        self.graph.patch(Patch(addQuads=[
 
            (uri, L9['points'], Literal(c.points_as_string()),
light9/effecteval/effect.py
Show inline comments
 
@@ -26,28 +26,24 @@ class EffectNode(object):
 
        if self.code is None:
 
            raise ValueError("effect %s has no code" % self.uri)
 
        m = re.match(r'^out = sub\((.*?), intensity=(.*?)\)', self.code)
 
        if not m:
 
            raise NotImplementedError
 
        subUri = uriFromCode(m.group(1))
 
        subs = Submaster.get_global_submasters(self.graph)
 
        self.sub = subs.get_sub_by_uri(subUri)
 
        
 
        intensityCurve = uriFromCode(m.group(2))
 
        self.curve = Curve(uri=intensityCurve)
 

	
 
        # read from disk ok? how do we know to reread? start with
 
        # mtime. the mtime check could be done occasionally so on
 
        # average we read at most one curve's mtime per effectLoop.       
 

	
 
        pts = self.graph.value(intensityCurve, L9['points'])
 
        if pts is None:
 
            log.info("curve %r has no points" % intensityCurve)
 
        else:
 
            self.curve.set_from_string(pts)
 

	
 
        
 
    def eval(self, songTime):
 
        # consider http://waxeye.org/ for a parser that can be used in py and js
 
        level = self.curve.eval(songTime)
 
        scaledSubs = self.sub * level
 
        return scaledSubs
0 comments (0 inline, 0 general)