Mercurial > code > home > repos > light9
annotate flax/CueFaders.py @ 155:4c3060ceddcc
autoshifting is controllable now
author | dmcc |
---|---|
date | Mon, 07 Jul 2003 06:56:15 +0000 |
parents | 990a9474d0e7 |
children | 7d3a0f9107a8 |
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 | |
5 | |
6 class LabelledScale(Tk.Frame): | |
7 """Scale with two labels: a name and current value""" | |
8 def __init__(self, master, label, **opts): | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
9 Tk.Frame.__init__(self, master, bd=2, relief='raised') |
0 | 10 opts.setdefault('variable', Tk.DoubleVar()) |
11 opts.setdefault('showvalue', 0) | |
12 self.scale_var = opts['variable'] | |
13 self.scale = Tk.Scale(self, **opts) | |
14 self.scale.pack(side='top', expand=1, fill='both') | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
15 self.name = Tk.Label(self, text=label) |
0 | 16 self.name.pack(side='bottom') |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
17 self.scale_value = Tk.Label(self, width=6) |
0 | 18 self.scale_value.pack(side='bottom') |
19 self.scale_var.trace('w', self.update_value_label) | |
20 self.update_value_label() | |
21 def set_label(self, label): | |
22 self.name['text'] = label | |
23 def update_value_label(self, *args): | |
24 val = self.scale_var.get() * 100 | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
25 self.scale_value['text'] = "%0.2f" % val |
0 | 26 |
27 class TimedGoButton(Tk.Frame): | |
28 """Go button, fade time entry, and time fader""" | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
29 def __init__(self, master, name, scale_to_fade): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
30 Tk.Frame.__init__(self, master) |
0 | 31 self.name = name |
32 self.scale_to_fade = scale_to_fade | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
33 self.button = Tk.Button(self, text=name, command=self.start_fade) |
0 | 34 self.button.pack(fill='both', expand=1, side='left') |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
35 self.timer_var = Tk.StringVar() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
36 self.timer_entry = Tk.Entry(self, textvariable=self.timer_var, width=5) |
0 | 37 self.timer_entry.pack(fill='y', side='left') |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
38 self.timer_var.set("2") |
0 | 39 def start_fade(self, end_level=1): |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
40 try: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
41 fade_time = float(self.timer_var.get()) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
42 except ValueError: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
43 # TODO figure out how to handle this |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
44 print "can't fade -- bad time" |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
45 return |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
46 |
0 | 47 self.start_time = time.time() |
48 self.start_level = self.scale_to_fade.scale_var.get() | |
49 self.end_level = end_level | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
50 self.fade_length = fade_time |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
51 self.do_fade() |
0 | 52 def do_fade(self): |
53 diff = time.time() - self.start_time | |
54 if diff < self.fade_length: | |
55 percent = diff / self.fade_length | |
56 newlevel = self.start_level + \ | |
57 (percent * (self.end_level - self.start_level)) | |
58 self.scale_to_fade.scale_var.set(newlevel) | |
59 | |
60 if newlevel != self.end_level: | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
61 self.after(10, self.do_fade) |
0 | 62 else: |
63 self.scale_to_fade.scale_var.set(self.end_level) | |
64 | |
65 class CueFader(Tk.Frame): | |
66 def __init__(self, master, cuelist): | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
67 Tk.Frame.__init__(self, master) |
0 | 68 self.cuelist = cuelist |
155 | 69 self.auto_shift = Tk.IntVar() |
70 self.auto_shift.set(1) | |
0 | 71 |
72 self.scales = {} | |
73 self.shift_buttons = {} | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
74 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
75 topframe = Tk.Frame(self) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
76 self.current_cues = Tk.Label(topframe) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
77 self.current_cues.pack() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
78 self.update_cue_display() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
79 topframe.pack() |
0 | 80 |
155 | 81 bottomframe = Tk.Frame(self) |
82 self.auto_shift_checkbutton = Tk.Checkbutton(self, | |
83 variable=self.auto_shift, text='Autoshift', | |
84 command=self.toggle_autoshift) | |
85 self.auto_shift_checkbutton.pack() | |
86 bottomframe.pack(side='bottom') | |
87 | |
88 middleframe = Tk.Frame(self) | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
89 for name, start, end, side in (('Prev', 1, 0, 'left'), |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
90 ('Next', 0, 1, 'right')): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
91 frame = Tk.Frame(self) |
0 | 92 scale = LabelledScale(frame, name, from_=start, to_=end, |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
93 res=0.01, orient='horiz') |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
94 scale.pack(fill='both', expand=1) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
95 go = TimedGoButton(frame, 'Go %s' % name, scale) |
0 | 96 go.pack(fill='both', expand=1) |
97 frame.pack(side=side, fill='both', expand=1) | |
98 | |
155 | 99 shift = Tk.Button(frame, text="Shift %s" % name, state='disabled', |
100 command=lambda name=name: self.shift(name)) | |
101 | |
0 | 102 self.scales[name] = scale |
103 self.shift_buttons[name] = shift | |
104 | |
105 scale.scale_var.trace('w', \ | |
106 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) | |
155 | 107 middleframe.pack(side='bottom', fill='both', expand=1) |
108 def toggle_autoshift(self): | |
109 for name, button in self.shift_buttons.items(): | |
110 if not self.auto_shift.get(): | |
111 button.pack(side='bottom', fill='both', expand=1) | |
112 else: | |
113 button.pack_forget() | |
114 | |
0 | 115 def shift(self, name): |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
116 for scale in self.scales.values(): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
117 scale.scale_var.set(0) |
155 | 118 scale.scale.update() |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
119 print "shift", name |
0 | 120 self.cuelist.shift((-1, 1)[name == 'Next']) |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
121 self.update_cue_display() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
122 def update_cue_display(self): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
123 current_cues = [cue.name for cue in self.cuelist.get_current_cues()] |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
124 self.current_cues['text'] = ', '.join(current_cues) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
125 def xfade(self, name, scale): |
0 | 126 scale_val = scale.scale_var.get() |
127 | |
128 if scale_val == 1: | |
155 | 129 if self.auto_shift.get(): |
0 | 130 self.shift(name) |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
131 else: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
132 self.shift_buttons[name]['state'] = 'normal' |
0 | 133 else: |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
134 # disable any dangerous shifting |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
135 self.shift_buttons[name]['state'] = 'disabled' |
0 | 136 |
137 if scale_val != 0: | |
138 # disable illegal three part crossfades | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
139 # TODO: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
140 # if name == 'Next': |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
141 # disable go_prev button and slider, lock slider at 0 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
142 pass |
0 | 143 else: |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
144 # undo above changes |
0 | 145 |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
146 # Actually, TimedGoButton and LabelledScale can have enable/disable |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
147 # methods which will only do the Tk calls if necessary |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
148 pass |
0 | 149 |
150 class Cue: | |
151 """A Cue has a name, a time, and any number of other attributes.""" | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
152 def __init__(self, name, time=3, **attrs): |
0 | 153 self.name = name |
154 self.time = time | |
155 self.__dict__.update(attrs) | |
156 def __repr__(self): | |
157 return "<Cue %s, length %s>" % (self.name, self.time) | |
158 | |
159 empty_cue = Cue('empty') | |
160 | |
161 allow_class_to_be_pickled(Cue) | |
162 | |
163 class CueList: | |
164 """Persistent list of Cues""" | |
165 def __init__(self, filename): | |
166 self.filename = filename | |
167 self.treedict = TreeDict() | |
168 try: | |
169 self.treedict.load(filename) | |
170 except IOError: | |
171 self.treedict.cues = [] | |
172 self.cues = self.treedict.cues | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
173 self.current_cue_index = 0 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
174 self.next_pointer = None |
0 | 175 self.prev_pointer = None |
176 | |
177 import atexit | |
178 atexit.register(self.save) | |
179 def add_cue(self, cue, index=None): | |
180 """Adds a Cue object to the list. If no index is specified, | |
181 the cue will be added to the end.""" | |
182 index = index or len(self.cues) | |
183 self.cues.insert(index, cue) | |
184 def shift(self, diff): | |
185 """Shift through cue history""" | |
186 old_index = self.current_cue_index | |
187 self.current_cue_index = None | |
188 if diff < 0: # if going backwards | |
189 if self.prev_pointer: # use a prev pointer if we have one | |
190 self.current_cue_index = self.prev_pointer | |
191 self.next_pointer = old_index | |
192 self.prev_pointer = None | |
193 else: | |
194 if self.next_pointer: # use a next pointer if we have one | |
195 self.current_cue_index = self.next_pointer | |
196 self.next_pointer = None | |
197 self.prev_pointer = old_index | |
198 if not self.current_cue_index: | |
199 self.current_cue_index = old_index + diff | |
200 def set_next(self, index): | |
201 self.next_pointer = index | |
202 def set_prev(self, index): | |
203 self.prev_pointer = index | |
204 def bound_index(self, index): | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
205 if not self.cues: |
0 | 206 return None |
207 else: | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
208 return max(0, min(index, len(self.cues))) |
0 | 209 def get_current_cue_indices(self): |
210 cur = self.current_cue_index | |
211 return [self.bound_index(index) for index in | |
212 (self.prev_pointer or cur - 1, | |
213 cur, | |
214 self.next_pointer or cur + 1)] | |
215 def get_current_cues(self): | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
216 # print "get_current_cue_indices", self.get_current_cue_indices() |
0 | 217 return [self.get_cue_by_index(index) |
218 for index in self.get_current_cue_indices()] | |
219 def get_cue_by_index(self, index): | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
220 # print "get_cue_by_index", index |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
221 if index: |
0 | 222 return self.cues[self.bound_index(index)] |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
223 else: |
0 | 224 return empty_cue |
225 def __del__(self): | |
226 self.save() | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
227 def save(self): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
228 self.treedict.save(self.filename) |
0 | 229 |
230 if __name__ == "__main__": | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
231 if 0: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
232 z = CueList('cues/cuelist1') |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
233 z.add_cue(Cue('cue %s' % time.asctime(), time=2, a=7, b=8)) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
234 print 'cues', z.cues |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
235 else: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
236 cl = CueList('cues/cuelist1') |
0 | 237 |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
238 # to populate cue list |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
239 if 0: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
240 for x in range(20): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
241 cl.add_cue(Cue('cue %d' % x, time=x, some_attribute=3)) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
242 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
243 root = Tk.Tk() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
244 fader = CueFader(root, cl) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
245 fader.pack(fill='both', expand=1) |
0 | 246 Tk.mainloop() |