0
|
1 #!/usr/bin/python
|
|
2
|
|
3 from __future__ import division, nested_scopes
|
|
4 import Tkinter as tk
|
|
5 from dmxchanedit import Levelbox
|
|
6 import sys,os,time,atexit
|
|
7 sys.path.append("../light8")
|
|
8 import dmxclient
|
|
9 import Patch
|
|
10 import Submaster
|
|
11
|
|
12 from dispatch import dispatcher
|
|
13
|
|
14 class Subcomposer(tk.Frame):
|
|
15 def __init__(self, master, levelboxopts=None, dmxdummy=0, numchannels=68,
|
|
16 use_persistentlevels=0):
|
|
17 tk.Frame.__init__(self, master, bg='black')
|
|
18 self.dmxdummy = dmxdummy
|
|
19 self.numchannels = numchannels
|
|
20
|
|
21 self.levels = [0]*68 # levels should never get overwritten, just edited
|
|
22
|
|
23 self.levelbox = Levelbox(self)
|
|
24 self.levelbox.pack(side='top')
|
|
25 # the dmx levels we edit and output, range is 0..1 (dmx chan 1 is
|
|
26 # the 0 element)
|
|
27 self.levelbox.setlevels(self.levels)
|
|
28
|
|
29 self.savebox = Savebox(self, self.levels, cmd=self.savenewsub)
|
|
30 self.savebox.pack(side='top')
|
|
31
|
|
32 self.loadbox = Savebox(self, self.levels, verb="Load", cmd=self.loadsub)
|
|
33 self.loadbox.pack(side='top')
|
|
34
|
|
35 def alltozero():
|
|
36 self.set_levels([0] * self.numchannels)
|
|
37 dispatcher.send("levelchanged")
|
|
38
|
|
39 tk.Button(self, text="all to zero", command=alltozero).pack(side='top')
|
|
40
|
|
41 dispatcher.connect(self.levelchanged,"levelchanged")
|
|
42 dispatcher.connect(self.sendupdate,"levelchanged")
|
|
43
|
|
44 if use_persistentlevels:
|
|
45 self.persistentlevels()
|
|
46
|
|
47 self.lastupdate=0 # time we last sent to dmx
|
|
48
|
|
49 self.lastsent=[] # copy of levels
|
|
50
|
|
51 def persistentlevels(self):
|
|
52 """adjusts levels from subcomposer.savedlevels, if possible; and
|
|
53 arranges to save the levels in that file upon exit"""
|
|
54 self.load_levels()
|
|
55 atexit.register(self.save_levels)
|
|
56 def save_levels(self, *args):
|
|
57 levelfile = file("subcomposer.savedlevels","w")
|
|
58 levelfile.write(" ".join(map(str, self.levels)))
|
|
59 def load_levels(self):
|
|
60 try:
|
|
61 levelfile = file("subcomposer.savedlevels","r")
|
|
62 levels = map(float, levelfile.read().split())
|
|
63 self.set_levels(levels)
|
|
64 except IOError:
|
|
65 pass
|
|
66 def levelchanged(self, channel=None, newlevel=None):
|
|
67 if channel is not None and newlevel is not None:
|
|
68 if channel>len(self.levels):
|
|
69 return
|
|
70 self.levels[channel-1]=max(0,min(1,float(newlevel)))
|
|
71 self.levelbox.setlevels(self.levels)
|
|
72 def savenewsub(self, levels, subname):
|
|
73 leveldict={}
|
|
74 for i,lev in zip(range(len(self.levels)),self.levels):
|
|
75 if lev!=0:
|
|
76 leveldict[Patch.get_channel_name(i+1)]=lev
|
|
77
|
|
78 s=Submaster.Submaster(subname,leveldict)
|
|
79 s.save()
|
|
80 def loadsub(self, levels, subname):
|
|
81 """puts a sub into the levels, replacing old level values"""
|
|
82 s=Submaster.Submasters().get_sub_by_name(subname)
|
|
83 self.levels[:]=[0]*68
|
|
84 self.levels[:]=s.get_dmx_list()
|
|
85 dispatcher.send("levelchanged")
|
|
86 def sendupdate(self):
|
|
87 if not self.dmxdummy:
|
|
88 dmxclient.outputlevels(self.levels)
|
|
89 self.lastupdate = time.time()
|
|
90 self.lastsent = self.levels[:]
|
|
91 def considersendupdate(self, use_after_loop=0):
|
|
92 """If use_after_loop is true, it is the period of the after loop."""
|
|
93 if self.lastsent != self.levels or time.time() > self.lastupdate + 1:
|
|
94 self.sendupdate()
|
|
95 if use_after_loop:
|
|
96 self.after(use_after_loop, self.considersendupdate, use_after_loop)
|
|
97 def set_levels(self, levels):
|
|
98 self.levels[:] = levels
|
|
99 dispatcher.send("levelchanged")
|
|
100
|
|
101 def Savebox(master, levels, verb="Save", cmd=None):
|
|
102 f=tk.Frame(master,bd=2,relief='raised')
|
|
103 tk.Label(f,text="Sub name:").pack(side='left')
|
|
104 e=tk.Entry(f)
|
|
105 e.pack(side='left',exp=1,fill='x')
|
|
106 def cb(*args):
|
|
107 subname=e.get()
|
|
108 cmd(levels,subname)
|
|
109 print "sub",verb,subname
|
|
110 e.bind("<Return>",cb)
|
|
111 tk.Button(f,text=verb,command=cb).pack(side='left')
|
|
112 return f
|
|
113
|
|
114 def open_sub_editing_window(subname, use_mainloop=1, dmxdummy=0):
|
|
115 if use_mainloop:
|
|
116 toplevel = tk.Tk()
|
|
117 else:
|
|
118 toplevel = tk.Toplevel()
|
|
119 if dmxdummy:
|
|
120 dummy_str = ' (dummy)'
|
|
121 else:
|
|
122 dummy_str = ''
|
|
123 toplevel.title("Subcomposer: %s%s" % (subname, dummy_str))
|
|
124 sc = Subcomposer(toplevel, use_persistentlevels=0, dmxdummy=dmxdummy)
|
|
125 sc.pack(fill='both', expand=1)
|
|
126 sc.loadsub(None, subname) # don't ask
|
|
127 sc.considersendupdate(use_after_loop=10)
|
|
128 if use_mainloop:
|
|
129 tk.mainloop()
|
|
130
|
|
131 #############################
|
|
132
|
|
133 if __name__ == "__main__":
|
|
134 root=tk.Tk()
|
|
135 root.config(bg='black')
|
|
136 root.tk_setPalette("#004633")
|
|
137
|
|
138 sc = Subcomposer(root, dmxdummy=0)
|
|
139 sc.pack()
|
|
140
|
|
141 while 1:
|
|
142 if 0:
|
|
143 for i in range(20): # don't let Tk take all the time
|
|
144 tk._tkinter.dooneevent()
|
|
145 print "loop"
|
|
146 else:
|
|
147 root.update()
|
|
148
|
|
149 sc.considersendupdate()
|
|
150 time.sleep(.01)
|