Mercurial > code > home > repos > light9
changeset 168:f8b5cb5fbeed
- CueFader is hopefully done:
- CueFader is hopefully done:
- The TimedGoButton accepts a wheel to change the times. You can also
enter times directly.
- TimedGoButton really has a default starting time of 2 now. (there was
a variable attached to the wrong widget before)
- We send DMX levels with dmxclient now.
- Autoload Times is a new option.
- We load times from the next cue if Autoload Times is true.
- Time predictions in the LabelledScale are slightly better. You still
can change the time of an active fade.
- Cue cache and DMX level computing now have their own functions, which
get called at (hopefully) All The Right Times.
- There are even some docs now!
- Cues: sub_level parsing is better, will only throw out one line if
it encounters problems (instead of the rest of the cue)
- CueList: lots of 0 vs. None bugs fixed.
- TkCueList: stores a reference to the controlling fader so it can alert
it about changed cues.
- CueEditron: You can edit sub_levels now.
- cuelist1 was edited, checking it in for consistency's sake
author | dmcc |
---|---|
date | Wed, 09 Jul 2003 03:59:40 +0000 |
parents | 79bc84310e80 |
children | 2794ad9a8fd8 |
files | flax/CueFaders.py flax/cues/cuelist1 |
diffstat | 2 files changed, 167 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/flax/CueFaders.py Tue Jul 08 16:19:55 2003 +0000 +++ b/flax/CueFaders.py Wed Jul 09 03:59:40 2003 +0000 @@ -3,7 +3,7 @@ import time from TreeDict import TreeDict, allow_class_to_be_pickled from TLUtility import enumerate -import Submaster +import Submaster, dmxclient cue_state_indicator_colors = { # bg fg @@ -75,19 +75,30 @@ self.button.pack(fill='both', expand=1, side='left') self.timer_var = Tk.DoubleVar() - self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0) - self.timer_entry.entry.configure(textvariable=self.timer_var, width=5, - bg='black', fg='white') + self.timer_entry = Tk.Control(self, step=0.5, min=0, integer=0, + variable=self.timer_var, selectmode='immediate') + for widget in (self.timer_entry, self.timer_entry.entry, + self.timer_entry.incr, self.timer_entry.decr, self.button, self): + widget.bind("<4>", self.wheelscroll) + widget.bind("<5>", self.wheelscroll) + self.timer_entry.entry.configure(width=5, bg='black', fg='white') self.timer_entry.pack(fill='y', side='left') + self.timer_var.set(2) self.disabled = (self.button['state'] == 'disabled') self.fading = 0 + def wheelscroll(self, event): + """Mouse wheel increments or decrements timer.""" + if event.num == 4: # scroll up + self.timer_entry.increment() + else: # scroll down + self.timer_entry.decrement() def start_fade(self, end_level=1): try: fade_time = float(self.timer_var.get()) except ValueError: # since we use a control now, i don't think we need to worry about # validation any more. - print "can't fade -- bad time" + print ">>> Can't fade -- bad time", self.timer_var.get() return self.start_time = time.time() @@ -130,8 +141,11 @@ def __init__(self, master, cuelist): Tk.Frame.__init__(self, master, bg='black') self.cuelist = cuelist - self.auto_shift = Tk.IntVar() - self.auto_shift.set(1) + self.cuelist.set_fader(self) + + self.last_levels_sent = 0 + self.current_dmx_levels = [0] * 68 + self.after(0, self.send_dmx_levels_loop) # start DMX sending loop # this is a mechanism to stop Tk from autoshifting too much. # if this variable is true, the mouse button is down. we don't want @@ -150,12 +164,24 @@ fg='white', bg='blue') self.set_prev_button.pack(side='left') + self.auto_shift = Tk.IntVar() + self.auto_shift.set(1) + self.auto_shift_checkbutton = Tk.Checkbutton(topframe, variable=self.auto_shift, text='Autoshift', command=self.toggle_autoshift, bg='black', fg='white', highlightbackground='black') self.auto_shift_checkbutton.pack(fill='both', side='left') + self.auto_load_times = Tk.IntVar() + self.auto_load_times.set(1) + + self.auto_load_times_checkbutton = Tk.Checkbutton(topframe, + variable=self.auto_load_times, text='Autoload Times', + command=self.toggle_autoshift, bg='black', fg='white', + highlightbackground='black') + self.auto_load_times_checkbutton.pack(fill='both', side='left') + self.set_next_button = Tk.Button(topframe, text='Set Next', command=lambda: cuelist.set_selection_as_next(), fg='white', bg='red') @@ -188,6 +214,8 @@ scale.scale_var.trace('w', \ lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) + go.timer_var.trace('w', + lambda x, y, z, scale=scale: scale.update_value_label()) def button_press(event, name=name, scale=scale): self.no_shifts_until_release = 1 # prevent shifts until release @@ -198,8 +226,48 @@ scale.scale.bind("<ButtonPress>", button_press) scale.scale.bind("<ButtonRelease>", button_release) faderframe.pack(side='bottom', fill='both', expand=1) + + self.current_dir = 'Next' self.cues_as_subs = {} + self.update_cue_cache() + def reload_cue_times(self): + prev, cur, next = self.cuelist.get_current_cues() + self.go_buttons['Next'].set_time(next.time) + def update_cue_cache(self): + """Rebuilds subs from the current cues. As this is expensive, we don't + do it unless necessary (i.e. whenever we shift or a cue is edited)""" + # load the subs to fade between + for cue, name in zip(self.cuelist.get_current_cues(), + ('Prev', 'Cur', 'Next')): + self.cues_as_subs[name] = cue.get_levels_as_sub() + self.compute_dmx_levels() + def compute_dmx_levels(self): + """Compute the DMX levels to send. This should get called whenever the + DMX levels could change: either during a crossfade or when a cue is + edited. Since this is called when we know that a change might occur, + we will send the new levels too.""" + cur_sub = self.cues_as_subs.get('Cur') + if cur_sub: + scale = self.scales[self.current_dir] + scale_val = scale.scale_var.get() + + other_sub = self.cues_as_subs[self.current_dir] + current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val) + self.current_dmx_levels = current_levels_as_sub.get_dmx_list() + self.send_dmx_levels() + def send_dmx_levels(self): + # print "send_dmx_levels", self.current_dmx_levels + dmxclient.outputlevels(self.current_dmx_levels) + self.last_levels_sent = time.time() + def send_dmx_levels_loop(self): + diff = time.time() - self.last_levels_sent + if diff >= 2: # too long since last send + self.send_dmx_levels() + self.after(200, self.send_dmx_levels_loop) + else: + self.after(int((2 - diff) * 100), self.send_dmx_levels_loop) def get_scale_desc(self, val, name): + """Returns a description to the TimedGoButton""" go_button = self.go_buttons.get(name) if go_button: time = go_button.get_time() @@ -221,11 +289,9 @@ scale.scale.set(0) self.cuelist.shift((-1, 1)[name == 'Next']) - # now load the subs to fade between - for cue, name in zip(self.cuelist.get_current_cues(), - ('Prev', 'Cur', 'Next')): - self.cues_as_subs[name] = cue.get_levels_as_sub() - print "cues_as_subs", self.cues_as_subs + self.update_cue_cache() + if self.auto_load_times.get(): + self.reload_cue_times() def autoshift(self, name, scale): scale_val = scale.scale_var.get() @@ -254,13 +320,8 @@ self.scales[d].enable() self.go_buttons[d].enable() - cur_sub = self.cues_as_subs.get('Cur') - if cur_sub: - other_sub = self.cues_as_subs[name] - # print 'fade between %s and %s (%.2f)' % (cur_sub, other_sub, scale_val) - self.current_levels_as_sub = cur_sub.crossfade(other_sub, scale_val) - print "current levels", self.current_levels_as_sub.get_dmx_list() - # print + self.current_dir = name + self.compute_dmx_levels() def opposite_direction(self, d): if d == 'Next': return 'Prev' @@ -282,19 +343,17 @@ will reload the submasters from disk, combine all subs together, and then compute the normalized form.""" subdict = {} - try: - print self, self.sub_levels - for line in self.sub_levels.split(','): + for line in self.sub_levels.split(','): + try: line = line.strip() - # print 'line', line + if not line: + continue sub, scale = line.split(':') - # print 'sub', sub, 'scale', scale sub = sub.strip() scale = float(scale) subdict[sub] = scale - # print 'subdict', subdict - except (ValueError, AttributeError): - print "parsing error when computing sub for", self + except ValueError: + print "Parsing error for '%s' in %s" % (self.sub_levels, self) s = Submaster.Submasters() newsub = Submaster.sub_maxes(*[s[sub] * scale @@ -347,23 +406,27 @@ def set_prev(self, index): self.prev_pointer = index def bound_index(self, index): - if not self.cues: + if not self.cues or index < 0: return None else: - return max(0, min(index, len(self.cues) - 1)) + return min(index, len(self.cues) - 1) def get_current_cue_indices(self): + """Returns a list of the indices of three cues: the previous cue, + the current cue, and the next cue.""" cur = self.current_cue_index return [self.bound_index(index) for index in (self.prev_pointer or cur - 1, cur, self.next_pointer or cur + 1)] def get_current_cues(self): + """Returns a list of three cues: the previous cue, the current cue, + and the next cue.""" return [self.get_cue_by_index(index) for index in self.get_current_cue_indices()] def get_cue_by_index(self, index): - if index: + try: return self.cues[self.bound_index(index)] - else: + except TypeError: return empty_cue def __del__(self): self.save() @@ -379,9 +442,11 @@ def __init__(self, master, filename): CueList.__init__(self, filename) Tk.Frame.__init__(self, master, bg='black') + self.fader = None self.edit_tl = Tk.Toplevel() - self.editor = CueEditron(self.edit_tl, changed_callback=self.redraw_cue) + self.editor = CueEditron(self.edit_tl, + changed_callback=self.cue_changed) self.editor.pack(fill='both', expand=1) def edit_cue(index): @@ -411,13 +476,16 @@ for count, cue in enumerate(self.cues): self.display_cue(count, cue) self.update_cue_indicators() + def set_fader(self, fader): + self.fader = fader def wheelscroll(self, evt): """Perform mouse wheel scrolling""" - amount = 2 - if evt.num == 4: + if evt.num == 4: # scroll down amount = -2 + else: # scroll up + amount = 2 self.hlist.yview('scroll', amount, 'units') - def redraw_cue(self, cue): + def cue_changed(self, cue): path = self.cues.index(cue) for col, header in enumerate(self.columns): try: @@ -429,6 +497,10 @@ self.cue_label_windows[path]['text'] = text else: self.hlist.item_configure(path, col, text=text) + + if cue in self.get_current_cues() and self.fader: + self.fader.update_cue_cache() + self.fader.reload_cue_times() def display_cue(self, path, cue): for col, header in enumerate(self.columns): try: @@ -452,6 +524,8 @@ """If cue_indices is None, we'll reset all of them.""" cue_indices = cue_indices or self.cue_label_windows.keys() for key in cue_indices: + if key is None: + continue window = self.cue_label_windows[key] window.configure(fg='white', bg='black') def update_cue_indicators(self): @@ -459,6 +533,8 @@ ('prev', 'cur', 'next'))) for count, state in states.items(): + if count is None: + continue window = self.cue_label_windows[count] bg, fg = cue_state_indicator_colors[state] window.configure(bg=bg, fg=fg) @@ -469,7 +545,8 @@ # try to see all indices, but next takes priority over all, and cur # over prev for index in self.get_current_cue_indices(): - self.hlist.see(index) + if index is not None: + self.hlist.see(index) def select_callback(self, index): new_next = int(index) self.set_next(new_next) @@ -514,7 +591,8 @@ pass def setup_editing_forms(self): self.variables = {} - for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')): + for row, field in enumerate(('name', 'time', 'page', 'desc', + 'sub_levels')): lab = Tk.Label(self, text=field, fg='white', bg='black') lab.grid(row=row, column=0, sticky='nsew') @@ -537,7 +615,8 @@ self.columnconfigure(1, weight=1) def fill_in_cue_info(self): self.enable_callbacks = 0 - for row, field in enumerate(('name', 'time', 'page', 'desc', 'sub_levels')): + for row, field in enumerate(('name', 'time', 'page', 'desc', + 'sub_levels')): text = '' if self.cue: try:
--- a/flax/cues/cuelist1 Tue Jul 08 16:19:55 2003 +0000 +++ b/flax/cues/cuelist1 Wed Jul 09 03:59:40 2003 +0000 @@ -1,19 +1,19 @@ <?xml version="1.0"?> <!DOCTYPE PyObject SYSTEM "PyObjects.dtd"> <PyObject family="obj" type="builtin_wrapper" class="_EmptyClass"> -<attr name="__toplevel__" family="map" type="__compound__" extra="None TreeDict" id="138432956" > +<attr name="__toplevel__" family="map" type="__compound__" extra="None TreeDict" id="138506468" > <entry> <key type="string" value="cues" /> - <val type="list" id="139794108" > - <item type="PyObject" id="140312100" class="Cue"> + <val type="list" id="139971548" > + <item type="PyObject" id="140423764" class="Cue"> + <attr name="name" type="string" value="tevya special" /> <attr name="desc" type="string" value="whoa - this works" /> <attr name="page" type="string" value="3.2" /> - <attr name="name" type="string" value="tevya special" /> <attr name="sub_levels" type="string" value="green : 1.0" /> - <attr name="time" type="string" value="0" /> + <attr name="time" type="string" value="2" /> </item> - <item type="PyObject" id="139843388" class="Cue"> - <attr name="subdict" type="dict" id="140307292" > + <item type="PyObject" id="139862804" class="Cue"> + <attr name="subdict" type="dict" id="139863044" > </attr> <attr name="name" type="string" value="lady luck" /> <attr name="time" type="string" value="1" /> @@ -21,8 +21,8 @@ <attr name="sub_levels" type="string" value="blue : 1.0, green : 0.5" /> <attr name="desc" type="string" value="music flourish" /> </item> - <item type="PyObject" id="139773172" class="Cue"> - <attr name="subdict" type="dict" id="139774164" > + <item type="PyObject" id="139862732" class="Cue"> + <attr name="subdict" type="dict" id="139852060" > </attr> <attr name="name" type="string" value="dolly solo" /> <attr name="time" type="string" value="2" /> @@ -30,8 +30,8 @@ <attr name="sub_levels" type="string" value="blue : 0.1, green : 0.1" /> <attr name="desc" type="string" value="tevya: "what's happening to the tradition?"" /> </item> - <item type="PyObject" id="139793260" class="Cue"> - <attr name="subdict" type="dict" id="139774508" > + <item type="PyObject" id="139915236" class="Cue"> + <attr name="subdict" type="dict" id="139852964" > </attr> <attr name="name" type="string" value="cue 3" /> <attr name="time" type="string" value="4" /> @@ -39,17 +39,17 @@ <attr name="sub_levels" type="string" value="red : 1" /> <attr name="desc" type="string" value="the third cue" /> </item> - <item type="PyObject" id="139775180" class="Cue"> - <attr name="subdict" type="dict" id="139774764" > + <item type="PyObject" id="139851228" class="Cue"> + <attr name="subdict" type="dict" id="139863188" > </attr> <attr name="name" type="string" value="heart" /> - <attr name="time" type="string" value="42" /> + <attr name="time" type="string" value="10" /> <attr name="page" type="string" value="1.3.13" /> <attr name="sub_levels" type="string" value="frontwhite : 0.2, red : 0.7" /> <attr name="desc" type="string" value=""you've gotta have heart"" /> </item> - <item type="PyObject" id="140308580" class="Cue"> - <attr name="subdict" type="dict" id="140311956" > + <item type="PyObject" id="139863332" class="Cue"> + <attr name="subdict" type="dict" id="139841476" > </attr> <attr name="name" type="string" value="more musical refs" /> <attr name="time" type="string" value="5" /> @@ -57,8 +57,8 @@ <attr name="sub_levels" type="string" value="blue : 1.0" /> <attr name="desc" type="string" value="etc." /> </item> - <item type="PyObject" id="139772700" class="Cue"> - <attr name="subdict" type="dict" id="140311684" > + <item type="PyObject" id="139855188" class="Cue"> + <attr name="subdict" type="dict" id="139855428" > </attr> <attr name="name" type="string" value="rainbow shimmer" /> <attr name="time" type="string" value="6" /> @@ -66,8 +66,8 @@ <attr name="sub_levels" type="string" value="" /> <attr name="desc" type="string" value="curtain close" /> </item> - <item type="PyObject" id="139774908" class="Cue"> - <attr name="subdict" type="dict" id="140310884" > + <item type="PyObject" id="139873788" class="Cue"> + <attr name="subdict" type="dict" id="139855956" > </attr> <attr name="name" type="string" value="fade up" /> <attr name="time" type="string" value="7" /> @@ -75,8 +75,8 @@ <attr name="sub_levels" type="string" value="" /> <attr name="desc" type="string" value="stage manager: "worklights, please"" /> </item> - <item type="PyObject" id="140311076" class="Cue"> - <attr name="subdict" type="dict" id="140310300" > + <item type="PyObject" id="139927324" class="Cue"> + <attr name="subdict" type="dict" id="139854356" > </attr> <attr name="name" type="string" value="blackout" /> <attr name="time" type="string" value="8" /> @@ -84,8 +84,8 @@ <attr name="sub_levels" type="string" value="" /> <attr name="desc" type="string" value=""lights out!"" /> </item> - <item type="PyObject" id="140304700" class="Cue"> - <attr name="subdict" type="dict" id="140302268" > + <item type="PyObject" id="139864660" class="Cue"> + <attr name="subdict" type="dict" id="139857340" > </attr> <attr name="name" type="string" value="sill" /> <attr name="time" type="string" value="4.2" /> @@ -93,68 +93,74 @@ <attr name="sub_levels" type="string" value="" /> <attr name="desc" type="string" value="another description" /> </item> - <item type="PyObject" id="140309860" class="Cue"> + <item type="PyObject" id="139855916" class="Cue"> + <attr name="name" type="string" value="front only" /> <attr name="desc" type="string" value="mr. cue 10" /> <attr name="page" type="string" value="2.7.3" /> - <attr name="name" type="string" value="front only" /> <attr name="sub_levels" type="string" value="" /> <attr name="time" type="string" value="10" /> </item> - <item type="PyObject" id="140310788" class="Cue"> + <item type="PyObject" id="139163156" class="Cue"> + <attr name="name" type="string" value="cue 11" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 11" /> <attr name="sub_levels" type="string" value="" /> <attr name="time" type="string" value="11" /> </item> - <item type="PyObject" id="139762676" class="Cue"> - <attr name="sub_levels" type="string" value="" /> + <item type="PyObject" id="139854140" class="Cue"> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> <attr name="name" type="string" value="cue 12" /> + <attr name="sub_levels" type="string" value="" /> <attr name="time" type="string" value="2.1" /> </item> - <item type="PyObject" id="140301540" class="Cue"> - <attr name="sub_levels" type="string" value="" /> + <item type="PyObject" id="139841764" class="Cue"> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> <attr name="name" type="string" value="cue 13" /> + <attr name="sub_levels" type="string" value="" /> <attr name="time" type="string" value="13" /> </item> - <item type="PyObject" id="140310636" class="Cue"> + <item type="PyObject" id="139854308" class="Cue"> + <attr name="name" type="string" value="cue 14" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 14" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="14" /> </item> - <item type="PyObject" id="140307748" class="Cue"> + <item type="PyObject" id="139858580" class="Cue"> + <attr name="name" type="string" value="cue 15" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 15" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="15" /> </item> - <item type="PyObject" id="140309436" class="Cue"> + <item type="PyObject" id="139856100" class="Cue"> + <attr name="name" type="string" value="cue 16" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 16" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="16" /> </item> - <item type="PyObject" id="140290764" class="Cue"> + <item type="PyObject" id="139856180" class="Cue"> + <attr name="name" type="string" value="cue 17" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 17" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="17" /> </item> - <item type="PyObject" id="140300196" class="Cue"> + <item type="PyObject" id="139846156" class="Cue"> + <attr name="name" type="string" value="some name" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="some name" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="18" /> </item> - <item type="PyObject" id="140301756" class="Cue"> + <item type="PyObject" id="139841948" class="Cue"> + <attr name="name" type="string" value="cue 19" /> <attr name="desc" type="string" value="" /> <attr name="page" type="string" value="" /> - <attr name="name" type="string" value="cue 19" /> + <attr name="sub_levels" type="string" value="red : 1" /> <attr name="time" type="string" value="19" /> </item> </val>