annotate flax/CueFaders.py @ 124:8de8a2f467db

The "T" function now creates TimedEvents with LinearBlenders for you The "T" function now creates TimedEvents with LinearBlenders for you (using the same LinearBlender). Thus, we don't need to specify linear anymore. The timeline seek bar was reading the length of track1 instead of the whole timeline. This is fixed.
author dmcc
date Fri, 13 Jun 2003 15:55:54 +0000
parents 45b12307c695
children 990a9474d0e7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
45b12307c695 Initial revision
drewp
parents:
diff changeset
1 from __future__ import division, nested_scopes
45b12307c695 Initial revision
drewp
parents:
diff changeset
2 import Tix as Tk
45b12307c695 Initial revision
drewp
parents:
diff changeset
3 import time
45b12307c695 Initial revision
drewp
parents:
diff changeset
4 from TreeDict import TreeDict, allow_class_to_be_pickled
45b12307c695 Initial revision
drewp
parents:
diff changeset
5 from TLUtility import enumerate
45b12307c695 Initial revision
drewp
parents:
diff changeset
6 import Submaster, dmxclient
45b12307c695 Initial revision
drewp
parents:
diff changeset
7
45b12307c695 Initial revision
drewp
parents:
diff changeset
8 cue_state_indicator_colors = {
45b12307c695 Initial revision
drewp
parents:
diff changeset
9 # bg fg
45b12307c695 Initial revision
drewp
parents:
diff changeset
10 'prev' : ('blue', 'white'),
45b12307c695 Initial revision
drewp
parents:
diff changeset
11 'cur' : ('yellow', 'black'),
45b12307c695 Initial revision
drewp
parents:
diff changeset
12 'next' : ('red', 'white'),
45b12307c695 Initial revision
drewp
parents:
diff changeset
13 }
45b12307c695 Initial revision
drewp
parents:
diff changeset
14
45b12307c695 Initial revision
drewp
parents:
diff changeset
15 # TODO
45b12307c695 Initial revision
drewp
parents:
diff changeset
16 # FIXE pause fades, set new time to be remaining about of time in the fade so
45b12307c695 Initial revision
drewp
parents:
diff changeset
17 # fade can continue properly
45b12307c695 Initial revision
drewp
parents:
diff changeset
18 # FIXE make fades work properly: the set_next / prev bug
45b12307c695 Initial revision
drewp
parents:
diff changeset
19 # WONT find cue by page ("not necessawy!")
45b12307c695 Initial revision
drewp
parents:
diff changeset
20 # WONT CueFader controls KeyboardController? unlikely
45b12307c695 Initial revision
drewp
parents:
diff changeset
21 # FIXE AutoSave loop
45b12307c695 Initial revision
drewp
parents:
diff changeset
22
45b12307c695 Initial revision
drewp
parents:
diff changeset
23 class LabelledScale(Tk.Frame):
45b12307c695 Initial revision
drewp
parents:
diff changeset
24 """Scale with two labels: a name and current value"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
25 def __init__(self, master, label, **opts):
45b12307c695 Initial revision
drewp
parents:
diff changeset
26 Tk.Frame.__init__(self, master, bd=2, relief='raised', bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
27 self.labelformatter = opts.get('labelformatter')
45b12307c695 Initial revision
drewp
parents:
diff changeset
28 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
29 del opts['labelformatter']
45b12307c695 Initial revision
drewp
parents:
diff changeset
30 except KeyError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
31 pass
45b12307c695 Initial revision
drewp
parents:
diff changeset
32
45b12307c695 Initial revision
drewp
parents:
diff changeset
33 opts.setdefault('variable', Tk.DoubleVar())
45b12307c695 Initial revision
drewp
parents:
diff changeset
34 opts.setdefault('showvalue', 0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
35
45b12307c695 Initial revision
drewp
parents:
diff changeset
36 self.normaltrough = opts.get('troughcolor', 'black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
37 self.flashtrough = opts.get('flashtroughcolor', 'red')
45b12307c695 Initial revision
drewp
parents:
diff changeset
38 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
39 del opts['flashtroughcolor']
45b12307c695 Initial revision
drewp
parents:
diff changeset
40 except KeyError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
41 pass
45b12307c695 Initial revision
drewp
parents:
diff changeset
42
45b12307c695 Initial revision
drewp
parents:
diff changeset
43 self.scale_var = opts['variable']
45b12307c695 Initial revision
drewp
parents:
diff changeset
44 self.scale = Tk.Scale(self, **opts)
45b12307c695 Initial revision
drewp
parents:
diff changeset
45 self.scale.pack(side='top', expand=1, fill='both')
45b12307c695 Initial revision
drewp
parents:
diff changeset
46 self.name = Tk.Label(self, text=label, bg='black', fg='white')
45b12307c695 Initial revision
drewp
parents:
diff changeset
47 self.name.pack(side='bottom')
45b12307c695 Initial revision
drewp
parents:
diff changeset
48 self.scale_value = Tk.Label(self, bg='black', fg='white')
45b12307c695 Initial revision
drewp
parents:
diff changeset
49 self.scale_value.pack(side='bottom')
45b12307c695 Initial revision
drewp
parents:
diff changeset
50 self.scale_var.trace('w', self.update_value_label)
45b12307c695 Initial revision
drewp
parents:
diff changeset
51 self.update_value_label()
45b12307c695 Initial revision
drewp
parents:
diff changeset
52 self.disabled = (self.scale['state'] == 'disabled')
45b12307c695 Initial revision
drewp
parents:
diff changeset
53 def set_label(self, label):
45b12307c695 Initial revision
drewp
parents:
diff changeset
54 self.name['text'] = label
45b12307c695 Initial revision
drewp
parents:
diff changeset
55 def update_value_label(self, *args):
45b12307c695 Initial revision
drewp
parents:
diff changeset
56 val = self.scale_var.get() * 100
45b12307c695 Initial revision
drewp
parents:
diff changeset
57 if self.labelformatter:
45b12307c695 Initial revision
drewp
parents:
diff changeset
58 format = self.labelformatter(val)
45b12307c695 Initial revision
drewp
parents:
diff changeset
59 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
60 format = "%0.2f" % val
45b12307c695 Initial revision
drewp
parents:
diff changeset
61 self.scale_value['text'] = format
45b12307c695 Initial revision
drewp
parents:
diff changeset
62 if val != 0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
63 self.scale['troughcolor'] = self.flashtrough
45b12307c695 Initial revision
drewp
parents:
diff changeset
64 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
65 self.scale['troughcolor'] = self.normaltrough
45b12307c695 Initial revision
drewp
parents:
diff changeset
66 def disable(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
67 if not self.disabled:
45b12307c695 Initial revision
drewp
parents:
diff changeset
68 self.scale['state'] = 'disabled'
45b12307c695 Initial revision
drewp
parents:
diff changeset
69 self.scale_var.set(0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
70 self.disabled = 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
71 def enable(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
72 if self.disabled:
45b12307c695 Initial revision
drewp
parents:
diff changeset
73 self.scale['state'] = 'normal'
45b12307c695 Initial revision
drewp
parents:
diff changeset
74 self.disabled = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
75
45b12307c695 Initial revision
drewp
parents:
diff changeset
76 class TimedGoButton(Tk.Frame):
45b12307c695 Initial revision
drewp
parents:
diff changeset
77 """Go button, fade time entry, and time fader"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
78 def __init__(self, master, name, scale_to_fade, **kw):
45b12307c695 Initial revision
drewp
parents:
diff changeset
79 Tk.Frame.__init__(self, master, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
80 self.name = name
45b12307c695 Initial revision
drewp
parents:
diff changeset
81 self.scale_to_fade = scale_to_fade
45b12307c695 Initial revision
drewp
parents:
diff changeset
82 self.button = Tk.Button(self, text=name, command=self.start_fade, **kw)
45b12307c695 Initial revision
drewp
parents:
diff changeset
83 self.button.pack(fill='both', expand=1, side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
84
45b12307c695 Initial revision
drewp
parents:
diff changeset
85 self.timer_var = Tk.DoubleVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
86 self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0,
45b12307c695 Initial revision
drewp
parents:
diff changeset
87 variable=self.timer_var, selectmode='immediate')
45b12307c695 Initial revision
drewp
parents:
diff changeset
88 for widget in (self.timer_entry, self.timer_entry.entry,
45b12307c695 Initial revision
drewp
parents:
diff changeset
89 self.timer_entry.incr, self.timer_entry.decr, self.button, self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
90 widget.bind("<4>", self.wheelscroll)
45b12307c695 Initial revision
drewp
parents:
diff changeset
91 widget.bind("<5>", self.wheelscroll)
45b12307c695 Initial revision
drewp
parents:
diff changeset
92 self.timer_entry.entry.configure(width=5, bg='black', fg='white')
45b12307c695 Initial revision
drewp
parents:
diff changeset
93 self.timer_entry.pack(fill='y', side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
94 self.timer_var.set(2)
45b12307c695 Initial revision
drewp
parents:
diff changeset
95 self.disabled = (self.button['state'] == 'disabled')
45b12307c695 Initial revision
drewp
parents:
diff changeset
96 self.start_time = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
97 self.fading = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
98 self.last_after_key = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
99 def manual_override(self, *args):
45b12307c695 Initial revision
drewp
parents:
diff changeset
100 self.end_fade()
45b12307c695 Initial revision
drewp
parents:
diff changeset
101 def wheelscroll(self, event):
45b12307c695 Initial revision
drewp
parents:
diff changeset
102 """Mouse wheel increments or decrements timer."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
103 if event.num == 4: # scroll up
45b12307c695 Initial revision
drewp
parents:
diff changeset
104 self.timer_entry.increment()
45b12307c695 Initial revision
drewp
parents:
diff changeset
105 else: # scroll down
45b12307c695 Initial revision
drewp
parents:
diff changeset
106 self.timer_entry.decrement()
45b12307c695 Initial revision
drewp
parents:
diff changeset
107 def start_fade(self, end_level=1):
45b12307c695 Initial revision
drewp
parents:
diff changeset
108 self.last_start_time = self.start_time
45b12307c695 Initial revision
drewp
parents:
diff changeset
109 self.start_time = time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
110 self.start_level = self.scale_to_fade.scale_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
111 self.end_level = end_level
45b12307c695 Initial revision
drewp
parents:
diff changeset
112
45b12307c695 Initial revision
drewp
parents:
diff changeset
113 if self.fading == 1: # if we're already fading
45b12307c695 Initial revision
drewp
parents:
diff changeset
114 self.fading = 'paused'
45b12307c695 Initial revision
drewp
parents:
diff changeset
115 # new fade should be as long as however much was left
45b12307c695 Initial revision
drewp
parents:
diff changeset
116 self.fade_length = self.fade_length - \
45b12307c695 Initial revision
drewp
parents:
diff changeset
117 (time.time() - self.last_start_time)
45b12307c695 Initial revision
drewp
parents:
diff changeset
118 self.button['text'] = 'Unpause'
45b12307c695 Initial revision
drewp
parents:
diff changeset
119 self.after_cancel(self.last_after_key)
45b12307c695 Initial revision
drewp
parents:
diff changeset
120 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
121 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
122 fade_time = float(self.timer_var.get())
45b12307c695 Initial revision
drewp
parents:
diff changeset
123 except ValueError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
124 # since we use a TixControl now, i don't think we need to worry
45b12307c695 Initial revision
drewp
parents:
diff changeset
125 # about validation any more.
45b12307c695 Initial revision
drewp
parents:
diff changeset
126 print ">>> Can't fade -- bad time", self.timer_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
127 return
45b12307c695 Initial revision
drewp
parents:
diff changeset
128
45b12307c695 Initial revision
drewp
parents:
diff changeset
129 # if we're not already fading, we get our time from the entry
45b12307c695 Initial revision
drewp
parents:
diff changeset
130 if self.fading != 'paused':
45b12307c695 Initial revision
drewp
parents:
diff changeset
131 self.fade_length = fade_time
45b12307c695 Initial revision
drewp
parents:
diff changeset
132
45b12307c695 Initial revision
drewp
parents:
diff changeset
133 self.button['text'] = 'Pause'
45b12307c695 Initial revision
drewp
parents:
diff changeset
134 self.fading = 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
135 self.do_fade()
45b12307c695 Initial revision
drewp
parents:
diff changeset
136 def do_fade(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
137 diff = time.time() - self.start_time
45b12307c695 Initial revision
drewp
parents:
diff changeset
138 if diff < self.fade_length:
45b12307c695 Initial revision
drewp
parents:
diff changeset
139 percent = diff / self.fade_length
45b12307c695 Initial revision
drewp
parents:
diff changeset
140 newlevel = self.start_level + \
45b12307c695 Initial revision
drewp
parents:
diff changeset
141 (percent * (self.end_level - self.start_level))
45b12307c695 Initial revision
drewp
parents:
diff changeset
142 self.scale_to_fade.scale_var.set(newlevel)
45b12307c695 Initial revision
drewp
parents:
diff changeset
143
45b12307c695 Initial revision
drewp
parents:
diff changeset
144 if newlevel != self.end_level:
45b12307c695 Initial revision
drewp
parents:
diff changeset
145 self.last_after_key = self.after(10, self.do_fade)
45b12307c695 Initial revision
drewp
parents:
diff changeset
146 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
147 self.end_fade()
45b12307c695 Initial revision
drewp
parents:
diff changeset
148 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
149 self.scale_to_fade.scale_var.set(self.end_level)
45b12307c695 Initial revision
drewp
parents:
diff changeset
150 self.end_fade()
45b12307c695 Initial revision
drewp
parents:
diff changeset
151 def end_fade(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
152 self.button['text'] = self.name
45b12307c695 Initial revision
drewp
parents:
diff changeset
153 self.fading = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
154 self.after_cancel(self.last_after_key)
45b12307c695 Initial revision
drewp
parents:
diff changeset
155 def disable(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
156 if not self.disabled:
45b12307c695 Initial revision
drewp
parents:
diff changeset
157 self.button['state'] = 'disabled'
45b12307c695 Initial revision
drewp
parents:
diff changeset
158 self.disabled = 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
159 def enable(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
160 if self.disabled:
45b12307c695 Initial revision
drewp
parents:
diff changeset
161 self.button['state'] = 'normal'
45b12307c695 Initial revision
drewp
parents:
diff changeset
162 self.disabled = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
163 def set_time(self, time):
45b12307c695 Initial revision
drewp
parents:
diff changeset
164 self.timer_var.set(time)
45b12307c695 Initial revision
drewp
parents:
diff changeset
165 def get_time(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
166 return self.timer_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
167 def is_fading(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
168 return self.fading
45b12307c695 Initial revision
drewp
parents:
diff changeset
169
45b12307c695 Initial revision
drewp
parents:
diff changeset
170 class CueFader(Tk.Frame):
45b12307c695 Initial revision
drewp
parents:
diff changeset
171 def __init__(self, master, cuelist):
45b12307c695 Initial revision
drewp
parents:
diff changeset
172 Tk.Frame.__init__(self, master, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
173 self.cuelist = cuelist
45b12307c695 Initial revision
drewp
parents:
diff changeset
174 self.cuelist.set_fader(self)
45b12307c695 Initial revision
drewp
parents:
diff changeset
175
45b12307c695 Initial revision
drewp
parents:
diff changeset
176 self.last_levels_sent = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
177 self.current_dmx_levels = [0] * 68
45b12307c695 Initial revision
drewp
parents:
diff changeset
178 self.after(0, self.send_dmx_levels_loop) # start DMX sending loop
45b12307c695 Initial revision
drewp
parents:
diff changeset
179
45b12307c695 Initial revision
drewp
parents:
diff changeset
180 # this is a mechanism to stop Tk from autoshifting too much.
45b12307c695 Initial revision
drewp
parents:
diff changeset
181 # if this variable is true, the mouse button is down. we don't want
45b12307c695 Initial revision
drewp
parents:
diff changeset
182 # to shift until they release it. when it is released, we will
45b12307c695 Initial revision
drewp
parents:
diff changeset
183 # set it to false and then call autoshift.
45b12307c695 Initial revision
drewp
parents:
diff changeset
184 self.no_shifts_until_release = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
185
45b12307c695 Initial revision
drewp
parents:
diff changeset
186 self.scales = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
187 self.shift_buttons = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
188 self.go_buttons = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
189
45b12307c695 Initial revision
drewp
parents:
diff changeset
190 topframe = Tk.Frame(self, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
191
45b12307c695 Initial revision
drewp
parents:
diff changeset
192 self.set_prev_button = Tk.Button(topframe, text='Set Prev',
45b12307c695 Initial revision
drewp
parents:
diff changeset
193 command=lambda: cuelist.set_selection_as_prev(),
45b12307c695 Initial revision
drewp
parents:
diff changeset
194 fg='white', bg='blue')
45b12307c695 Initial revision
drewp
parents:
diff changeset
195 self.set_prev_button.pack(side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
196
45b12307c695 Initial revision
drewp
parents:
diff changeset
197 self.auto_shift = Tk.IntVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
198 self.auto_shift.set(1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
199
45b12307c695 Initial revision
drewp
parents:
diff changeset
200 self.auto_shift_checkbutton = Tk.Checkbutton(topframe,
45b12307c695 Initial revision
drewp
parents:
diff changeset
201 variable=self.auto_shift, text='Autoshift',
45b12307c695 Initial revision
drewp
parents:
diff changeset
202 command=self.toggle_autoshift, bg='black', fg='white',
45b12307c695 Initial revision
drewp
parents:
diff changeset
203 highlightbackground='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
204 self.auto_shift_checkbutton.pack(fill='both', side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
205
45b12307c695 Initial revision
drewp
parents:
diff changeset
206 self.auto_load_times = Tk.IntVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
207 self.auto_load_times.set(1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
208
45b12307c695 Initial revision
drewp
parents:
diff changeset
209 self.auto_load_times_checkbutton = Tk.Checkbutton(topframe,
45b12307c695 Initial revision
drewp
parents:
diff changeset
210 variable=self.auto_load_times, text='Autoload Times',
45b12307c695 Initial revision
drewp
parents:
diff changeset
211 bg='black', fg='white',
45b12307c695 Initial revision
drewp
parents:
diff changeset
212 highlightbackground='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
213 self.auto_load_times_checkbutton.pack(fill='both', side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
214
45b12307c695 Initial revision
drewp
parents:
diff changeset
215 self.mute = Tk.IntVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
216 self.mute.set(0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
217
45b12307c695 Initial revision
drewp
parents:
diff changeset
218 self.mutebutton = Tk.Checkbutton(topframe,
45b12307c695 Initial revision
drewp
parents:
diff changeset
219 variable=self.mute, text='Mute',
45b12307c695 Initial revision
drewp
parents:
diff changeset
220 bg='black', fg='white',
45b12307c695 Initial revision
drewp
parents:
diff changeset
221 highlightbackground='black',
45b12307c695 Initial revision
drewp
parents:
diff changeset
222 command=self.send_dmx_levels)
45b12307c695 Initial revision
drewp
parents:
diff changeset
223 self.mutebutton.pack(fill='both', side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
224
45b12307c695 Initial revision
drewp
parents:
diff changeset
225 self.set_next_button = Tk.Button(topframe, text='Set Next',
45b12307c695 Initial revision
drewp
parents:
diff changeset
226 command=lambda: cuelist.set_selection_as_next(),
45b12307c695 Initial revision
drewp
parents:
diff changeset
227 fg='white', bg='red')
45b12307c695 Initial revision
drewp
parents:
diff changeset
228 self.set_next_button.pack(side='left')
45b12307c695 Initial revision
drewp
parents:
diff changeset
229
45b12307c695 Initial revision
drewp
parents:
diff changeset
230 topframe.pack(side='top')
45b12307c695 Initial revision
drewp
parents:
diff changeset
231
45b12307c695 Initial revision
drewp
parents:
diff changeset
232 faderframe = Tk.Frame(self, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
233 self.direction_info = (('Prev', 1, 0, 'left', 'blue'),
45b12307c695 Initial revision
drewp
parents:
diff changeset
234 ('Next', 0, 1, 'right', 'red'))
45b12307c695 Initial revision
drewp
parents:
diff changeset
235 for name, start, end, side, color in self.direction_info:
45b12307c695 Initial revision
drewp
parents:
diff changeset
236 frame = Tk.Frame(self, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
237 scale = LabelledScale(frame, name, from_=start, to_=end,
45b12307c695 Initial revision
drewp
parents:
diff changeset
238 res=0.0001, orient='horiz', flashtroughcolor=color,
45b12307c695 Initial revision
drewp
parents:
diff changeset
239 labelformatter=lambda val, name=name: self.get_scale_desc(val,
45b12307c695 Initial revision
drewp
parents:
diff changeset
240 name))
45b12307c695 Initial revision
drewp
parents:
diff changeset
241 scale.pack(fill='x', expand=0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
242 go = TimedGoButton(frame, 'Go %s' % name, scale, bg=color,
45b12307c695 Initial revision
drewp
parents:
diff changeset
243 fg='white', width=10)
45b12307c695 Initial revision
drewp
parents:
diff changeset
244 go.pack(fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
245 frame.pack(side=side, fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
246
45b12307c695 Initial revision
drewp
parents:
diff changeset
247 shift = Tk.Button(frame, text="Shift %s" % name, state='disabled',
45b12307c695 Initial revision
drewp
parents:
diff changeset
248 command=lambda name=name: self.shift(name), fg=color,
45b12307c695 Initial revision
drewp
parents:
diff changeset
249 bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
250
45b12307c695 Initial revision
drewp
parents:
diff changeset
251 self.scales[name] = scale
45b12307c695 Initial revision
drewp
parents:
diff changeset
252 self.shift_buttons[name] = shift
45b12307c695 Initial revision
drewp
parents:
diff changeset
253 self.go_buttons[name] = go
45b12307c695 Initial revision
drewp
parents:
diff changeset
254
45b12307c695 Initial revision
drewp
parents:
diff changeset
255 scale.scale_var.trace('w', \
45b12307c695 Initial revision
drewp
parents:
diff changeset
256 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale))
45b12307c695 Initial revision
drewp
parents:
diff changeset
257 go.timer_var.trace('w',
45b12307c695 Initial revision
drewp
parents:
diff changeset
258 lambda x, y, z, scale=scale: scale.update_value_label())
45b12307c695 Initial revision
drewp
parents:
diff changeset
259
45b12307c695 Initial revision
drewp
parents:
diff changeset
260 def button_press(event, name=name, scale=scale):
45b12307c695 Initial revision
drewp
parents:
diff changeset
261 self.no_shifts_until_release = 1 # prevent shifts until release
45b12307c695 Initial revision
drewp
parents:
diff changeset
262 def button_release(event, name=name, scale=scale):
45b12307c695 Initial revision
drewp
parents:
diff changeset
263 self.no_shifts_until_release = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
264 self.autoshift(name, scale)
45b12307c695 Initial revision
drewp
parents:
diff changeset
265
45b12307c695 Initial revision
drewp
parents:
diff changeset
266 scale.scale.bind("<ButtonPress>", button_press)
45b12307c695 Initial revision
drewp
parents:
diff changeset
267 scale.scale.bind("<ButtonRelease>", button_release)
45b12307c695 Initial revision
drewp
parents:
diff changeset
268 faderframe.pack(side='bottom', fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
269
45b12307c695 Initial revision
drewp
parents:
diff changeset
270 self.current_dir = 'Next'
45b12307c695 Initial revision
drewp
parents:
diff changeset
271 self.cues_as_subs = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
272 self.update_cue_cache()
45b12307c695 Initial revision
drewp
parents:
diff changeset
273 def reload_cue_times(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
274 prev, cur, next = self.cuelist.get_current_cues()
45b12307c695 Initial revision
drewp
parents:
diff changeset
275 self.go_buttons['Next'].set_time(next.time)
45b12307c695 Initial revision
drewp
parents:
diff changeset
276 def update_cue_cache(self, compute_dmx_levels=1):
45b12307c695 Initial revision
drewp
parents:
diff changeset
277 """Rebuilds subs from the current cues. As this is expensive, we don't
45b12307c695 Initial revision
drewp
parents:
diff changeset
278 do it unless necessary (i.e. whenever we shift or a cue is edited)"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
279 # print "update_cue_cache"
45b12307c695 Initial revision
drewp
parents:
diff changeset
280 # load the subs to fade between
45b12307c695 Initial revision
drewp
parents:
diff changeset
281 for cue, name in zip(self.cuelist.get_current_cues(),
45b12307c695 Initial revision
drewp
parents:
diff changeset
282 ('Prev', 'Cur', 'Next')):
45b12307c695 Initial revision
drewp
parents:
diff changeset
283 self.cues_as_subs[name] = cue.get_levels_as_sub()
45b12307c695 Initial revision
drewp
parents:
diff changeset
284 if compute_dmx_levels:
45b12307c695 Initial revision
drewp
parents:
diff changeset
285 self.compute_dmx_levels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
286 def compute_dmx_levels(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
287 """Compute the DMX levels to send. This should get called whenever the
45b12307c695 Initial revision
drewp
parents:
diff changeset
288 DMX levels could change: either during a crossfade or when a cue is
45b12307c695 Initial revision
drewp
parents:
diff changeset
289 edited. Since this is called when we know that a change might occur,
45b12307c695 Initial revision
drewp
parents:
diff changeset
290 we will send the new levels too."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
291 cur_sub = self.cues_as_subs.get('Cur')
45b12307c695 Initial revision
drewp
parents:
diff changeset
292 if cur_sub:
45b12307c695 Initial revision
drewp
parents:
diff changeset
293 scale = self.scales[self.current_dir]
45b12307c695 Initial revision
drewp
parents:
diff changeset
294 scale_val = scale.scale_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
295
45b12307c695 Initial revision
drewp
parents:
diff changeset
296 other_sub = self.cues_as_subs[self.current_dir]
45b12307c695 Initial revision
drewp
parents:
diff changeset
297 current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val)
45b12307c695 Initial revision
drewp
parents:
diff changeset
298 self.current_dmx_levels = current_levels_as_sub.get_dmx_list()
45b12307c695 Initial revision
drewp
parents:
diff changeset
299 self.send_dmx_levels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
300
45b12307c695 Initial revision
drewp
parents:
diff changeset
301 # print "compute_dmx_levels: fade at", scale_val
45b12307c695 Initial revision
drewp
parents:
diff changeset
302 # print "between", cur_sub.name,
45b12307c695 Initial revision
drewp
parents:
diff changeset
303 # print "and", other_sub.name
45b12307c695 Initial revision
drewp
parents:
diff changeset
304 # print
45b12307c695 Initial revision
drewp
parents:
diff changeset
305 def send_dmx_levels(self, *args):
45b12307c695 Initial revision
drewp
parents:
diff changeset
306 # print "send_dmx_levels", self.current_dmx_levels
45b12307c695 Initial revision
drewp
parents:
diff changeset
307 if self.mute.get():
45b12307c695 Initial revision
drewp
parents:
diff changeset
308 dmxclient.outputlevels([0] * 68)
45b12307c695 Initial revision
drewp
parents:
diff changeset
309 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
310 dmxclient.outputlevels(self.current_dmx_levels)
45b12307c695 Initial revision
drewp
parents:
diff changeset
311 self.last_levels_sent = time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
312 def send_dmx_levels_loop(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
313 diff = time.time() - self.last_levels_sent
45b12307c695 Initial revision
drewp
parents:
diff changeset
314 if diff >= 2: # too long since last send
45b12307c695 Initial revision
drewp
parents:
diff changeset
315 self.send_dmx_levels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
316 self.after(200, self.send_dmx_levels_loop)
45b12307c695 Initial revision
drewp
parents:
diff changeset
317 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
318 self.after(int((2 - diff) * 100), self.send_dmx_levels_loop)
45b12307c695 Initial revision
drewp
parents:
diff changeset
319 def get_scale_desc(self, val, name):
45b12307c695 Initial revision
drewp
parents:
diff changeset
320 """Returns a description to the TimedGoButton"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
321 go_button = self.go_buttons.get(name)
45b12307c695 Initial revision
drewp
parents:
diff changeset
322 if go_button:
45b12307c695 Initial revision
drewp
parents:
diff changeset
323 time = go_button.get_time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
324 return "%0.2f%%, %0.1fs left" % (val, time - ((val / 100.0) * time))
45b12307c695 Initial revision
drewp
parents:
diff changeset
325 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
326 return "%0.2f%%" % val
45b12307c695 Initial revision
drewp
parents:
diff changeset
327 def toggle_autoshift(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
328 for name, button in self.shift_buttons.items():
45b12307c695 Initial revision
drewp
parents:
diff changeset
329 if not self.auto_shift.get():
45b12307c695 Initial revision
drewp
parents:
diff changeset
330 button.pack(side='bottom', fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
331 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
332 button.pack_forget()
45b12307c695 Initial revision
drewp
parents:
diff changeset
333 def shift(self, name):
45b12307c695 Initial revision
drewp
parents:
diff changeset
334 # to prevent overshifting
45b12307c695 Initial revision
drewp
parents:
diff changeset
335 if self.no_shifts_until_release:
45b12307c695 Initial revision
drewp
parents:
diff changeset
336 return
45b12307c695 Initial revision
drewp
parents:
diff changeset
337 # print "shift", name
45b12307c695 Initial revision
drewp
parents:
diff changeset
338
45b12307c695 Initial revision
drewp
parents:
diff changeset
339 self.cuelist.shift((-1, 1)[name == 'Next'])
45b12307c695 Initial revision
drewp
parents:
diff changeset
340 self.update_cue_cache(compute_dmx_levels=0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
341 for scale_name, scale in self.scales.items():
45b12307c695 Initial revision
drewp
parents:
diff changeset
342 # print "shift: setting scale to 0", scale_name
45b12307c695 Initial revision
drewp
parents:
diff changeset
343 scale.scale.set(0)
45b12307c695 Initial revision
drewp
parents:
diff changeset
344 self.go_buttons[scale_name].manual_override()
45b12307c695 Initial revision
drewp
parents:
diff changeset
345 self.update_cue_cache(compute_dmx_levels=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
346
45b12307c695 Initial revision
drewp
parents:
diff changeset
347 if self.auto_load_times.get():
45b12307c695 Initial revision
drewp
parents:
diff changeset
348 self.reload_cue_times()
45b12307c695 Initial revision
drewp
parents:
diff changeset
349 def autoshift(self, name, scale):
45b12307c695 Initial revision
drewp
parents:
diff changeset
350 scale_val = scale.scale_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
351
45b12307c695 Initial revision
drewp
parents:
diff changeset
352 if scale_val == 1:
45b12307c695 Initial revision
drewp
parents:
diff changeset
353 if self.auto_shift.get():
45b12307c695 Initial revision
drewp
parents:
diff changeset
354 self.shift(name)
45b12307c695 Initial revision
drewp
parents:
diff changeset
355 def xfade(self, name, scale):
45b12307c695 Initial revision
drewp
parents:
diff changeset
356 if self.auto_shift.get():
45b12307c695 Initial revision
drewp
parents:
diff changeset
357 self.autoshift(name, scale)
45b12307c695 Initial revision
drewp
parents:
diff changeset
358 scale_val = scale.scale_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
359 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
360 scale_val = scale.scale_var.get()
45b12307c695 Initial revision
drewp
parents:
diff changeset
361 if scale_val == 1:
45b12307c695 Initial revision
drewp
parents:
diff changeset
362 self.shift_buttons[name]['state'] = 'normal'
45b12307c695 Initial revision
drewp
parents:
diff changeset
363 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
364 # disable any dangerous shifting
45b12307c695 Initial revision
drewp
parents:
diff changeset
365 self.shift_buttons[name]['state'] = 'disabled'
45b12307c695 Initial revision
drewp
parents:
diff changeset
366
45b12307c695 Initial revision
drewp
parents:
diff changeset
367 d = self.opposite_direction(name)
45b12307c695 Initial revision
drewp
parents:
diff changeset
368 if scale_val != 0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
369 # disable illegal three part crossfades
45b12307c695 Initial revision
drewp
parents:
diff changeset
370 self.scales[d].disable()
45b12307c695 Initial revision
drewp
parents:
diff changeset
371 self.go_buttons[d].disable()
45b12307c695 Initial revision
drewp
parents:
diff changeset
372 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
373 # undo above work
45b12307c695 Initial revision
drewp
parents:
diff changeset
374 self.scales[d].enable()
45b12307c695 Initial revision
drewp
parents:
diff changeset
375 self.go_buttons[d].enable()
45b12307c695 Initial revision
drewp
parents:
diff changeset
376
45b12307c695 Initial revision
drewp
parents:
diff changeset
377 self.current_dir = name
45b12307c695 Initial revision
drewp
parents:
diff changeset
378 self.compute_dmx_levels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
379 def opposite_direction(self, d):
45b12307c695 Initial revision
drewp
parents:
diff changeset
380 if d == 'Next':
45b12307c695 Initial revision
drewp
parents:
diff changeset
381 return 'Prev'
45b12307c695 Initial revision
drewp
parents:
diff changeset
382 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
383 return 'Next'
45b12307c695 Initial revision
drewp
parents:
diff changeset
384
45b12307c695 Initial revision
drewp
parents:
diff changeset
385 class Cue:
45b12307c695 Initial revision
drewp
parents:
diff changeset
386 """A Cue has a name, a time, and any number of other attributes."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
387 def __init__(self, name, time=3, sub_levels='', **attrs):
45b12307c695 Initial revision
drewp
parents:
diff changeset
388 self.name = name
45b12307c695 Initial revision
drewp
parents:
diff changeset
389 self.time = time
45b12307c695 Initial revision
drewp
parents:
diff changeset
390 self.sub_levels = sub_levels
45b12307c695 Initial revision
drewp
parents:
diff changeset
391 self.__dict__.update(attrs)
45b12307c695 Initial revision
drewp
parents:
diff changeset
392 def __repr__(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
393 return "<Cue %s, length %s>" % (self.name, self.time)
45b12307c695 Initial revision
drewp
parents:
diff changeset
394 def get_levels_as_sub(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
395 """Get this Cue as a combined Submaster, normalized. This method
45b12307c695 Initial revision
drewp
parents:
diff changeset
396 should not be called constantly, since it is somewhat expensive. It
45b12307c695 Initial revision
drewp
parents:
diff changeset
397 will reload the submasters from disk, combine all subs together, and
45b12307c695 Initial revision
drewp
parents:
diff changeset
398 then compute the normalized form."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
399 subdict = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
400 for line in self.sub_levels.split(','):
45b12307c695 Initial revision
drewp
parents:
diff changeset
401 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
402 line = line.strip()
45b12307c695 Initial revision
drewp
parents:
diff changeset
403 if not line:
45b12307c695 Initial revision
drewp
parents:
diff changeset
404 continue
45b12307c695 Initial revision
drewp
parents:
diff changeset
405 sub, scale = line.split(':')
45b12307c695 Initial revision
drewp
parents:
diff changeset
406 sub = sub.strip()
45b12307c695 Initial revision
drewp
parents:
diff changeset
407 scale = float(scale)
45b12307c695 Initial revision
drewp
parents:
diff changeset
408 subdict[sub] = scale
45b12307c695 Initial revision
drewp
parents:
diff changeset
409 except ValueError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
410 print "Parsing error for '%s' in %s" % (self.sub_levels, self)
45b12307c695 Initial revision
drewp
parents:
diff changeset
411
45b12307c695 Initial revision
drewp
parents:
diff changeset
412 s = Submaster.Submasters()
45b12307c695 Initial revision
drewp
parents:
diff changeset
413 newsub = Submaster.sub_maxes(*[s[sub] * scale
45b12307c695 Initial revision
drewp
parents:
diff changeset
414 for sub, scale in subdict.items()])
45b12307c695 Initial revision
drewp
parents:
diff changeset
415 return newsub.get_normalized_copy()
45b12307c695 Initial revision
drewp
parents:
diff changeset
416
45b12307c695 Initial revision
drewp
parents:
diff changeset
417 empty_cue = Cue('empty')
45b12307c695 Initial revision
drewp
parents:
diff changeset
418
45b12307c695 Initial revision
drewp
parents:
diff changeset
419 allow_class_to_be_pickled(Cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
420
45b12307c695 Initial revision
drewp
parents:
diff changeset
421 class CueList:
45b12307c695 Initial revision
drewp
parents:
diff changeset
422 """Persistent list of Cues"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
423 def __init__(self, filename):
45b12307c695 Initial revision
drewp
parents:
diff changeset
424 self.filename = filename
45b12307c695 Initial revision
drewp
parents:
diff changeset
425 self.treedict = TreeDict()
45b12307c695 Initial revision
drewp
parents:
diff changeset
426 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
427 self.treedict.load(filename)
45b12307c695 Initial revision
drewp
parents:
diff changeset
428 except IOError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
429 self.treedict.cues = []
45b12307c695 Initial revision
drewp
parents:
diff changeset
430 self.cues = self.treedict.cues
45b12307c695 Initial revision
drewp
parents:
diff changeset
431 self.current_cue_index = -1
45b12307c695 Initial revision
drewp
parents:
diff changeset
432 self.next_pointer = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
433 self.prev_pointer = None
45b12307c695 Initial revision
drewp
parents:
diff changeset
434
45b12307c695 Initial revision
drewp
parents:
diff changeset
435 import atexit
45b12307c695 Initial revision
drewp
parents:
diff changeset
436 atexit.register(self.save)
45b12307c695 Initial revision
drewp
parents:
diff changeset
437 def add_cue(self, cue, index=None):
45b12307c695 Initial revision
drewp
parents:
diff changeset
438 """Adds a Cue object to the list. If no index is specified,
45b12307c695 Initial revision
drewp
parents:
diff changeset
439 the cue will be added to the end."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
440 index = index or len(self.cues)
45b12307c695 Initial revision
drewp
parents:
diff changeset
441 self.cues.insert(index, cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
442 def shift(self, diff):
45b12307c695 Initial revision
drewp
parents:
diff changeset
443 """Shift through cue history"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
444 old_index = self.current_cue_index
45b12307c695 Initial revision
drewp
parents:
diff changeset
445 self.current_cue_index = None
45b12307c695 Initial revision
drewp
parents:
diff changeset
446 if diff < 0: # if going backwards
45b12307c695 Initial revision
drewp
parents:
diff changeset
447 if self.prev_pointer: # use a prev pointer if we have one
45b12307c695 Initial revision
drewp
parents:
diff changeset
448 self.current_cue_index = self.prev_pointer
45b12307c695 Initial revision
drewp
parents:
diff changeset
449 self.next_pointer = old_index
45b12307c695 Initial revision
drewp
parents:
diff changeset
450 self.prev_pointer = None
45b12307c695 Initial revision
drewp
parents:
diff changeset
451 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
452 if self.next_pointer: # use a next pointer if we have one
45b12307c695 Initial revision
drewp
parents:
diff changeset
453 self.current_cue_index = self.next_pointer
45b12307c695 Initial revision
drewp
parents:
diff changeset
454 self.next_pointer = None
45b12307c695 Initial revision
drewp
parents:
diff changeset
455 self.prev_pointer = old_index
45b12307c695 Initial revision
drewp
parents:
diff changeset
456 if not self.current_cue_index:
45b12307c695 Initial revision
drewp
parents:
diff changeset
457 self.current_cue_index = old_index + diff
45b12307c695 Initial revision
drewp
parents:
diff changeset
458 def set_next(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
459 self.next_pointer = index
45b12307c695 Initial revision
drewp
parents:
diff changeset
460 def set_prev(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
461 self.prev_pointer = index
45b12307c695 Initial revision
drewp
parents:
diff changeset
462 def bound_index(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
463 if not self.cues or index < 0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
464 return None
45b12307c695 Initial revision
drewp
parents:
diff changeset
465 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
466 return min(index, len(self.cues) - 1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
467 def get_current_cue_indices(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
468 """Returns a list of the indices of three cues: the previous cue,
45b12307c695 Initial revision
drewp
parents:
diff changeset
469 the current cue, and the next cue."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
470 cur = self.current_cue_index
45b12307c695 Initial revision
drewp
parents:
diff changeset
471 return [self.bound_index(index) for index in
45b12307c695 Initial revision
drewp
parents:
diff changeset
472 (self.prev_pointer or cur - 1,
45b12307c695 Initial revision
drewp
parents:
diff changeset
473 cur,
45b12307c695 Initial revision
drewp
parents:
diff changeset
474 self.next_pointer or cur + 1)]
45b12307c695 Initial revision
drewp
parents:
diff changeset
475 def get_current_cues(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
476 """Returns a list of three cues: the previous cue, the current cue,
45b12307c695 Initial revision
drewp
parents:
diff changeset
477 and the next cue."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
478 return [self.get_cue_by_index(index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
479 for index in self.get_current_cue_indices()]
45b12307c695 Initial revision
drewp
parents:
diff changeset
480 def get_cue_by_index(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
481 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
482 return self.cues[self.bound_index(index)]
45b12307c695 Initial revision
drewp
parents:
diff changeset
483 except TypeError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
484 return empty_cue
45b12307c695 Initial revision
drewp
parents:
diff changeset
485 def __del__(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
486 self.save()
45b12307c695 Initial revision
drewp
parents:
diff changeset
487 def save(self, backup=0):
45b12307c695 Initial revision
drewp
parents:
diff changeset
488 if backup:
45b12307c695 Initial revision
drewp
parents:
diff changeset
489
45b12307c695 Initial revision
drewp
parents:
diff changeset
490 backupfilename = "%s-backup" % self.filename
45b12307c695 Initial revision
drewp
parents:
diff changeset
491 print time.asctime(), "Saving backup version of cues to", \
45b12307c695 Initial revision
drewp
parents:
diff changeset
492 backupfilename
45b12307c695 Initial revision
drewp
parents:
diff changeset
493 self.treedict.save(backupfilename)
45b12307c695 Initial revision
drewp
parents:
diff changeset
494 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
495 print time.asctime(), "Saving cues to", self.filename
45b12307c695 Initial revision
drewp
parents:
diff changeset
496 self.treedict.save(self.filename)
45b12307c695 Initial revision
drewp
parents:
diff changeset
497 def reload(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
498 # TODO: we probably will need to make sure that indices still make
45b12307c695 Initial revision
drewp
parents:
diff changeset
499 # sense, etc.
45b12307c695 Initial revision
drewp
parents:
diff changeset
500 self.treedict.load(self.filename)
45b12307c695 Initial revision
drewp
parents:
diff changeset
501
45b12307c695 Initial revision
drewp
parents:
diff changeset
502 class TkCueList(CueList, Tk.Frame):
45b12307c695 Initial revision
drewp
parents:
diff changeset
503 def __init__(self, master, filename):
45b12307c695 Initial revision
drewp
parents:
diff changeset
504 CueList.__init__(self, filename)
45b12307c695 Initial revision
drewp
parents:
diff changeset
505 Tk.Frame.__init__(self, master, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
506 self.fader = None
45b12307c695 Initial revision
drewp
parents:
diff changeset
507
45b12307c695 Initial revision
drewp
parents:
diff changeset
508 self.edit_tl = Tk.Toplevel()
45b12307c695 Initial revision
drewp
parents:
diff changeset
509 self.editor = CueEditron(self.edit_tl,
45b12307c695 Initial revision
drewp
parents:
diff changeset
510 changed_callback=self.cue_changed)
45b12307c695 Initial revision
drewp
parents:
diff changeset
511 self.editor.pack(fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
512
45b12307c695 Initial revision
drewp
parents:
diff changeset
513 def edit_cue(index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
514 index = int(index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
515 self.editor.set_cue_to_edit(self.cues[index])
45b12307c695 Initial revision
drewp
parents:
diff changeset
516
45b12307c695 Initial revision
drewp
parents:
diff changeset
517 self.columns = ('name', 'time', 'page', 'cuenum', 'desc', 'sub_levels')
45b12307c695 Initial revision
drewp
parents:
diff changeset
518 self.scrolled_hlist = Tk.ScrolledHList(self,
45b12307c695 Initial revision
drewp
parents:
diff changeset
519 options='hlist.columns %d hlist.header 1' % len(self.columns))
45b12307c695 Initial revision
drewp
parents:
diff changeset
520 self.hlist = self.scrolled_hlist.hlist
45b12307c695 Initial revision
drewp
parents:
diff changeset
521 self.hlist.configure(fg='white', bg='black',
45b12307c695 Initial revision
drewp
parents:
diff changeset
522 command=self.select_callback, browsecmd=edit_cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
523 self.hlist.bind("<4>", self.wheelscroll)
45b12307c695 Initial revision
drewp
parents:
diff changeset
524 self.hlist.bind("<5>", self.wheelscroll)
45b12307c695 Initial revision
drewp
parents:
diff changeset
525 self.scrolled_hlist.pack(fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
526
45b12307c695 Initial revision
drewp
parents:
diff changeset
527 boldfont = self.tk.call('tix', 'option', 'get',
45b12307c695 Initial revision
drewp
parents:
diff changeset
528 'bold_font')
45b12307c695 Initial revision
drewp
parents:
diff changeset
529 header_style = Tk.DisplayStyle('text', refwindow=self,
45b12307c695 Initial revision
drewp
parents:
diff changeset
530 anchor='center', padx=8, pady=2, font=boldfont)
45b12307c695 Initial revision
drewp
parents:
diff changeset
531
45b12307c695 Initial revision
drewp
parents:
diff changeset
532 for count, header in enumerate(self.columns):
45b12307c695 Initial revision
drewp
parents:
diff changeset
533 self.hlist.header_create(count, itemtype='text',
45b12307c695 Initial revision
drewp
parents:
diff changeset
534 text=header, style=header_style)
45b12307c695 Initial revision
drewp
parents:
diff changeset
535
45b12307c695 Initial revision
drewp
parents:
diff changeset
536 self.cue_label_windows = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
537 for count, cue in enumerate(self.cues):
45b12307c695 Initial revision
drewp
parents:
diff changeset
538 self.display_cue(count, cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
539 self.update_cue_indicators()
45b12307c695 Initial revision
drewp
parents:
diff changeset
540 self.save_loop()
45b12307c695 Initial revision
drewp
parents:
diff changeset
541 def set_fader(self, fader):
45b12307c695 Initial revision
drewp
parents:
diff changeset
542 self.fader = fader
45b12307c695 Initial revision
drewp
parents:
diff changeset
543 def wheelscroll(self, evt):
45b12307c695 Initial revision
drewp
parents:
diff changeset
544 """Perform mouse wheel scrolling"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
545 if evt.num == 4: # scroll down
45b12307c695 Initial revision
drewp
parents:
diff changeset
546 amount = -2
45b12307c695 Initial revision
drewp
parents:
diff changeset
547 else: # scroll up
45b12307c695 Initial revision
drewp
parents:
diff changeset
548 amount = 2
45b12307c695 Initial revision
drewp
parents:
diff changeset
549 self.hlist.yview('scroll', amount, 'units')
45b12307c695 Initial revision
drewp
parents:
diff changeset
550 def cue_changed(self, cue):
45b12307c695 Initial revision
drewp
parents:
diff changeset
551 path = self.cues.index(cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
552 for col, header in enumerate(self.columns):
45b12307c695 Initial revision
drewp
parents:
diff changeset
553 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
554 text = getattr(cue, header)
45b12307c695 Initial revision
drewp
parents:
diff changeset
555 except AttributeError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
556 text = ''
45b12307c695 Initial revision
drewp
parents:
diff changeset
557
45b12307c695 Initial revision
drewp
parents:
diff changeset
558 if col == 0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
559 self.cue_label_windows[path]['text'] = text
45b12307c695 Initial revision
drewp
parents:
diff changeset
560 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
561 self.hlist.item_configure(path, col, text=text)
45b12307c695 Initial revision
drewp
parents:
diff changeset
562
45b12307c695 Initial revision
drewp
parents:
diff changeset
563 if cue in self.get_current_cues() and self.fader:
45b12307c695 Initial revision
drewp
parents:
diff changeset
564 self.fader.update_cue_cache()
45b12307c695 Initial revision
drewp
parents:
diff changeset
565 self.fader.reload_cue_times()
45b12307c695 Initial revision
drewp
parents:
diff changeset
566 def display_cue(self, path, cue):
45b12307c695 Initial revision
drewp
parents:
diff changeset
567 for col, header in enumerate(self.columns):
45b12307c695 Initial revision
drewp
parents:
diff changeset
568 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
569 text = getattr(cue, header)
45b12307c695 Initial revision
drewp
parents:
diff changeset
570 except AttributeError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
571 text = ''
45b12307c695 Initial revision
drewp
parents:
diff changeset
572
45b12307c695 Initial revision
drewp
parents:
diff changeset
573 if col == 0:
45b12307c695 Initial revision
drewp
parents:
diff changeset
574 lab = Tk.Label(self.hlist, text=text, fg='white', bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
575 def select_and_highlight(event):
45b12307c695 Initial revision
drewp
parents:
diff changeset
576 self.select_callback(path)
45b12307c695 Initial revision
drewp
parents:
diff changeset
577 self.hlist.selection_clear()
45b12307c695 Initial revision
drewp
parents:
diff changeset
578 self.hlist.selection_set(path)
45b12307c695 Initial revision
drewp
parents:
diff changeset
579
45b12307c695 Initial revision
drewp
parents:
diff changeset
580 lab.bind("<Double-1>", select_and_highlight)
45b12307c695 Initial revision
drewp
parents:
diff changeset
581 self.hlist.add(path, itemtype='window', window=lab)
45b12307c695 Initial revision
drewp
parents:
diff changeset
582 self.cue_label_windows[path] = lab
45b12307c695 Initial revision
drewp
parents:
diff changeset
583 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
584 self.hlist.item_create(path, col, text=text)
45b12307c695 Initial revision
drewp
parents:
diff changeset
585 def reset_cue_indicators(self, cue_indices=None):
45b12307c695 Initial revision
drewp
parents:
diff changeset
586 """If cue_indices is None, we'll reset all of them."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
587 cue_indices = cue_indices or self.cue_label_windows.keys()
45b12307c695 Initial revision
drewp
parents:
diff changeset
588 for key in cue_indices:
45b12307c695 Initial revision
drewp
parents:
diff changeset
589 if key is None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
590 continue
45b12307c695 Initial revision
drewp
parents:
diff changeset
591 window = self.cue_label_windows[key]
45b12307c695 Initial revision
drewp
parents:
diff changeset
592 window.configure(fg='white', bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
593 def update_cue_indicators(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
594 states = dict(zip(self.get_current_cue_indices(),
45b12307c695 Initial revision
drewp
parents:
diff changeset
595 ('prev', 'cur', 'next')))
45b12307c695 Initial revision
drewp
parents:
diff changeset
596
45b12307c695 Initial revision
drewp
parents:
diff changeset
597 for count, state in states.items():
45b12307c695 Initial revision
drewp
parents:
diff changeset
598 if count is None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
599 continue
45b12307c695 Initial revision
drewp
parents:
diff changeset
600 window = self.cue_label_windows[count]
45b12307c695 Initial revision
drewp
parents:
diff changeset
601 bg, fg = cue_state_indicator_colors[state]
45b12307c695 Initial revision
drewp
parents:
diff changeset
602 window.configure(bg=bg, fg=fg)
45b12307c695 Initial revision
drewp
parents:
diff changeset
603 def shift(self, diff):
45b12307c695 Initial revision
drewp
parents:
diff changeset
604 self.reset_cue_indicators(self.get_current_cue_indices())
45b12307c695 Initial revision
drewp
parents:
diff changeset
605 CueList.shift(self, diff)
45b12307c695 Initial revision
drewp
parents:
diff changeset
606 self.update_cue_indicators()
45b12307c695 Initial revision
drewp
parents:
diff changeset
607 # try to see all indices, but next takes priority over all, and cur
45b12307c695 Initial revision
drewp
parents:
diff changeset
608 # over prev
45b12307c695 Initial revision
drewp
parents:
diff changeset
609 for index in self.get_current_cue_indices():
45b12307c695 Initial revision
drewp
parents:
diff changeset
610 if index is not None:
45b12307c695 Initial revision
drewp
parents:
diff changeset
611 self.hlist.see(index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
612 def select_callback(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
613 new_next = int(index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
614 self.set_next(new_next)
45b12307c695 Initial revision
drewp
parents:
diff changeset
615 def set_next(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
616 prev, cur, next = self.get_current_cue_indices()
45b12307c695 Initial revision
drewp
parents:
diff changeset
617 self.reset_cue_indicators((next,))
45b12307c695 Initial revision
drewp
parents:
diff changeset
618 CueList.set_next(self, index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
619 self.update_cue_indicators()
45b12307c695 Initial revision
drewp
parents:
diff changeset
620
45b12307c695 Initial revision
drewp
parents:
diff changeset
621 if self.fader: # XXX this is untested
45b12307c695 Initial revision
drewp
parents:
diff changeset
622 self.fader.update_cue_cache()
45b12307c695 Initial revision
drewp
parents:
diff changeset
623 def set_prev(self, index):
45b12307c695 Initial revision
drewp
parents:
diff changeset
624 prev, cur, next = self.get_current_cue_indices()
45b12307c695 Initial revision
drewp
parents:
diff changeset
625 self.reset_cue_indicators((prev,))
45b12307c695 Initial revision
drewp
parents:
diff changeset
626 CueList.set_prev(self, index)
45b12307c695 Initial revision
drewp
parents:
diff changeset
627 self.update_cue_indicators()
45b12307c695 Initial revision
drewp
parents:
diff changeset
628
45b12307c695 Initial revision
drewp
parents:
diff changeset
629 if self.fader: # XXX this is untested
45b12307c695 Initial revision
drewp
parents:
diff changeset
630 self.fader.update_cue_cache()
45b12307c695 Initial revision
drewp
parents:
diff changeset
631 def set_selection_as_prev(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
632 sel = self.hlist.info_selection()
45b12307c695 Initial revision
drewp
parents:
diff changeset
633 if sel:
45b12307c695 Initial revision
drewp
parents:
diff changeset
634 self.set_prev(int(sel[0]))
45b12307c695 Initial revision
drewp
parents:
diff changeset
635 def set_selection_as_next(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
636 sel = self.hlist.info_selection()
45b12307c695 Initial revision
drewp
parents:
diff changeset
637 if sel:
45b12307c695 Initial revision
drewp
parents:
diff changeset
638 self.set_next(int(sel[0]))
45b12307c695 Initial revision
drewp
parents:
diff changeset
639 def save_loop(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
640 """This saves the CueList every minute."""
45b12307c695 Initial revision
drewp
parents:
diff changeset
641 self.save(backup=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
642 self.after(60000, self.save_loop)
45b12307c695 Initial revision
drewp
parents:
diff changeset
643
45b12307c695 Initial revision
drewp
parents:
diff changeset
644 class CueEditron(Tk.Frame):
45b12307c695 Initial revision
drewp
parents:
diff changeset
645 def __init__(self, master, changed_callback=None, cue=None):
45b12307c695 Initial revision
drewp
parents:
diff changeset
646 Tk.Frame.__init__(self, master, bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
647 self.master = master
45b12307c695 Initial revision
drewp
parents:
diff changeset
648 self.cue = cue
45b12307c695 Initial revision
drewp
parents:
diff changeset
649 self.changed_callback = changed_callback
45b12307c695 Initial revision
drewp
parents:
diff changeset
650 self.enable_callbacks = 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
651
45b12307c695 Initial revision
drewp
parents:
diff changeset
652 self.setup_editing_forms()
45b12307c695 Initial revision
drewp
parents:
diff changeset
653 self.set_cue_to_edit(cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
654 def set_cue_to_edit(self, cue):
45b12307c695 Initial revision
drewp
parents:
diff changeset
655 if cue != self.cue:
45b12307c695 Initial revision
drewp
parents:
diff changeset
656 self.cue = cue
45b12307c695 Initial revision
drewp
parents:
diff changeset
657 self.fill_in_cue_info()
45b12307c695 Initial revision
drewp
parents:
diff changeset
658 self.set_title()
45b12307c695 Initial revision
drewp
parents:
diff changeset
659 def set_title(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
660 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
661 self.master.title("Editing '%s'" % self.cue.name)
45b12307c695 Initial revision
drewp
parents:
diff changeset
662 except AttributeError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
663 pass
45b12307c695 Initial revision
drewp
parents:
diff changeset
664 def setup_editing_forms(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
665 self.variables = {}
45b12307c695 Initial revision
drewp
parents:
diff changeset
666 for row, field in enumerate(('name', 'time', 'page', 'cuenum', 'desc',
45b12307c695 Initial revision
drewp
parents:
diff changeset
667 'sub_levels')):
45b12307c695 Initial revision
drewp
parents:
diff changeset
668 lab = Tk.Label(self, text=field, fg='white', bg='black')
45b12307c695 Initial revision
drewp
parents:
diff changeset
669 lab.grid(row=row, column=0, sticky='nsew')
45b12307c695 Initial revision
drewp
parents:
diff changeset
670
45b12307c695 Initial revision
drewp
parents:
diff changeset
671 entryvar = Tk.StringVar()
45b12307c695 Initial revision
drewp
parents:
diff changeset
672 entry = Tk.Entry(self, fg='white', bg='black',
45b12307c695 Initial revision
drewp
parents:
diff changeset
673 textvariable=entryvar, insertbackground='white',
45b12307c695 Initial revision
drewp
parents:
diff changeset
674 highlightcolor='red') # TODO this red/black is backwards
45b12307c695 Initial revision
drewp
parents:
diff changeset
675 entry.grid(row=row, column=1, sticky='nsew')
45b12307c695 Initial revision
drewp
parents:
diff changeset
676
45b12307c695 Initial revision
drewp
parents:
diff changeset
677 self.variables[field] = entryvar
45b12307c695 Initial revision
drewp
parents:
diff changeset
678
45b12307c695 Initial revision
drewp
parents:
diff changeset
679 def field_changed(x, y, z, field=field, entryvar=entryvar):
45b12307c695 Initial revision
drewp
parents:
diff changeset
680 if self.cue:
45b12307c695 Initial revision
drewp
parents:
diff changeset
681 setattr(self.cue, field, entryvar.get())
45b12307c695 Initial revision
drewp
parents:
diff changeset
682 if self.enable_callbacks and self.changed_callback:
45b12307c695 Initial revision
drewp
parents:
diff changeset
683 self.changed_callback(self.cue)
45b12307c695 Initial revision
drewp
parents:
diff changeset
684 if field == 'name':
45b12307c695 Initial revision
drewp
parents:
diff changeset
685 self.set_title()
45b12307c695 Initial revision
drewp
parents:
diff changeset
686
45b12307c695 Initial revision
drewp
parents:
diff changeset
687 entryvar.trace('w', field_changed)
45b12307c695 Initial revision
drewp
parents:
diff changeset
688 self.columnconfigure(1, weight=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
689 def fill_in_cue_info(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
690 self.enable_callbacks = 0
45b12307c695 Initial revision
drewp
parents:
diff changeset
691 for row, field in enumerate(('name', 'time', 'page', 'cuenum', 'desc',
45b12307c695 Initial revision
drewp
parents:
diff changeset
692 'sub_levels')):
45b12307c695 Initial revision
drewp
parents:
diff changeset
693 text = ''
45b12307c695 Initial revision
drewp
parents:
diff changeset
694 if self.cue:
45b12307c695 Initial revision
drewp
parents:
diff changeset
695 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
696 text = getattr(self.cue, field)
45b12307c695 Initial revision
drewp
parents:
diff changeset
697 except AttributeError:
45b12307c695 Initial revision
drewp
parents:
diff changeset
698 pass
45b12307c695 Initial revision
drewp
parents:
diff changeset
699 self.variables[field].set(text)
45b12307c695 Initial revision
drewp
parents:
diff changeset
700 self.enable_callbacks = 1
45b12307c695 Initial revision
drewp
parents:
diff changeset
701
45b12307c695 Initial revision
drewp
parents:
diff changeset
702 if __name__ == "__main__":
45b12307c695 Initial revision
drewp
parents:
diff changeset
703 root = Tk.Tk()
45b12307c695 Initial revision
drewp
parents:
diff changeset
704 root.title("ShowMaster 9000")
45b12307c695 Initial revision
drewp
parents:
diff changeset
705 root.geometry("600x670")
45b12307c695 Initial revision
drewp
parents:
diff changeset
706 cl = TkCueList(root, 'cues/dolly')
45b12307c695 Initial revision
drewp
parents:
diff changeset
707 cl.pack(fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
708
45b12307c695 Initial revision
drewp
parents:
diff changeset
709 fader = CueFader(root, cl)
45b12307c695 Initial revision
drewp
parents:
diff changeset
710 fader.pack(fill='both', expand=1)
45b12307c695 Initial revision
drewp
parents:
diff changeset
711 try:
45b12307c695 Initial revision
drewp
parents:
diff changeset
712 Tk.mainloop()
45b12307c695 Initial revision
drewp
parents:
diff changeset
713 except KeyboardInterrupt:
45b12307c695 Initial revision
drewp
parents:
diff changeset
714 root.destroy()