Changeset - cbc98de2ab06
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 16 years ago 2009-06-15 02:21:48
drewp@bigasterisk.com
refactor curveCalc toplevel
Ignore-this: de2c8786b6929ffe2037a04a443d3cf4
1 file changed with 117 insertions and 115 deletions:
bin/curvecalc
117
115
0 comments (0 inline, 0 general)
bin/curvecalc
Show inline comments
 
@@ -7,15 +7,14 @@ now launches like this:
 

	
 

	
 
todo: curveview should preserve more objects, for speed maybe
 

	
 
"""
 
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:
 
    import louie as dispatcher 
 
from twisted.internet import reactor,tksupport
 
import twisted
 
@@ -27,29 +26,26 @@ import logging
 
log = logging.getLogger()
 
logging.basicConfig(format="%(asctime)s %(levelname)-5s %(name)s %(filename)s:%(lineno)d: %(message)s")
 
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
 
import light9.Effects
 

	
 
class Music:
 
    def __init__(self):
 
        self.player=None # xmlrpc Proxy to player
 
        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"""
 
        if self.player is None:
 
            print "connect to player"
 
            self.player = Proxy(networking.musicUrl())
 
@@ -217,22 +213,22 @@ class Subtermview(tk.Frame):
 
        sev=Subexprview(self,self.subterm.subexpr)
 
        sev.pack(side='left',fill='both',exp=1)
 

	
 
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=[]
 
        self.later = None
 

	
 
        self.update()
 
        
 
    def update(self):
 
        d = music.current_time()
 
        d = self.music.current_time()
 
        d.addCallback(self.update2)
 
        d.addErrback(self.updateerr)
 
        
 
    def updateerr(self,e):
 

	
 
        print e.getTraceback()
 
@@ -289,44 +285,30 @@ def create_status_lines(master):
 
        l = tk.Label(master,anchor='w',justify='left')
 
        l.pack(side='top',fill='x')
 
        dispatcher.connect(lambda val,l=l,sn=signame,tf=textfilter:
 
                           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
 

	
 
    term = Subterm(Submaster.Submaster(graph=graph, sub=subUri),
 
                   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()
 

	
 
    def add_cmd(evt):
 
        uri = L9['sub/%s' % newname.get()]
 
        graph.add((uri, RDF.type, L9.Subterm))
 
@@ -371,24 +353,24 @@ def createSubtermGraph(song, subterms):
 
        graph.add((uri, RDF.type, L9['Subterm']))
 
        graph.add((uri, RDFS.label, Literal(subterm.submaster.name)))
 
        graph.add((uri, L9['sub'], L9['sub/%s' % subterm.submaster.name]))
 
        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)
 
                
 

	
 
def graphPathForSubterms(song):
 
    return showconfig.subtermsForSong(showconfig.songFilenameFromURI(song)) + ".n3"
 

	
 
@@ -396,97 +378,117 @@ def read_all_subs(graph):
 
    """read all sub files into this graph so when add_one_subterm tries
 
    to add, the sub will be available"""
 
    subsDir = showconfig.subsDir()
 
    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("<Control-Key-s>",savekey)
 
root.bind("<Control-Key-r>", lambda evt: dispatcher.send('reload all subs'))
 
root.bind("<Control-Key-n>", lambda evt: dispatcher.send('focus new subterm'))
 
root.bind("<Control-Key-N>", lambda evt: dispatcher.send('focus new curve'))
 

	
 
def setupKeyBindings(root, song, subterms, curveset):
 
    root.bind("<Control-Key-s>",
 
              lambda *args: savekey(song, subterms, curveset))
 
    root.bind("<Control-Key-r>", lambda evt: dispatcher.send('reload all subs'))
 
    root.bind("<Control-Key-n>",
 
              lambda evt: dispatcher.send('focus new subterm'))
 
    root.bind("<Control-Key-N>", lambda evt: dispatcher.send('focus new curve'))
 
    root.bind("<Control-Key-q>",lambda ev: reactor.stop)
 
    root.bind("<Destroy>",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("<Control-Key-q>",lambda ev: reactor.stop)
 
root.bind("<Destroy>",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()
0 comments (0 inline, 0 general)