Mercurial > code > home > repos > light9
comparison flax/curvecalc @ 202:97e21bc387fe
loading and saving
loading and saving
fixed the hanging bug in update()
author | drewp |
---|---|
date | Wed, 16 Jun 2004 14:22:48 +0000 |
parents | f5d3492981ab |
children | 3905d3c92aaa |
comparison
equal
deleted
inserted
replaced
201:e4a711d9a338 | 202:97e21bc387fe |
---|---|
3 """ | 3 """ |
4 todo: curveview should preserve more objects, for speed maybe | 4 todo: curveview should preserve more objects, for speed maybe |
5 | 5 |
6 """ | 6 """ |
7 from __future__ import division | 7 from __future__ import division |
8 import xmlrpclib,time,socket,sys,textwrap,math | 8 import xmlrpclib,time,socket,sys,textwrap,math,glob |
9 from bisect import bisect_left,bisect,bisect_right | 9 from bisect import bisect_left,bisect,bisect_right |
10 import Tkinter as tk | 10 import Tkinter as tk |
11 from dispatch import dispatcher | 11 from dispatch import dispatcher |
12 from twisted.internet import reactor,tksupport | 12 from twisted.internet import reactor,tksupport |
13 from twisted.web.xmlrpc import Proxy | 13 from twisted.web.xmlrpc import Proxy |
23 """curve does not know its name. see Curveset""" | 23 """curve does not know its name. see Curveset""" |
24 points = None # x-sorted list of (x,y) | 24 points = None # x-sorted list of (x,y) |
25 def __init__(self): | 25 def __init__(self): |
26 self.points = [] | 26 self.points = [] |
27 | 27 |
28 self.points = [(0,0),(1,1),(9,1),(10,0)] | 28 def load(self,filename): |
29 for x in range(11,500): | 29 for line in file(filename): |
30 self.points.append((x,.5)) | 30 self.points.append(tuple([float(a) for a in line.split()])) |
31 self.points.sort() | |
32 dispatcher.send("points changed",sender=self) | |
33 | |
34 def save(self,filename): | |
35 f = file(filename,'w') | |
36 for p in self.points: | |
37 f.write("%s %s\n" % p) | |
38 f.close() | |
31 | 39 |
32 def eval(self,t): | 40 def eval(self,t): |
33 i = bisect_left(self.points,(t,None))-1 | 41 i = bisect_left(self.points,(t,None))-1 |
34 | 42 |
35 if self.points[i][0]>t: | 43 if self.points[i][0]>t: |
53 self.selected_points=[] # idx of points being dragged | 61 self.selected_points=[] # idx of points being dragged |
54 self.update() | 62 self.update() |
55 self.bind("<Enter>",self.focus) | 63 self.bind("<Enter>",self.focus) |
56 dispatcher.connect(self.input_time,"input time") | 64 dispatcher.connect(self.input_time,"input time") |
57 dispatcher.connect(self.update,"zoom changed") | 65 dispatcher.connect(self.update,"zoom changed") |
66 dispatcher.connect(self.update,"points changed",sender=self.curve) | |
58 self.bind("<Configure>",self.update) | 67 self.bind("<Configure>",self.update) |
59 def screen_from_world(self,p): | 68 def screen_from_world(self,p): |
60 start,end = self.zoom | 69 start,end = self.zoom |
61 ht = self.winfo_height() | 70 ht = self.winfo_height() |
62 return (p[0]-start)/(end-start)*self.winfo_width(), (ht-5)-p[1]*(ht-10) | 71 return (p[0]-start)/(end-start)*self.winfo_width(), (ht-5)-p[1]*(ht-10) |
79 self.world_from_screen(self.winfo_width(),0)[0]) | 88 self.world_from_screen(self.winfo_width(),0)[0]) |
80 | 89 |
81 visleftidx = max(0,bisect_left(cp,(visible_x[0],None))-1) | 90 visleftidx = max(0,bisect_left(cp,(visible_x[0],None))-1) |
82 visrightidx = min(len(cp)-1,bisect_left(cp,(visible_x[1],None))+1) | 91 visrightidx = min(len(cp)-1,bisect_left(cp,(visible_x[1],None))+1) |
83 | 92 |
84 visible_points = cp[visleftidx:visrightidx] | 93 visible_points = cp[visleftidx:visrightidx+1] |
85 | 94 |
86 self.delete('curve') | 95 self.delete('curve') |
87 linepts=[] | 96 linepts=[] |
88 for p in visible_points: | 97 for p in visible_points: |
89 linepts.extend(self.screen_from_world(p)) | 98 linepts.extend(self.screen_from_world(p)) |
99 if not linepts: | |
100 return | |
90 line = self.create_line(*linepts,**{'tags':'curve'}) | 101 line = self.create_line(*linepts,**{'tags':'curve'}) |
91 | 102 |
92 # canvas doesnt have keyboard focus, so i can't easily change the | 103 # canvas doesnt have keyboard focus, so i can't easily change the |
93 # cursor when ctrl is pressed | 104 # cursor when ctrl is pressed |
94 # def curs(ev): | 105 # def curs(ev): |
95 # print ev.state | 106 # print ev.state |
96 # self.bind("<KeyPress>",curs) | 107 # self.bind("<KeyPress>",curs) |
97 # self.bind("<KeyRelease-Control_L>",lambda ev: curs(0)) | 108 # self.bind("<KeyRelease-Control_L>",lambda ev: curs(0)) |
98 self.tag_bind(line,"<Control-ButtonPress-1>",self.newpoint) | 109 self.tag_bind(line,"<Control-ButtonPress-1>",self.newpoint) |
99 | 110 |
100 self.dots = {} # idx : canvas rectangle | 111 self.dots = {} # idx : canvas rectangle |
101 | 112 |
102 if len(visible_points)<50: ###self.zoom[1]-self.zoom[0]<30 or len(visible_points)<: | 113 if len(visible_points)<50: |
103 for i,p in enumerate(visible_points): | 114 for i,p in enumerate(visible_points): |
104 rad=3 | 115 rad=3 |
105 p = self.screen_from_world(p) | 116 p = self.screen_from_world(p) |
106 # if p[0]-prevx<10: | |
107 # # too close- skip the dots | |
108 # continue | |
109 dot = self.create_rectangle(p[0]-rad,p[1]-rad,p[0]+rad,p[1]+rad, | 117 dot = self.create_rectangle(p[0]-rad,p[1]-rad,p[0]+rad,p[1]+rad, |
110 outline='black',fill='blue', | 118 outline='black',fill='blue', |
111 tags=('curve','point')) | 119 tags=('curve','point')) |
112 self.tag_bind(dot,"<ButtonPress-1>", | 120 self.tag_bind(dot,"<ButtonPress-1>", |
113 lambda ev,i=i: self.dotpress(ev,i)) | 121 lambda ev,i=i: self.dotpress(ev,i)) |
143 def dotmotion(self,ev,dotidx): | 151 def dotmotion(self,ev,dotidx): |
144 cp = self.curve.points | 152 cp = self.curve.points |
145 | 153 |
146 moved=0 | 154 moved=0 |
147 for idx in self.selected_points: | 155 for idx in self.selected_points: |
148 newp = self.world_from_screen(ev.x,ev.y) | 156 x,y = self.world_from_screen(ev.x,ev.y) |
149 if idx>0 and newp[0]<=cp[idx-1][0]: | 157 y = max(0,min(1,y)) |
158 if idx>0 and x<=cp[idx-1][0]: | |
150 continue | 159 continue |
151 if idx<len(cp)-1 and newp[0]>=cp[idx+1][0]: | 160 if idx<len(cp)-1 and x>=cp[idx+1][0]: |
152 continue | 161 continue |
153 moved=1 | 162 moved=1 |
154 cp[idx] = newp | 163 cp[idx] = (x,y) |
155 if moved: | 164 if moved: |
156 self.update() | 165 self.update() |
157 def unselect(self): | 166 def unselect(self): |
158 self.selected_points=[] | 167 self.selected_points=[] |
159 self.highlight_selected_dots() | 168 self.highlight_selected_dots() |
163 | 172 |
164 class Curveset: | 173 class Curveset: |
165 curves = None # curvename : curve | 174 curves = None # curvename : curve |
166 def __init__(self): | 175 def __init__(self): |
167 self.curves = {} | 176 self.curves = {} |
177 def load(self,basename): | |
178 """find all files that look like basename-curvename and add | |
179 curves with their contents""" | |
180 for filename in glob.glob("%s-*"%basename): | |
181 curvename = filename[filename.rfind('-')+1:] | |
182 c=Curve() | |
183 c.load(filename) | |
184 self.add_curve(curvename,c) | |
185 def save(self,basename): | |
186 """writes a file for each curve with a name | |
187 like basename-curvename""" | |
188 for name,cur in self.curves.items(): | |
189 cur.save("%s-%s" % (basename,name)) | |
168 def add_curve(self,name,curve): | 190 def add_curve(self,name,curve): |
169 self.curves[name] = curve | 191 self.curves[name] = curve |
170 dispatcher.send("add_curve",sender=self,name=name) | 192 dispatcher.send("add_curve",sender=self,name=name) |
171 def globalsdict(self): | 193 def globalsdict(self): |
172 return self.curves.copy() | 194 return self.curves.copy() |
194 def current_time(self): | 216 def current_time(self): |
195 """return deferred which gets called with the current time""" | 217 """return deferred which gets called with the current time""" |
196 if self.player is None: | 218 if self.player is None: |
197 self.player = Proxy("http://spot:8040") | 219 self.player = Proxy("http://spot:8040") |
198 d = self.player.callRemote("songlength") | 220 d = self.player.callRemote("songlength") |
199 def sendmax(l): | 221 d.addCallback(lambda l: dispatcher.send("max time",maxtime=l)) |
200 dispatcher.send("max time",maxtime=l) | 222 d = self.player.callRemote("songname") |
201 d.addCallback(sendmax) | 223 d.addCallback(lambda n: dispatcher.send("songname",name=n)) |
202 d = self.player.callRemote('gettime') | 224 d = self.player.callRemote('gettime') |
203 def sendtime(t): | 225 def sendtime(t): |
204 dispatcher.send("input time",val=t) | 226 dispatcher.send("input time",val=t) |
205 return t # pass along to the real receiver | 227 return t # pass along to the real receiver |
206 def error(e): | 228 def error(e): |
283 scaledsubs.append(scl) | 305 scaledsubs.append(scl) |
284 out = Submaster.sub_maxes(*scaledsubs) | 306 out = Submaster.sub_maxes(*scaledsubs) |
285 dispatcher.send("output levels",val=out.get_levels()) | 307 dispatcher.send("output levels",val=out.get_levels()) |
286 dmxclient.outputlevels(out.get_dmx_list(),twisted=1) | 308 dmxclient.outputlevels(out.get_dmx_list(),twisted=1) |
287 | 309 |
288 def statuslines(master): | 310 def create_status_lines(master): |
289 for signame,textfilter in [ | 311 for signame,textfilter in [ |
290 ('input time',lambda t: "%.2fs"%t), | 312 ('input time',lambda t: "%.2fs"%t), |
291 ('output levels', | 313 ('output levels', |
292 lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v) | 314 lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v) |
293 for n,v in | 315 for n,v in |
298 l.pack(side='top',fill='x') | 320 l.pack(side='top',fill='x') |
299 dispatcher.connect(lambda val,l=l,sn=signame,tf=textfilter: | 321 dispatcher.connect(lambda val,l=l,sn=signame,tf=textfilter: |
300 l.config(text=sn+": "+tf(val)), | 322 l.config(text=sn+": "+tf(val)), |
301 signame,weak=0) | 323 signame,weak=0) |
302 | 324 |
325 def savesubterms(filename,subterms): | |
326 f = file(filename,'w') | |
327 for st in subterms: | |
328 f.write("%s %s\n" % (st.sub.name,st.subexpr.expr)) | |
329 f.close() | |
330 | |
331 def save(song,subterms,curveset): | |
332 savesubterms("subterms/"+song,subterms) | |
333 curveset.save(basename="curves/"+song) | |
303 | 334 |
304 ####################################################################### | 335 ####################################################################### |
305 root=tk.Tk() | 336 root=tk.Tk() |
306 root.wm_geometry("790x930") | 337 root.wm_geometry("790x930") |
307 #root.tk_focusFollowsMouse() | 338 #root.tk_focusFollowsMouse() |
308 | 339 |
309 m=Music() | 340 music=Music() |
310 | 341 |
311 zc = Zoomcontrol(root) | 342 zc = Zoomcontrol(root) |
312 zc.pack(side='top',fill='x') | 343 zc.pack(side='top',fill='x') |
313 | 344 |
314 cs = Curveset() | 345 curveset = Curveset() |
315 csv = Curvesetview(root,cs) | 346 csv = Curvesetview(root,curveset) |
316 csv.pack(side='top',fill='both',exp=1) | 347 csv.pack(side='top',fill='both',exp=1) |
317 | 348 |
318 for loop in range(6): | 349 song = "16mix.wav" |
319 cs.add_curve('c'+str(loop+1),Curve()) | 350 |
351 curveset.load(basename="curves/"+song) | |
320 | 352 |
321 subterms = [] | 353 subterms = [] |
322 for subname in "zip_orange","zip_red": | 354 for line in file("subterms/"+song): |
323 | 355 subname,expr = line.strip().split(" ",1) |
324 se = Subexpr(cs) | 356 |
325 if subname=='zip_orange': | 357 term = Subterm() |
326 se.expr="c1(t)+c2(t)+c3(t)+c4(t)+c5(t)" | 358 |
359 sexpr = Subexpr(curveset) | |
360 sexpr.expr = expr | |
327 | 361 |
328 st=Subterm() | 362 term.sub = Submaster.Submaster(subname) |
329 st.sub=Submaster.Submaster(subname) | 363 term.subexpr = sexpr |
330 st.subexpr=se | 364 subterms.append(term) |
331 | 365 |
332 stv=Subtermview(root,st) | 366 stv=Subtermview(root,term) |
333 stv.pack(side='top',fill='x') | 367 stv.pack(side='top',fill='x') |
334 subterms.append(st) | |
335 | 368 |
336 out = Output(subterms) | 369 out = Output(subterms) |
337 | 370 |
338 statuslines(root) | 371 #save(song,subterms,curveset) |
372 | |
373 create_status_lines(root) | |
339 | 374 |
340 recent_t=[] | 375 recent_t=[] |
376 later = None | |
341 def update(): | 377 def update(): |
342 d = m.current_time() | 378 global later |
379 d = music.current_time() | |
343 d.addCallback(update2) | 380 d.addCallback(update2) |
344 d.addErrback(updateerr) | 381 d.addErrback(updateerr) |
345 def updateerr(e): | 382 def updateerr(e): |
346 reactor.callLater(1,update) | 383 global later |
384 print "err",e | |
385 if later and not later.cancelled and not later.called: later.cancel() | |
386 later = reactor.callLater(1,update) | |
347 def update2(t): | 387 def update2(t): |
348 global recent_t | 388 global recent_t,later |
349 reactor.callLater(.001,update) | 389 |
390 if later and not later.cancelled and not later.called: later.cancel() | |
391 later = reactor.callLater(.01,update) | |
350 | 392 |
351 recent_t = recent_t[-50:]+[t] | 393 recent_t = recent_t[-50:]+[t] |
352 period = (recent_t[-1]-recent_t[0])/len(recent_t) | 394 period = (recent_t[-1]-recent_t[0])/len(recent_t) |
353 dispatcher.send("update period",val=period) | 395 dispatcher.send("update period",val=period) |
354 out.send_dmx(t) | 396 out.send_dmx(t) |