diff --git a/bin/keyboardcomposer b/bin/keyboardcomposer --- a/bin/keyboardcomposer +++ b/bin/keyboardcomposer @@ -242,7 +242,8 @@ class KeyboardComposer(tk.Frame, SubClie self.setup_key_nudgers(subbox.scale) - self.effectEval[effect] = light9.effect.effecteval.EffectEval(self.graph, effect) + sharedEffectOutputs = {} + self.effectEval[effect] = light9.effect.effecteval.EffectEval(self.graph, effect, sharedEffectOutputs) col = (col + 1) % 8 last_group = group diff --git a/light9/effect/effecteval.py b/light9/effect/effecteval.py --- a/light9/effect/effecteval.py +++ b/light9/effect/effecteval.py @@ -5,6 +5,9 @@ from webcolors import rgb_to_hex, hex_to from decimal import Decimal import math from noise import pnoise1 +import logging + +log = logging.getLogger('effecteval') def literalColor(rnorm, gnorm, bnorm): return Literal(rgb_to_hex([rnorm * 255, gnorm * 255, bnorm * 255])) @@ -45,17 +48,22 @@ class EffectEval(object): runs one effect's code to turn effect attr settings into output device settings. No state; suitable for reload(). """ - def __init__(self, graph, effect): + def __init__(self, graph, effect, sharedEffectOutputs): self.graph = graph self.effect = effect # effect : [(dev, attr, value, isScaled)] - self.effectOutputs = {} - - self.graph.addHandler(self.updateEffectsFromGraph) + self.effectOutputs = sharedEffectOutputs + + if not self.effectOutputs: + self.graph.addHandler(self.updateEffectsFromGraph) def updateEffectsFromGraph(self): - self.effectOutputs = {} + # let this cache while i'm working on note timing + if self.effectOutputs: + log.warn('keeping %s effectOutputs, no reload', len(self.effectOutputs)) + return + for effect in self.graph.subjects(RDF.type, L9['Effect']): settings = [] for setting in self.graph.objects(effect, L9['setting']): diff --git a/light9/effect/sequencer.py b/light9/effect/sequencer.py --- a/light9/effect/sequencer.py +++ b/light9/effect/sequencer.py @@ -33,11 +33,11 @@ def sendToCollector(client, session, set class Note(object): - def __init__(self, graph, uri, effectevalModule): + def __init__(self, graph, uri, effectevalModule, sharedEffectOutputs): g = self.graph = graph self.uri = uri self.effectEval = effectevalModule.EffectEval( - graph, g.value(uri, L9['effectClass'])) + graph, g.value(uri, L9['effectClass']), sharedEffectOutputs) self.baseEffectSettings = {} # {effectAttr: value} for s in g.objects(uri, L9['setting']): ea = g.value(s, L9['effectAttr']) @@ -110,6 +110,7 @@ class Sequencer(object): self.recentUpdateTimes = [] self.lastStatLog = 0 + self._compileGraphCall = None self.notes = {} # song: [notes] self.graph.addHandler(self.compileGraph) self.update() @@ -118,13 +119,30 @@ class Sequencer(object): onChange=lambda: self.graph.addHandler(self.compileGraph)) def compileGraph(self): + log.info('compileGraph request') + self._compileGraphRun() + return + + # may not help + if self._compileGraphCall: + self._compileGraphCall.cancel() + self._compileGraphCall = reactor.callLater( + .5, + self.graph.addHandler, self._compileGraphRun) + + def _compileGraphRun(self): """rebuild our data from the graph""" + self._compileGraphCall = None + log.info('compileGraph start') g = self.graph + sharedEffectOutputs = {} + for song in g.subjects(RDF.type, L9['Song']): self.notes[song] = [] for note in g.objects(song, L9['note']): - self.notes[song].append(Note(g, note, effecteval)) + self.notes[song].append(Note(g, note, effecteval, sharedEffectOutputs)) + log.info('compileGraph done') @stats.update.time() def update(self):