#!bin/python from __future__ import division, nested_scopes from optparse import OptionParser import Tkinter as tk import louie as dispatcher from twisted.internet import reactor, tksupport, task import run_local from light9.dmxchanedit import Levelbox from light9 import dmxclient, Patch, Submaster, showconfig, prof from light9.uihelpers import toplevelat from light9.rdfdb.syncedgraph import SyncedGraph class Subcomposer(tk.Frame): def __init__(self, master, graph): tk.Frame.__init__(self, master, bg='black') self.graph = graph self.levelbox = Levelbox(self, graph) self.levelbox.pack(side='top') self.savebox = EntryCommand(self, cmd=self.savenewsub) self.savebox.pack(side='top') self.loadbox = EntryCommand(self, verb="Load", cmd=self.loadsub) self.loadbox.pack(side='top') def alltozero(): for lev in self.levelbox.levels: lev.setlevel(0) tk.Button(self, text="all to zero", command=alltozero).pack(side='top') dispatcher.connect(self.sendupdate, "levelchanged") def fill_both_boxes(self, subname): for box in [self.savebox, self.loadbox]: box.set(subname) def save_levels(self, *args): levelfile = file("subcomposer.savedlevels","w") levelfile.write(" ".join(map(str, self.levels))) def load_levels(self): try: levelfile = file("subcomposer.savedlevels","r") levels = map(float, levelfile.read().split()) self.set_levels(levels) except IOError: pass def savenewsub(self, subname): leveldict={} for i,lev in zip(range(len(self.levels)),self.levels): if lev!=0: leveldict[Patch.get_channel_name(i+1)]=lev s=Submaster.Submaster(subname,leveldict=leveldict) s.save() def loadsub(self, subname): """puts a sub into the levels, replacing old level values""" s=Submaster.Submasters(showconfig.getGraph()).get_sub_by_name(subname) self.set_levels(s.get_dmx_list()) dispatcher.send("levelchanged") def toDmxLevels(self): # the dmx levels we edit and output, range is 0..1 (dmx chan 1 is # the 0 element) out = {} for lev in self.levelbox.levels: out[lev.channelnum] = lev.currentlevel if not out: return [] return [out.get(i, 0) for i in range(max(out.keys()) + 1)] def sendupdate(self): dmxclient.outputlevels(self.toDmxLevels(), twisted=True) class EntryCommand(tk.Frame): def __init__(self, master, verb="Save", cmd=None): tk.Frame.__init__(self, master, bd=2, relief='raised') tk.Label(self, text="Sub name:").pack(side='left') self.cmd = cmd self.entry = tk.Entry(self) self.entry.pack(side='left', expand=True, fill='x') self.entry.bind("", self.action) tk.Button(self, text=verb, command=self.action).pack(side='left') def action(self, *args): subname = self.entry.get() self.cmd(subname) print "sub", self.cmd, subname def set(self, text): self.entry.delete(0, 'end') self.entry.insert(0, text) ############################# if __name__ == "__main__": parser = OptionParser(usage="%prog [subname]") parser.add_option('--no-geometry', action='store_true', help="don't save/restore window geometry") opts, args = parser.parse_args() root=tk.Tk() root.config(bg='black') root.tk_setPalette("#004633") if not opts.no_geometry: toplevelat("subcomposer", root) graph = SyncedGraph("subcomposer") sc = Subcomposer(root, graph) sc.pack() tk.Label(root,text="Bindings: B1 adjust level; B2 set full; B3 instant bump", font="Helvetica -12 italic",anchor='w').pack(side='top',fill='x') if len(args) == 1: root.config(bg='green') # trying to make these look distinctive sc.loadsub(args[0]) sc.fill_both_boxes(args[0]) task.LoopingCall(sc.sendupdate).start(1) tksupport.install(root,ms=10) prof.run(reactor.run, profile=False)