#!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 from light9.rdfdb import clientsession class Subcomposer(tk.Frame): def __init__(self, master, graph, session): tk.Frame.__init__(self, master, bg='black') self.graph = graph self.session = session 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 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() # this is going to be more like 'tie to sub' and 'untied' 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") clientsession.add_option(parser) opts, args = parser.parse_args() root=tk.Tk() root.config(bg='black') root.tk_setPalette("#004633") if not opts.no_geometry: toplevelat("subcomposer - %s" % opts.session, root) graph = SyncedGraph("subcomposer") session = clientsession.getUri('subcomposer', opts) sc = Subcomposer(root, graph, session) 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) root.protocol('WM_DELETE_WINDOW', reactor.stop) tksupport.install(root,ms=10) prof.run(reactor.run, profile=False)