Changeset - 6906cacaa218
[Not reviewed]
default
0 4 0
drewp@bigasterisk.com - 9 years ago 2016-06-12 00:24:57
drewp@bigasterisk.com
KC and SEQ share inotify code to reload effect code
Ignore-this: 2ae8142fda67b2290f4d0af219781c69
4 files changed with 31 insertions and 21 deletions:
0 comments (0 inline, 0 general)
bin/keyboardcomposer
Show inline comments
 
@@ -16,12 +16,13 @@ from light9.subclient import SubClient
 
from light9 import showconfig, networking, prof
 
from light9.uihelpers import toplevelat
 
from light9.namespaces import L9, RDF
 
from light9.tkdnd import initTkdnd, dragSourceRegister, dropTargetRegister
 
from light9.rdfdb import clientsession
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
from light9.effect.sequencer import CodeWatcher
 
import light9.effect.effecteval
 

	
 
from bcf2000 import BCF2000
 

	
 
nudge_keys = {
 
    'up'   : list('qwertyui'),
 
@@ -160,13 +161,17 @@ class KeyboardComposer(tk.Frame, SubClie
 
        self.connect_to_hw(hw_sliders)
 

	
 
        self.make_key_hints()
 
        self.make_buttons()
 

	
 
        self.graph.addHandler(self.redraw_sliders)
 
        self.send_levels_loop()
 

	
 
        self.codeWatcher = CodeWatcher(
 
            onChange=lambda: self.graph.addHandler(self.redraw_sliders))
 
        
 
        self.send_levels_loop(delay=.05)
 
        self.graph.addHandler(self.rowFromGraph)
 

	
 
    def make_buttons(self):
 
        self.buttonframe = tk.Frame(self, bg='black')
 
        self.buttonframe.pack(side=tk.BOTTOM)
 

	
light9/collector/device.py
Show inline comments
 
@@ -48,12 +48,13 @@ def resolve(deviceType, deviceAttr, valu
 
    if len(values) == 1:
 
        return values[0]
 
    if deviceAttr == L9['color']:
 
        rgbs = [hex_to_rgb(v) for v in values]
 
        return rgb_to_hex([max(*component) for component in zip(*rgbs)])
 
    # angles should perhaps use average; gobo choice use the most-open one
 
    
 
    return max(values)
 
    
 
def toOutputAttrs(deviceType, deviceAttrSettings):
 
    """
 
    Given device attr settings like {L9['color']: Literal('#ff0000')},
 
    return a similar dict where the keys are output attrs (like
light9/effect/effecteval.py
Show inline comments
 
@@ -28,13 +28,13 @@ 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):
 
        self.graph = graph
 
        self.effect = effect
 
        self.effect = effect 
 

	
 
        # effect : [(dev, attr, value, isScaled)]
 
        self.effectOutputs = {}
 
        
 
        #for ds in g.objects(g.value(uri, L9['effectClass']), L9['deviceSetting']):
 
        #    self.setting = (g.value(ds, L9['device']), g.value(ds, L9['attr']))
light9/effect/sequencer.py
Show inline comments
 
@@ -71,13 +71,33 @@ class Note(object):
 
    def outputSettings(self, t):
 
        """
 
        list of (device, attr, value)
 
        """
 
        effectSettings = [(L9['strength'], self.evalCurve(t))]
 
        return self.effectEval.outputFromEffect(effectSettings, t)
 
                
 

	
 

	
 
class CodeWatcher(object):
 
    def __init__(self, onChange):
 
        self.onChange = onChange
 

	
 
        self.notifier = INotify()
 
        self.notifier.startReading()
 
        self.notifier.watch(
 
            FilePath(effecteval.__file__.replace('.pyc', '.py')),
 
            callbacks=[self.codeChange])
 

	
 
    def codeChange(self, watch, path, mask):
 
        def go():
 
            log.info("reload effecteval")
 
            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, sendToCollector):
 
        self.graph = graph
 
        self.sendToCollector = sendToCollector
 
        self.music = MusicTime(period=.2, pollCurvecalc=False)
 
@@ -85,35 +105,19 @@ class Sequencer(object):
 
        self.recentUpdateTimes = []
 
        self.lastStatLog = 0
 
        self.notes = {} # song: [notes]
 
        self.graph.addHandler(self.compileGraph)
 
        self.update()
 

	
 
        self.watchCode()
 

	
 
    def watchCode(self):
 
        self.notifier = INotify()
 
        self.notifier.startReading()
 
        self.notifier.watch(
 
            FilePath(effecteval.__file__.replace('.pyc', '.py')),
 
            callbacks=[self.codeChange])
 

	
 
    def codeChange(self, watch, path, mask):
 
        def go():
 
            reload(effecteval)
 
            self.graph.addHandler(self.compileGraph)
 
        # in case we got an event at the start of the write
 
        reactor.callLater(.1, go) 
 
        self.codeWatcher = CodeWatcher(
 
            onChange=lambda: self.graph.addHandler(self.compileGraph))
 

	
 
    def compileGraph(self):
 
        """rebuild our data from the graph"""
 
        g = self.graph
 

	
 
        log.info("compileGraph")
 
        reload(effecteval)
 
        
 
        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))
 

	
 
    @stats.update.time()
0 comments (0 inline, 0 general)