diff --git a/bin/curvecalc b/bin/curvecalc --- a/bin/curvecalc +++ b/bin/curvecalc @@ -10,9 +10,8 @@ todo: curveview should preserve more obj """ from __future__ import division -import xmlrpclib,time,socket,sys,textwrap,math,glob,random,os,optparse,traceback -from bisect import bisect_left,bisect,bisect_right -import Tkinter as tk +import time,textwrap,math,random,os,optparse +import Tix as tk try: from dispatch import dispatcher except ImportError: @@ -30,9 +29,9 @@ log.setLevel(logging.DEBUG) import run_local from light9 import Submaster, dmxclient, networking, showconfig, prof, Patch -from light9.TLUtility import make_attributes_from_args, dict_subset +from light9.TLUtility import make_attributes_from_args from light9.zoomcontrol import Zoomcontrol -from light9.curve import Curve, Curveview, Curveset, Curvesetview +from light9.curve import Curveset, Curvesetview from light9.wavelength import wavelength from light9.uihelpers import toplevelat from light9.namespaces import L9 @@ -44,9 +43,6 @@ class Music: self.recenttime=0 dispatcher.connect(self.seekplay_or_pause,"music seek") - - def seekplay_or_pause(self,t): - self.music.seekplay_or_pause(t) def current_time(self): """return deferred which gets called with the current time""" @@ -220,7 +216,7 @@ class Subtermview(tk.Frame): class Output: lastsendtime=0 lastsendlevs=None - def __init__(self,subterms,music): + def __init__(self, subterms, music): make_attributes_from_args('subterms','music') self.recent_t=[] @@ -229,7 +225,7 @@ class Output: self.update() def update(self): - d = music.current_time() + d = self.music.current_time() d.addCallback(self.update2) d.addErrback(self.updateerr) @@ -292,22 +288,7 @@ def create_status_lines(master): l.config(text=sn+": "+tf(val)), signame,weak=0) -class SubtermSetView(tk.Frame): - def __init__(self, master, *args, **kw): - tk.Frame.__init__(self, master, *args, **kw) - self.cur_row = 0 - self.cur_col = 0 - self.ncols = 2 - def add_subtermview(self, stv): - stv.grid(row=self.cur_row, column=self.cur_col, sticky='news') - self.columnconfigure(self.cur_col, weight=1) - - self.cur_col += 1 - self.cur_col %= self.ncols - if self.cur_col == 0: - self.cur_row += 1 - -def add_one_subterm(graph, subUri, curveset, subterms, root, ssv, expr=None): +def add_one_subterm(graph, subUri, curveset, subterms, root, master, expr=None): subname = graph.label(subUri) if expr is None: expr = '%s(t)' % subname @@ -316,14 +297,15 @@ def add_one_subterm(graph, subUri, curve Subexpr(curveset,expr)) subterms.append(term) - stv=Subtermview(ssv, graph, term) - # stv.pack(side='top',fill='x') - - ssv.add_subtermview(stv) + stv=Subtermview(master, graph, term) + stv.pack(side='top',fill='x') return term def sub_commands_tk(master, curveset, subterms, root, ssv, graph): + """ + the row that starts with 'reload subs' button + """ f=tk.Frame(master,relief='raised',bd=1) newname = tk.StringVar() @@ -374,18 +356,18 @@ def createSubtermGraph(song, subterms): graph.add((uri, L9['expression'], Literal(subterm.subexpr.expr))) return graph -def add_subterms_for_song(graph, song, curveset, subterms, root, ssv): +def add_subterms_for_song(graph, song, curveset, subterms, root, master): for st in graph.objects(song, L9['subterm']): try: add_one_subterm(graph, graph.value(st, L9['sub']), curveset, subterms, - root, ssv, graph.value(st, L9['expression'])) + root, master, graph.value(st, L9['expression'])) except rdflib.exceptions.UniquenessError: print "working around curvecalc save corruption" # curvecalc put all the expressions on one subterm, which is wrong for expr in graph.objects(st, L9['expression']): add_one_subterm(graph, graph.value(st, L9['sub']), curveset, subterms, - root, ssv, + root, master, expr) @@ -399,94 +381,114 @@ def read_all_subs(graph): for filename in os.listdir(subsDir): graph.parse(os.path.join(subsDir, filename), format="n3") -####################################################################### -root=tk.Tk() -root.tk_setPalette("gray50") -toplevelat("curvecalc",root) -root.tk_focusFollowsMouse() - -parser = optparse.OptionParser() -parser.set_usage("%prog [opts] songURI") -parser.add_option("--sliders", action='store_true', - help='use hardware sliders') -parser.add_option("--skip-music", action='store_true', - help="ignore music and smooth_music curve files") -opts, args = parser.parse_args() - -try: - song = URIRef(args[0]) -except IndexError: - raise SystemExit("song URI is required, e.g. 'http://light9.bigasterisk.com/show/dance2008/song3'") - -log.debug("music") -music=Music() - -zc = Zoomcontrol(root) -zc.pack(side='top',fill='x') - -curveset = Curveset(sliders=opts.sliders) -csv = Curvesetview(root, curveset) -csv.pack(side='top',fill='both',exp=1) +def makeGraph(): + graphOrig = showconfig.getGraph() + graph = Graph() # a copy, since we're going to add subs into it + for s in graphOrig: + graph.add(s) + read_all_subs(graph) + return graph -ssv = SubtermSetView(root) -ssv.pack(side='top', fill='x') - -graphOrig = showconfig.getGraph() -graph = Graph() # a copy, since we're going to add subs into it -for s in graphOrig: - graph.add(s) -read_all_subs(graph) -root.title("Curvemaster 3000MX - %s" % graph.label(song)) - -musicfilename = showconfig.songOnDisk(song) -maxtime = wavelength(musicfilename) -dispatcher.send("max time",maxtime=maxtime) -dispatcher.connect(lambda: maxtime, "get max time",weak=0) -dispatcher.send("show all") -curveset.load(basename=os.path.join(showconfig.curvesDir(), - showconfig.songFilenameFromURI(song)), - skipMusic=opts.skip_music) - -subterms = [] -sub_commands_tk(root, curveset, subterms, root, ssv, graph).pack(side='top',fill='x') - -try: - graph.parse(graphPathForSubterms(song), format='n3') - add_subterms_for_song(graph, song, curveset, subterms, root, ssv) -except OSError, e: - print e - -log.debug("output") -out = Output(subterms, music) - -def savekey(*args): - print "saving",song +def savekey(song, subterms, curveset): + print "saving", song g = createSubtermGraph(song, subterms) g.serialize(graphPathForSubterms(song), format="nt") - curveset.save(basename=os.path.join(showconfig.curvesDir(), showconfig.songFilenameFromURI(song))) + curveset.save(basename=os.path.join(showconfig.curvesDir(), + showconfig.songFilenameFromURI(song))) print "saved" - -root.bind("",savekey) -root.bind("", lambda evt: dispatcher.send('reload all subs')) -root.bind("", lambda evt: dispatcher.send('focus new subterm')) -root.bind("", lambda evt: dispatcher.send('focus new curve')) + +def setupKeyBindings(root, song, subterms, curveset): + root.bind("", + lambda *args: savekey(song, subterms, curveset)) + root.bind("", lambda evt: dispatcher.send('reload all subs')) + root.bind("", + lambda evt: dispatcher.send('focus new subterm')) + root.bind("", lambda evt: dispatcher.send('focus new curve')) + root.bind("",lambda ev: reactor.stop) + root.bind("",lambda ev: reactor.stop) + root.protocol('WM_DELETE_WINDOW', reactor.stop) + +def createHelpLines(root): + for helpline in ["Bindings: C-s save subterms; Esc see current time; S-Esc see curtime to end; C-Esc show all; Mousewheel zoom; C-p play/pause music at mouse", + "Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; Del selected points; 1..5 add point at time; B1 drag select points", + "Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve"]: + line = tk.Label(root, text=helpline, font="Helvetica -12 italic", + anchor='w') + line.pack(side='top',fill='x') + + +def main(): + root=tk.Tk() + root.tk_setPalette("gray50") + toplevelat("curvecalc",root) + root.tk_focusFollowsMouse() + + parser = optparse.OptionParser() + parser.set_usage("%prog [opts] songURI") + parser.add_option("--sliders", action='store_true', + help='use hardware sliders') + parser.add_option("--skip-music", action='store_true', + help="ignore music and smooth_music curve files") + opts, args = parser.parse_args() + + try: + song = URIRef(args[0]) + except IndexError: + raise SystemExit("song URI is required, e.g. 'http://light9.bigasterisk.com/show/dance2008/song3'") + + log.debug("music") + music=Music() + + zc = Zoomcontrol(root) + zc.pack(side='top',fill='x') -create_status_lines(root) -for helpline in ["Bindings: C-s save subterms; Esc see current time; S-Esc see curtime to end; C-Esc show all; Mousewheel zoom; C-p play/pause music at mouse", - "Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; Del selected points; 1..5 add point at time; B1 drag select points", - "Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve"]: - tk.Label(root,text=helpline, font="Helvetica -12 italic", - anchor='w').pack(side='top',fill='x') + curveset = Curveset(sliders=opts.sliders) + csv = Curvesetview(root, curveset) + csv.pack(side='top',fill='both',exp=1) + + subtermArea = tk.Frame(root) + subtermArea.pack(side='top', fill='x') + + sw = tk.ScrolledWindow(subtermArea) + sw.pack(fill='both') + subtermScroll = tk.Frame(sw.subwidget('window')) + subtermScroll.pack(fill='both') + + graph = makeGraph() + + + musicfilename = showconfig.songOnDisk(song) + maxtime = wavelength(musicfilename) + dispatcher.send("max time",maxtime=maxtime) + dispatcher.connect(lambda: maxtime, "get max time",weak=0) + dispatcher.send("show all") + curveset.load(basename=os.path.join(showconfig.curvesDir(), + showconfig.songFilenameFromURI(song)), + skipMusic=opts.skip_music) -#def logprint(msg): -# print "log",msg -#twisted.python.log.addObserver(logprint) + subterms = [] + sub_commands_tk(root, curveset, subterms, root, subtermArea, + graph).pack(side='top',fill='both') + + try: + graph.parse(graphPathForSubterms(song), format='n3') + add_subterms_for_song(graph, song, curveset, subterms, root, + subtermScroll) + except OSError, e: + print e -root.bind("",lambda ev: reactor.stop) -root.bind("",lambda ev: reactor.stop) -root.protocol('WM_DELETE_WINDOW', reactor.stop) -tksupport.install(root,ms=20) -log.debug("run") -prof.run(reactor.run, profile=False) + log.debug("output") + out = Output(subterms, music) + + setupKeyBindings(root, song, subterms, curveset) + create_status_lines(root) + createHelpLines(root) + root.title("Curvemaster 3000MX - %s" % graph.label(song)) + + tksupport.install(root,ms=20) + log.debug("run") + prof.run(reactor.run, profile=False) + +main()