Mercurial > code > home > repos > light9
annotate 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 |
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() | |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
21 self.disabled = (self.scale['state'] == 'disabled') |
0 | 22 def set_label(self, label): |
23 self.name['text'] = label | |
24 def update_value_label(self, *args): | |
25 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
|
26 self.scale_value['text'] = "%0.2f" % val |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
27 def disable(self): |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
28 if not self.disabled: |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
29 self.scale['state'] = 'disabled' |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
30 self.scale_var.set(0) |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
31 self.disabled = 1 |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
32 def enable(self): |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
33 if self.disabled: |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
34 self.scale['state'] = 'normal' |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
35 self.disabled = 0 |
0 | 36 |
37 class TimedGoButton(Tk.Frame): | |
38 """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
|
39 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
|
40 Tk.Frame.__init__(self, master) |
0 | 41 self.name = name |
42 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
|
43 self.button = Tk.Button(self, text=name, command=self.start_fade) |
0 | 44 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
|
45 self.timer_var = Tk.StringVar() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
46 self.timer_entry = Tk.Entry(self, textvariable=self.timer_var, width=5) |
0 | 47 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
|
48 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
|
49 self.disabled = (self.button['state'] == 'disabled') |
0 | 50 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
|
51 try: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
52 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
|
53 except ValueError: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
54 # 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
|
55 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
|
56 return |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
57 |
0 | 58 self.start_time = time.time() |
59 self.start_level = self.scale_to_fade.scale_var.get() | |
60 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
|
61 self.fade_length = fade_time |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
62 self.do_fade() |
0 | 63 def do_fade(self): |
64 diff = time.time() - self.start_time | |
65 if diff < self.fade_length: | |
66 percent = diff / self.fade_length | |
67 newlevel = self.start_level + \ | |
68 (percent * (self.end_level - self.start_level)) | |
69 self.scale_to_fade.scale_var.set(newlevel) | |
70 | |
71 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
|
72 self.after(10, self.do_fade) |
0 | 73 else: |
74 self.scale_to_fade.scale_var.set(self.end_level) | |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
75 def disable(self): |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
76 if not self.disabled: |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
77 self.button['state'] = 'disabled' |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
78 self.disabled = 1 |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
79 def enable(self): |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
80 if self.disabled: |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
81 self.button['state'] = 'normal' |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
82 self.disabled = 0 |
0 | 83 |
84 class CueFader(Tk.Frame): | |
85 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
|
86 Tk.Frame.__init__(self, master) |
0 | 87 self.cuelist = cuelist |
155 | 88 self.auto_shift = Tk.IntVar() |
89 self.auto_shift.set(1) | |
0 | 90 |
91 self.scales = {} | |
92 self.shift_buttons = {} | |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
93 self.go_buttons = {} |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
94 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
95 topframe = Tk.Frame(self) |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
96 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
|
97 self.current_cues.pack() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
98 self.update_cue_display() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
99 topframe.pack() |
0 | 100 |
155 | 101 bottomframe = Tk.Frame(self) |
102 self.auto_shift_checkbutton = Tk.Checkbutton(self, | |
103 variable=self.auto_shift, text='Autoshift', | |
104 command=self.toggle_autoshift) | |
105 self.auto_shift_checkbutton.pack() | |
106 bottomframe.pack(side='bottom') | |
107 | |
108 middleframe = Tk.Frame(self) | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
109 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
|
110 ('Next', 0, 1, 'right')): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
111 frame = Tk.Frame(self) |
0 | 112 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
|
113 res=0.01, orient='horiz') |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
114 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
|
115 go = TimedGoButton(frame, 'Go %s' % name, scale) |
0 | 116 go.pack(fill='both', expand=1) |
117 frame.pack(side=side, fill='both', expand=1) | |
118 | |
155 | 119 shift = Tk.Button(frame, text="Shift %s" % name, state='disabled', |
120 command=lambda name=name: self.shift(name)) | |
121 | |
0 | 122 self.scales[name] = scale |
123 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
|
124 self.go_buttons[name] = go |
0 | 125 |
126 scale.scale_var.trace('w', \ | |
127 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) | |
155 | 128 middleframe.pack(side='bottom', fill='both', expand=1) |
129 def toggle_autoshift(self): | |
130 for name, button in self.shift_buttons.items(): | |
131 if not self.auto_shift.get(): | |
132 button.pack(side='bottom', fill='both', expand=1) | |
133 else: | |
134 button.pack_forget() | |
135 | |
0 | 136 def shift(self, name): |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
137 print "shift", name |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
138 for scale_name, scale in self.scales.items(): |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
139 scale.scale_var.set(0) |
0 | 140 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
|
141 self.update_cue_display() |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
142 def update_cue_display(self): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
143 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
|
144 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
|
145 def xfade(self, name, scale): |
0 | 146 scale_val = scale.scale_var.get() |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
147 # print "xfade", name, scale_val |
0 | 148 |
149 if scale_val == 1: | |
155 | 150 if self.auto_shift.get(): |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
151 print "autoshifting", name |
0 | 152 self.shift(name) |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
153 scale_val = scale.scale_var.get() # this needs to be refreshed |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
154 else: |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
155 self.shift_buttons[name]['state'] = 'normal' |
0 | 156 else: |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
157 # disable any dangerous shifting |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
158 self.shift_buttons[name]['state'] = 'disabled' |
0 | 159 |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
160 d = self.opposite_direction(name) |
0 | 161 if scale_val != 0: |
162 # 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
|
163 self.scales[d].disable() |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
164 self.go_buttons[d].disable() |
0 | 165 else: |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
166 # undo above work |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
167 self.scales[d].enable() |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
168 self.go_buttons[d].enable() |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
169 def opposite_direction(self, d): |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
170 if d == 'Next': |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
171 return 'Prev' |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
172 else: |
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
173 return 'Next' |
0 | 174 |
175 class Cue: | |
176 """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
|
177 def __init__(self, name, time=3, **attrs): |
0 | 178 self.name = name |
179 self.time = time | |
180 self.__dict__.update(attrs) | |
181 def __repr__(self): | |
182 return "<Cue %s, length %s>" % (self.name, self.time) | |
183 | |
184 empty_cue = Cue('empty') | |
185 | |
186 allow_class_to_be_pickled(Cue) | |
187 | |
188 class CueList: | |
189 """Persistent list of Cues""" | |
190 def __init__(self, filename): | |
191 self.filename = filename | |
192 self.treedict = TreeDict() | |
193 try: | |
194 self.treedict.load(filename) | |
195 except IOError: | |
196 self.treedict.cues = [] | |
197 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
|
198 self.current_cue_index = 0 |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
199 self.next_pointer = None |
0 | 200 self.prev_pointer = None |
201 | |
202 import atexit | |
203 atexit.register(self.save) | |
204 def add_cue(self, cue, index=None): | |
205 """Adds a Cue object to the list. If no index is specified, | |
206 the cue will be added to the end.""" | |
207 index = index or len(self.cues) | |
208 self.cues.insert(index, cue) | |
209 def shift(self, diff): | |
210 """Shift through cue history""" | |
211 old_index = self.current_cue_index | |
212 self.current_cue_index = None | |
213 if diff < 0: # if going backwards | |
214 if self.prev_pointer: # use a prev pointer if we have one | |
215 self.current_cue_index = self.prev_pointer | |
216 self.next_pointer = old_index | |
217 self.prev_pointer = None | |
218 else: | |
219 if self.next_pointer: # use a next pointer if we have one | |
220 self.current_cue_index = self.next_pointer | |
221 self.next_pointer = None | |
222 self.prev_pointer = old_index | |
223 if not self.current_cue_index: | |
224 self.current_cue_index = old_index + diff | |
225 def set_next(self, index): | |
226 self.next_pointer = index | |
227 def set_prev(self, index): | |
228 self.prev_pointer = index | |
229 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
|
230 if not self.cues: |
0 | 231 return None |
232 else: | |
158
5c7ac46e33d3
more disabling of stuff that make no sense at certain times and some
dmcc
parents:
157
diff
changeset
|
233 return max(0, min(index, len(self.cues) - 1)) |
0 | 234 def get_current_cue_indices(self): |
235 cur = self.current_cue_index | |
236 return [self.bound_index(index) for index in | |
237 (self.prev_pointer or cur - 1, | |
238 cur, | |
239 self.next_pointer or cur + 1)] | |
240 def get_current_cues(self): | |
241 return [self.get_cue_by_index(index) | |
242 for index in self.get_current_cue_indices()] | |
243 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
|
244 if index: |
0 | 245 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
|
246 else: |
0 | 247 return empty_cue |
248 def __del__(self): | |
249 self.save() | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
250 def save(self): |
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
251 self.treedict.save(self.filename) |
0 | 252 |
253 if __name__ == "__main__": | |
157 | 254 cl = CueList('cues/cuelist1') |
0 | 255 |
157 | 256 # to populate cue list |
257 if 0: | |
258 for x in range(20): | |
259 cl.add_cue(Cue('cue %d' % x, time=x, some_attribute=3)) | |
151
990a9474d0e7
early cue stuff. the CueList will supply the CueFader with the cues to
dmcc
parents:
0
diff
changeset
|
260 |
157 | 261 root = Tk.Tk() |
262 fader = CueFader(root, cl) | |
263 fader.pack(fill='both', expand=1) | |
264 Tk.mainloop() |