Mercurial > code > home > repos > light9
view flax/CueFaders.py @ 158:5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
more disabling of stuff that make no sense at certain times and some
bug fixes. still haven't fixed the scale problem
author | dmcc |
---|---|
date | Mon, 07 Jul 2003 07:39:40 +0000 |
parents | 7d3a0f9107a8 |
children | 0803fb42109d |
line wrap: on
line source
from __future__ import division, nested_scopes import Tix as Tk import time from TreeDict import TreeDict, allow_class_to_be_pickled class LabelledScale(Tk.Frame): """Scale with two labels: a name and current value""" def __init__(self, master, label, **opts): Tk.Frame.__init__(self, master, bd=2, relief='raised') opts.setdefault('variable', Tk.DoubleVar()) opts.setdefault('showvalue', 0) self.scale_var = opts['variable'] self.scale = Tk.Scale(self, **opts) self.scale.pack(side='top', expand=1, fill='both') self.name = Tk.Label(self, text=label) self.name.pack(side='bottom') self.scale_value = Tk.Label(self, width=6) self.scale_value.pack(side='bottom') self.scale_var.trace('w', self.update_value_label) self.update_value_label() self.disabled = (self.scale['state'] == 'disabled') def set_label(self, label): self.name['text'] = label def update_value_label(self, *args): val = self.scale_var.get() * 100 self.scale_value['text'] = "%0.2f" % val def disable(self): if not self.disabled: self.scale['state'] = 'disabled' self.scale_var.set(0) self.disabled = 1 def enable(self): if self.disabled: self.scale['state'] = 'normal' self.disabled = 0 class TimedGoButton(Tk.Frame): """Go button, fade time entry, and time fader""" def __init__(self, master, name, scale_to_fade): Tk.Frame.__init__(self, master) self.name = name self.scale_to_fade = scale_to_fade self.button = Tk.Button(self, text=name, command=self.start_fade) self.button.pack(fill='both', expand=1, side='left') self.timer_var = Tk.StringVar() self.timer_entry = Tk.Entry(self, textvariable=self.timer_var, width=5) self.timer_entry.pack(fill='y', side='left') self.timer_var.set("2") self.disabled = (self.button['state'] == 'disabled') def start_fade(self, end_level=1): try: fade_time = float(self.timer_var.get()) except ValueError: # TODO figure out how to handle this print "can't fade -- bad time" return self.start_time = time.time() self.start_level = self.scale_to_fade.scale_var.get() self.end_level = end_level self.fade_length = fade_time self.do_fade() def do_fade(self): diff = time.time() - self.start_time if diff < self.fade_length: percent = diff / self.fade_length newlevel = self.start_level + \ (percent * (self.end_level - self.start_level)) self.scale_to_fade.scale_var.set(newlevel) if newlevel != self.end_level: self.after(10, self.do_fade) else: self.scale_to_fade.scale_var.set(self.end_level) def disable(self): if not self.disabled: self.button['state'] = 'disabled' self.disabled = 1 def enable(self): if self.disabled: self.button['state'] = 'normal' self.disabled = 0 class CueFader(Tk.Frame): def __init__(self, master, cuelist): Tk.Frame.__init__(self, master) self.cuelist = cuelist self.auto_shift = Tk.IntVar() self.auto_shift.set(1) self.scales = {} self.shift_buttons = {} self.go_buttons = {} topframe = Tk.Frame(self) self.current_cues = Tk.Label(topframe) self.current_cues.pack() self.update_cue_display() topframe.pack() bottomframe = Tk.Frame(self) self.auto_shift_checkbutton = Tk.Checkbutton(self, variable=self.auto_shift, text='Autoshift', command=self.toggle_autoshift) self.auto_shift_checkbutton.pack() bottomframe.pack(side='bottom') middleframe = Tk.Frame(self) for name, start, end, side in (('Prev', 1, 0, 'left'), ('Next', 0, 1, 'right')): frame = Tk.Frame(self) scale = LabelledScale(frame, name, from_=start, to_=end, res=0.01, orient='horiz') scale.pack(fill='both', expand=1) go = TimedGoButton(frame, 'Go %s' % name, scale) go.pack(fill='both', expand=1) frame.pack(side=side, fill='both', expand=1) shift = Tk.Button(frame, text="Shift %s" % name, state='disabled', command=lambda name=name: self.shift(name)) self.scales[name] = scale self.shift_buttons[name] = shift self.go_buttons[name] = go scale.scale_var.trace('w', \ lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) middleframe.pack(side='bottom', fill='both', expand=1) def toggle_autoshift(self): for name, button in self.shift_buttons.items(): if not self.auto_shift.get(): button.pack(side='bottom', fill='both', expand=1) else: button.pack_forget() def shift(self, name): print "shift", name for scale_name, scale in self.scales.items(): scale.scale_var.set(0) self.cuelist.shift((-1, 1)[name == 'Next']) self.update_cue_display() def update_cue_display(self): current_cues = [cue.name for cue in self.cuelist.get_current_cues()] self.current_cues['text'] = ', '.join(current_cues) def xfade(self, name, scale): scale_val = scale.scale_var.get() # print "xfade", name, scale_val if scale_val == 1: if self.auto_shift.get(): print "autoshifting", name self.shift(name) scale_val = scale.scale_var.get() # this needs to be refreshed else: self.shift_buttons[name]['state'] = 'normal' else: # disable any dangerous shifting self.shift_buttons[name]['state'] = 'disabled' d = self.opposite_direction(name) if scale_val != 0: # disable illegal three part crossfades self.scales[d].disable() self.go_buttons[d].disable() else: # undo above work self.scales[d].enable() self.go_buttons[d].enable() def opposite_direction(self, d): if d == 'Next': return 'Prev' else: return 'Next' class Cue: """A Cue has a name, a time, and any number of other attributes.""" def __init__(self, name, time=3, **attrs): self.name = name self.time = time self.__dict__.update(attrs) def __repr__(self): return "<Cue %s, length %s>" % (self.name, self.time) empty_cue = Cue('empty') allow_class_to_be_pickled(Cue) class CueList: """Persistent list of Cues""" def __init__(self, filename): self.filename = filename self.treedict = TreeDict() try: self.treedict.load(filename) except IOError: self.treedict.cues = [] self.cues = self.treedict.cues self.current_cue_index = 0 self.next_pointer = None self.prev_pointer = None import atexit atexit.register(self.save) def add_cue(self, cue, index=None): """Adds a Cue object to the list. If no index is specified, the cue will be added to the end.""" index = index or len(self.cues) self.cues.insert(index, cue) def shift(self, diff): """Shift through cue history""" old_index = self.current_cue_index self.current_cue_index = None if diff < 0: # if going backwards if self.prev_pointer: # use a prev pointer if we have one self.current_cue_index = self.prev_pointer self.next_pointer = old_index self.prev_pointer = None else: if self.next_pointer: # use a next pointer if we have one self.current_cue_index = self.next_pointer self.next_pointer = None self.prev_pointer = old_index if not self.current_cue_index: self.current_cue_index = old_index + diff def set_next(self, index): self.next_pointer = index def set_prev(self, index): self.prev_pointer = index def bound_index(self, index): if not self.cues: return None else: return max(0, min(index, len(self.cues) - 1)) def get_current_cue_indices(self): 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): return [self.get_cue_by_index(index) for index in self.get_current_cue_indices()] def get_cue_by_index(self, index): if index: return self.cues[self.bound_index(index)] else: return empty_cue def __del__(self): self.save() def save(self): self.treedict.save(self.filename) if __name__ == "__main__": cl = CueList('cues/cuelist1') # to populate cue list if 0: for x in range(20): cl.add_cue(Cue('cue %d' % x, time=x, some_attribute=3)) root = Tk.Tk() fader = CueFader(root, cl) fader.pack(fill='both', expand=1) Tk.mainloop()