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