Changeset - 3905d3c92aaa
[Not reviewed]
default
0 7 2
drewp - 20 years ago 2005-04-10 15:03:24

twisted mainloop, more row-change keys, xmlrpc fadesub command on port 8050
9 files changed with 404 insertions and 100 deletions:
0 comments (0 inline, 0 general)
flax/KeyboardComposer.py
Show inline comments
 
from __future__ import nested_scopes
 
from __future__ import division,nested_scopes
 
import sys, time
 
sys.path.append('..')
 
from Widgets.Fadable import Fadable
 

	
 
from twisted.internet import reactor,tksupport
 
from twisted.web import xmlrpc, server
 
from Tix import *
 
import math, atexit, pickle
 
from Submaster import Submasters, sub_maxes
 
import dmxclient
 
from uihelpers import toplevelat
 

	
 
@@ -37,16 +39,16 @@ class SubScale(Scale, Fadable):
 
class SubmasterTk(Frame):
 
    def __init__(self, master, name, current_level):
 
        Frame.__init__(self, master, bd=1, relief='raised', bg='black')
 
        self.slider_var = DoubleVar()
 
        self.slider_var.set(current_level)
 
        self.scale = SubScale(self, variable=self.slider_var, width=20)
 
        namelabel = Label(self, text=name, font="Arial 8", bg='black',
 
        namelabel = Label(self, text=name, font="Arial 11", bg='black',
 
            fg='white')
 
        namelabel.pack(side=TOP)
 
        levellabel = Label(self, textvariable=self.slider_var, font="Arial 8",
 
        levellabel = Label(self, textvariable=self.slider_var, font="Arial 11",
 
            bg='black', fg='white')
 
        levellabel.pack(side=TOP)
 
        self.scale.pack(side=BOTTOM, expand=1, fill=BOTH)
 

	
 
class KeyboardComposer(Frame):
 
    def __init__(self, root, submasters, current_sub_levels=None, dmxdummy=0):
 
@@ -67,12 +69,13 @@ class KeyboardComposer(Frame):
 
        self.draw_ui()
 
        self.send_levels_loop()
 
    def draw_ui(self):
 
        self.rows = [] # this holds Tk Frames for each row
 
        self.slider_vars = {} # this holds subname:sub Tk vars
 
        self.slider_table = {} # this holds coords:sub Tk vars
 
        self.name_to_subtk = {} # subname : SubmasterTk instance
 
        self.current_row = 0
 
        
 
        self.make_key_hints()
 
        self.draw_sliders()
 
        self.highlight_row(self.current_row)
 
        self.rows[self.current_row].focus()
 
@@ -120,19 +123,22 @@ class KeyboardComposer(Frame):
 
                keysym = "<KeyPress-%s>" % key.upper()
 
                keysym = keysym.replace('SEMICOLON', 'colon')
 
                tkobject.bind(keysym, \
 
                    lambda evt, num=keys.index(key), d=d: \
 
                        self.got_nudger(num, d, full=1))
 

	
 
        # page up and page down change the row
 
        for key in '<Prior> <Next> <Control-n> <Control-p>'.split():
 
        # Row changing:
 
        # Page dn, C-n, and ] do down
 
        # Page up, C-p, and ' do up
 
        for key in '<Prior> <Next> <Control-n> <Control-p> ' \
 
                   '<Key-bracketright> <Key-apostrophe>'.split():
 
            tkobject.bind(key, self.change_row)
 

	
 
    def change_row(self, event):
 
        diff = 1
 
        if event.keysym in ('Prior', 'p'):
 
        if event.keysym in ('Prior', 'p', 'bracketright'):
 
            diff = -1
 
        old_row = self.current_row
 
        self.current_row += diff
 
        self.current_row = max(0, self.current_row)
 
        self.current_row = min(len(self.rows) - 1, self.current_row)
 
        self.unhighlight_row(old_row)
 
@@ -160,12 +166,13 @@ class KeyboardComposer(Frame):
 
            if col == 0: # make new row
 
                row = self.make_row()
 
                rowcount += 1
 
            current_level = self.current_sub_levels.get(sub.name, 0)
 
            subtk = self.draw_sub_slider(row, col, sub.name, current_level)
 
            self.slider_table[(rowcount, col)] = subtk
 
            self.name_to_subtk[sub.name] = subtk
 
            col += 1
 
            col %= 10
 

	
 
            def slider_changed(x, y, z, subtk=subtk):
 
                subtk.scale.draw_indicator_colors()
 
                self.send_levels()
 
@@ -200,12 +207,13 @@ class KeyboardComposer(Frame):
 
        maxes = sub_maxes(*scaledsubs)
 
        return maxes
 
    def save_current_stage(self, subname):
 
        print "saving current levels as", subname
 
        sub = self.get_levels_as_sub()
 
        sub.name = subname
 
        sub.temporary = 0
 
        sub.save()
 

	
 
    def save(self):
 
        pickle.dump(self.get_levels(), 
 
                    file('.keyboardcomposer.savedlevels', 'w'))
 
    def send_frequent_updates(self):
 
@@ -233,19 +241,36 @@ class KeyboardComposer(Frame):
 
        for r in self.rows:
 
            r.destroy()
 
        self.keyhints.destroy()
 
        self.buttonframe.destroy()
 
        self.draw_ui()
 

	
 
class LevelServer(xmlrpc.XMLRPC):
 
    def __init__(self,name_to_subtk):
 
        self.name_to_subtk = name_to_subtk
 
        
 
    def xmlrpc_fadesub(self,subname,level,secs):
 
        """submaster will fade to level in secs"""
 
        try:
 
            self.name_to_subtk[subname].scale.fade(level,secs)
 
            ret='ok'
 
        except Exception,e:
 
            ret=str(e)
 
        return ret
 

	
 

	
 
if __name__ == "__main__":
 
    s = Submasters()
 

	
 
    root = Tk()
 
    tl = toplevelat("Keyboard Composer", existingtoplevel=root)
 
    kc = KeyboardComposer(tl, s, dmxdummy=0)
 
    kc.pack(fill=BOTH, expand=1)
 
    atexit.register(kc.save)
 
    try:
 
        mainloop()
 
    except KeyboardInterrupt:
 
        tl.destroy()
 
        sys.exit()
 

	
 
    ls = LevelServer(kc.name_to_subtk)
 
    reactor.listenTCP(8050, server.Site(ls))
 

	
 
    root.bind("<Destroy>",reactor.stop)
 
    root.protocol('WM_DELETE_WINDOW', reactor.stop)
 
    reactor.addSystemEventTrigger('after','shutdown',kc.save)
 
    tksupport.install(root,ms=10)
 
    reactor.run()
flax/MusicTime.py
Show inline comments
 
@@ -31,13 +31,13 @@ class MusicTimeTk(tk.Frame, MusicTime):
 
        self.update_time()
 
    def update_time(self):
 
        self.timevar.set(self.get_music_time())
 
        self.after(100, self.update_time)
 

	
 
if __name__ == "__main__":
 
    from optik import OptionParser
 
    from optparse import OptionParser
 
    parser = OptionParser()
 
    parser.add_option("-s", "--server", default='dash')
 
    parser.add_option("-p", "--port", default=8040, type='int')
 
    options, args = parser.parse_args()
 
    
 
    root = tk.Tk()
flax/Submaster.py
Show inline comments
 
@@ -34,12 +34,13 @@ class Submaster:
 
                    print "(%s) Error with this line: %s" % (self.name, 
 
                        line[:-1])
 
        except IOError:
 
            print "Can't read file for sub: %s" % self.name
 
    def save(self):
 
        if self.temporary:
 
            print "not saving temporary sub named",self.name
 
            return
 

	
 
        subfile = file("subs/%s" % self.name, 'w')
 
        names = self.levels.keys()
 
        names.sort()
 
        for name in names:
flax/TimelineDMX.py
Show inline comments
 
@@ -24,13 +24,13 @@ class ShowRunner(tk.Frame):
 
            b.pack(side='top',fill='x')
 
        self.tl_list.pack()
 
    def set_timeline(self, tlname):
 
        print "TimelineDMX: set timeline to", tlname
 
        self.show.set_timeline(tlname)
 
    def find_player(self):
 
        self.player = xmlrpclib.Server("http://localhost:8040")
 
        self.player = xmlrpclib.Server("http://spot:8040")
 
    def send_levels(self):
 
        levels = self.show.calc_active_submaster().get_dmx_list()
 
        
 
        dmxclient.outputlevels(levels)
 
    def sync_times(self):
 
        try:
flax/add_sub
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 
# usage: add_sub [-l sublevel] subname subterms_to_add_to
 

	
 
from optparse import OptionParser
 

	
 
parser = OptionParser()
 
parser.add_option('-l', '--level', default='0')
 
opts, args = parser.parse_args()
 
print 'debug', opts, args
 

	
 
sub = args.pop(0)
 
print "adding '%s' at %s" % (sub, opts.level)
 

	
 
for subterm in args:
 
    print "subterm", subterm
 
    print
 
    filename = 'subterms/%s' % subterm
 
    subs = [line.split(None, 1)[0] for line in file(filename).readlines()]
 
    if sub not in subs:
 
        f = file(filename, 'a')
 
        print 'appended!'
 
        print >>f, "%s %s" % (sub, opts.level)
flax/curvecalc
Show inline comments
 
@@ -2,39 +2,46 @@
 

	
 
"""
 
todo: curveview should preserve more objects, for speed maybe
 

	
 
"""
 
from __future__ import division
 
import xmlrpclib,time,socket,sys,textwrap,math,glob
 
import xmlrpclib,time,socket,sys,textwrap,math,glob,random
 
from bisect import bisect_left,bisect,bisect_right
 
import Tkinter as tk
 
from dispatch import dispatcher
 
from twisted.internet import reactor,tksupport
 
import twisted
 
from twisted.web.xmlrpc import Proxy
 

	
 
sys.path.append("../light8")
 
import dmxclient
 
sys.path.append("../../semprini")
 
from lengther import wavelength
 
import Submaster
 
from TLUtility import make_attributes_from_args
 

	
 
from zoomcontrol import Zoomcontrol
 

	
 
class Curve:
 
    """curve does not know its name. see Curveset"""
 
    points = None # x-sorted list of (x,y)
 
    def __init__(self):
 
        self.points = []
 
        self.points = [(0,0),(10,0)]
 

	
 
    def load(self,filename):
 
        self.points[:]=[]
 
        for line in file(filename):
 
            self.points.append(tuple([float(a) for a in line.split()]))
 
        self.points.sort()
 
        dispatcher.send("points changed",sender=self)
 

	
 
    def save(self,filename):
 
        if filename.endswith('-music') or filename.endswith('_music'):
 
            print "not saving music track"
 
            return
 
        f = file(filename,'w')
 
        for p in self.points:
 
            f.write("%s %s\n" % p)
 
        f.close()
 

	
 
    def eval(self,t):
 
@@ -47,27 +54,51 @@ class Curve:
 

	
 
        p1,p2 = self.points[i],self.points[i+1]
 
        frac = (t-p1[0])/(p2[0]-p1[0])
 
        y = p1[1]+(p2[1]-p1[1])*frac
 
        return y
 

	
 
    def insert_pt(self,new_pt):
 
        i = bisect(self.points,(new_pt[0],None))
 
        self.points.insert(i,new_pt)
 
    __call__=eval
 

	
 
class Curveview(tk.Canvas):
 
    def __init__(self,master,curve,**kw):
 
        self.curve=curve
 
        self._time = 0
 
        tk.Canvas.__init__(self,master,width=10,height=10,
 
                           relief='sunken',bd=1,
 
                           closeenough=5,**kw)
 
                           closeenough=5,takefocus=1, **kw)
 
        self.selected_points=[] # idx of points being dragged
 
        self.update()
 
        self.bind("<Enter>",self.focus)
 
        # self.bind("<Enter>",self.focus)
 
        dispatcher.connect(self.input_time,"input time")
 
        dispatcher.connect(self.update,"zoom changed")
 
        dispatcher.connect(self.update,"points changed",sender=self.curve)
 
        self.bind("<Configure>",self.update)
 
        for x in range(1, 6):
 
            def add_kb_marker_point(evt, x=x):
 
                print "add_kb_marker_point", evt
 
                self.add_point((self.current_time(), (x - 1) / 4.0))
 

	
 
            self.bind("<Key-%s>" % x, add_kb_marker_point)
 

	
 

	
 
        for butnum,factor in (5, 1.5),(4, 1/1.5):
 
            self.bind("<ButtonPress-%s>"%butnum,
 
                      lambda ev,factor=factor:
 
                      dispatcher.send("zoom about mouse",
 
                                      t=self.world_from_screen(ev.x,0)[0],
 
                                      factor=factor))
 
        self.bind("<Key-Escape>",lambda ev:
 
                  dispatcher.send("see time",
 
                                  t=self.current_time()))
 
    def current_time(self):
 
        return self._time
 

	
 
    def screen_from_world(self,p):
 
        start,end = self.zoom
 
        ht = self.winfo_height()
 
        return (p[0]-start)/(end-start)*self.winfo_width(), (ht-5)-p[1]*(ht-10)
 
    def world_from_screen(self,x,y):
 
        start,end = self.zoom
 
@@ -76,68 +107,120 @@ class Curveview(tk.Canvas):
 
    
 
    def input_time(self,val):
 
        t=val
 
        pts = self.screen_from_world((val,0))+self.screen_from_world((val,1))
 
        self.delete('timecursor')
 
        self.create_line(*pts,**dict(width=2,fill='red',tags=('timecursor',)))
 
        self._time = t
 
    def update(self,*args):
 

	
 
        self.zoom = dispatcher.send("zoom area")[0][1]
 
        cp = self.curve.points
 

	
 
        visible_x = (self.world_from_screen(0,0)[0],
 
                     self.world_from_screen(self.winfo_width(),0)[0])
 

	
 
        visleftidx = max(0,bisect_left(cp,(visible_x[0],None))-1)
 
        visrightidx = min(len(cp)-1,bisect_left(cp,(visible_x[1],None))+1)
 
                             
 
        visible_points = cp[visleftidx:visrightidx+1]
 
        visible_idxs = range(visleftidx,visrightidx+1)
 
        
 
        self.delete('curve')
 

	
 
        self._draw_markers(visible_x)
 
        
 
        self._draw_line(visible_idxs,visible_points)
 
        
 
        self.dots = {} # idx : canvas rectangle
 

	
 
        if len(visible_points)<50:
 
            self._draw_handle_points(visible_idxs,visible_points)
 

	
 
    def _draw_markers(self,visible_x):
 
        mark = self._draw_one_marker
 

	
 
        mark(0,"0")
 
        t1,t2=visible_x
 
        if t2-t1<30:
 
            for t in range(int(t1),int(t2)+1):
 
                mark(t,str(t))
 
        mark(-4,"-4")
 

	
 
        endtimes = dispatcher.send("get max time")
 
        if endtimes:
 
            endtime = endtimes[0][1]
 
            mark(endtime,"end %.1f"%endtime)
 
            mark(endtime+10,"post %.1f"%(endtime+10))
 
        
 
    def _draw_one_marker(self,t,label):
 
        x = self.screen_from_world((t,0))[0]
 
        self.create_line(x,self.winfo_height(),x,self.winfo_height()-20,
 
                         tags=('curve',))
 
        self.create_text(x,self.winfo_height()-20,text=label,anchor='s',
 
                         tags=('curve',))
 

	
 

	
 
    def _draw_line(self,visible_idxs,visible_points):
 
        linepts=[]
 
        for p in visible_points:
 
        step=1
 
        linewidth=2
 
        if len(visible_points)>800:
 
            step = int(len(visible_points)/800)
 
            linewidth=1
 
        for p in visible_points[::step]:
 
            linepts.extend(self.screen_from_world(p))
 
        if not linepts:
 
        if len(linepts)<4:
 
            return
 
        line = self.create_line(*linepts,**{'tags':'curve'})
 
        line = self.create_line(*linepts,**dict(width=linewidth,tags='curve'))
 

	
 
        # canvas doesnt have keyboard focus, so i can't easily change the
 
        # cursor when ctrl is pressed
 
        #        def curs(ev):
 
        #            print ev.state
 
        #        self.bind("<KeyPress>",curs)
 
        #        self.bind("<KeyRelease-Control_L>",lambda ev: curs(0))
 
        self.tag_bind(line,"<Control-ButtonPress-1>",self.newpoint)
 
        self.tag_bind(line,"<Control-ButtonPress-1>",self.newpointatmouse)
 

	
 
        self.dots = {} # idx : canvas rectangle
 

	
 
        if len(visible_points)<50: 
 
            for i,p in enumerate(visible_points):
 
                rad=3
 
                p = self.screen_from_world(p)
 
                dot = self.create_rectangle(p[0]-rad,p[1]-rad,p[0]+rad,p[1]+rad,
 
                                            outline='black',fill='blue',
 
                                            tags=('curve','point'))
 
                self.tag_bind(dot,"<ButtonPress-1>",
 
                              lambda ev,i=i: self.dotpress(ev,i))
 
                self.bind("<Motion>",
 
                          lambda ev,i=i: self.dotmotion(ev,i))
 
                self.bind("<ButtonRelease-1>",
 
                          lambda ev,i=i: self.dotrelease(ev,i))
 
                self.dots[i]=dot
 
    def _draw_handle_points(self,visible_idxs,visible_points):
 
        for i,p in zip(visible_idxs,visible_points):
 
            rad=3
 
            worldp = p
 
            p = self.screen_from_world(p)
 
            dot = self.create_rectangle(p[0]-rad,p[1]-rad,p[0]+rad,p[1]+rad,
 
                                        outline='black',fill='blue',
 
                                        tags=('curve','point', 'handle%d' % i))
 
            if worldp[1] == 0:
 
                rad += 3
 
                dot2 = self.create_oval(p[0]-rad,p[1]-rad,
 
                                             p[0]+rad,p[1]+rad,
 
                                             outline='darkgreen',
 
                                             tags=('curve','point', 'handle%d' % i))
 
            self.tag_bind('handle%d' % i,"<ButtonPress-1>",
 
                          lambda ev,i=i: self.dotpress(ev,i))
 
            self.bind("<Motion>",
 
                      lambda ev,i=i: self.dotmotion(ev,i))
 
            self.bind("<ButtonRelease-1>",
 
                      lambda ev,i=i: self.dotrelease(ev,i))
 
            self.dots[i]=dot
 

	
 
            self.highlight_selected_dots()
 

	
 
    def newpoint(self,ev):
 
        cp = self.curve.points
 
        self.highlight_selected_dots()
 
        
 
        p = self.world_from_screen(ev.x,ev.y)
 
        i = bisect(cp,(p[0],None))
 

	
 
    def newpointatmouse(self, ev):
 
        p = self.world_from_screen(ev.x,ev.y)
 
        x, y = p
 
        y = max(0, y)
 
        y = min(1, y)
 
        p = x, y
 
        self.add_point(p)
 

	
 
    def add_point(self, p):
 
        self.unselect()
 
        cp.insert(i,p)
 
        self.curve.insert_pt(p)
 
        self.update()
 

	
 
    def highlight_selected_dots(self):
 
        for i,d in self.dots.items():
 
            if i in self.selected_points:
 
                self.itemconfigure(d,fill='red')
 
@@ -147,13 +230,12 @@ class Curveview(tk.Canvas):
 
    def dotpress(self,ev,dotidx):
 
        self.selected_points=[dotidx]
 
        self.highlight_selected_dots()
 

	
 
    def dotmotion(self,ev,dotidx):
 
        cp = self.curve.points
 

	
 
        moved=0
 
        for idx in self.selected_points:
 
            x,y = self.world_from_screen(ev.x,ev.y)
 
            y = max(0,min(1,y))
 
            if idx>0 and x<=cp[idx-1][0]:
 
                continue
 
@@ -175,82 +257,130 @@ class Curveset:
 
    def __init__(self):
 
        self.curves = {}
 
    def load(self,basename):
 
        """find all files that look like basename-curvename and add
 
        curves with their contents"""
 
        for filename in glob.glob("%s-*"%basename):
 
            curvename = filename[filename.rfind('-')+1:]
 
            curvename = filename[filename.find('-')+1:]
 
            c=Curve()
 
            c.load(filename)
 
            curvename = curvename.replace('-','_')
 
            self.add_curve(curvename,c)            
 
    def save(self,basename):
 
        """writes a file for each curve with a name
 
        like basename-curvename"""
 
        for name,cur in self.curves.items():
 
            cur.save("%s-%s" % (basename,name))
 
    def add_curve(self,name,curve):
 
        self.curves[name] = curve
 
        dispatcher.send("add_curve",sender=self,name=name)
 
    def globalsdict(self):
 
        return self.curves.copy()
 
    def new_curve(self,name):
 
        if name=="":
 
            print "no name given"
 
            return
 
        while name in self.curves:
 
           name=name+"-1"
 

	
 
        self.add_curve(name,Curve())
 

	
 

	
 
class Curvesetview(tk.Frame):
 
    curves = None # curvename : Curveview
 
    def __init__(self,master,curveset,**kw):
 
        self.curves = {}
 
        self.curveset = curveset
 
        tk.Frame.__init__(self,master,**kw)
 
        
 
        f = tk.Frame(self,relief='raised',bd=1)
 
        f.pack(side='top',fill='x')
 
        tk.Button(f,text="new curve named:",
 
                  command=lambda: self.curveset.new_curve(self.newcurvename.get())).pack(side='left')
 
        self.newcurvename = tk.StringVar()
 
        tk.Entry(f,textvariable=self.newcurvename).pack(side='left',
 
                                                        fill='x',exp=1)
 
        
 
        
 
        dispatcher.connect(self.add_curve,"add_curve",sender=self.curveset)
 
    def add_curve(self,name):
 
        f = tk.Frame(self,relief='raised',bd=1)
 
        f.pack(side='top',fill='both',exp=1)
 
        tk.Label(f,text="curve %r"%name).pack(side='left')
 
        tk.Label(f,text="curve %r"%name,width=15).pack(side='left')
 
        cv = Curveview(f,self.curveset.curves[name])
 
        cv.pack(side='right',fill='both',exp=1)
 
        self.curves[name] = cv
 

	
 
class Music:
 
    def __init__(self):
 
        self.player=None # xmlrpc Proxy to player
 
        self.recenttime=0
 
        
 
    def current_time(self):
 
        """return deferred which gets called with the current time"""
 
        if self.player is None:
 
            self.player = Proxy("http://spot:8040")
 
            d = self.player.callRemote("songlength")
 
            d.addCallback(lambda l: dispatcher.send("max time",maxtime=l))
 
            d = self.player.callRemote("songname")
 
            d.addCallback(lambda n: dispatcher.send("songname",name=n))
 
            self.player = Proxy("http://miles:8040")
 
#            d = self.player.callRemote("songlength")
 
#            d.addCallback(lambda l: dispatcher.send("max time",maxtime=l))
 
#            d = self.player.callRemote("songname")
 
#            d.addCallback(lambda n: dispatcher.send("songname",name=n))
 
        d = self.player.callRemote('gettime')
 
        def sendtime(t):
 
            dispatcher.send("input time",val=t)
 
            return t # pass along to the real receiver
 
        def error(e):
 
            pass#self.player=None
 
        d.addCallback(sendtime)
 
        return d
 
        
 
class Subexpr:
 
    curveset = None
 
    def __init__(self,curveset):
 
    def __init__(self,curveset,expr=""):
 
        self.curveset = curveset
 
        self.lasteval = None
 
        self.expr=""
 
        self.expr=expr
 
        self._smooth_random_items = [random.random() for x in range(100)]
 
    def eval(self,t):
 
        if self.expr=="":
 
            dispatcher.send("expr_error",sender=self,exc="no expr, using 0")
 
            return 0
 
        glo = self.curveset.globalsdict()
 
        glo['t'] = t
 

	
 
        glo['nsin'] = lambda x: (math.sin(x * (2 * math.pi)) + 1) / 2
 
        glo['ncos'] = lambda x: (math.cos(x * (2 * math.pi)) + 1) / 2
 
        glo['within'] = lambda a, b: a < t < b
 
        glo['bef'] = lambda x: t < x
 
        glo['aft'] = lambda x: x < t
 
        glo['smoove'] = lambda x: -2 * (x ** 3) + 3 * (x ** 2)
 

	
 
        def smooth_random(speed=1):
 
            """1 = new stuff each second, <1 is slower, fade-ier"""
 
            x = (t * speed) % len(self._smooth_random_items)
 
            x1 = int(x)
 
            x2 = (int(x) + 1) % len(self._smooth_random_items)
 
            y1 = self._smooth_random_items[x1]
 
            y2 = self._smooth_random_items[x2]
 
            return y1 + (y2 - y1) * ((x - x1))
 

	
 
        def notch_random(speed=1):
 
            """1 = new stuff each second, <1 is slower, notch-ier"""
 
            x = (t * speed) % len(self._smooth_random_items)
 
            x1 = int(x)
 
            y1 = self._smooth_random_items[x1]
 
            return y1
 
            
 
        glo['noise'] = smooth_random
 
        glo['notch'] = notch_random
 

	
 
        try:
 
            self.lasteval = eval(self.expr,glo)
 
        except Exception,e:
 
            dispatcher.send("expr_error",sender=self,exc=e)
 
        else:
 
            dispatcher.send("expr_error",sender=self,exc="no errors")
 
            dispatcher.send("expr_error",sender=self,exc="ok")
 
        return self.lasteval
 

	
 
    def expr():
 
        doc = "python expression for level as a function of t, using curves"
 
        def fget(self):
 
            return self._expr
 
@@ -280,98 +410,154 @@ class Subexprview(tk.Frame):
 
            self.evar.set(self.subexpr.expr)
 
    def evar_changed(self,*args):
 
        self.subexpr.expr = self.evar.get()
 

	
 
class Subterm:
 
    """one Submaster and its Subexpr"""
 
    def __init__(self,submaster,subexpr):
 
        make_attributes_from_args('submaster','subexpr')
 
    def scaled(self,t):
 
        return self.sub * self.subexpr.eval(t)
 
        return self.submaster * self.subexpr.eval(t)
 

	
 
class Subtermview(tk.Frame):
 
    def __init__(self,master,st,**kw):
 
        self.subterm = st
 
        tk.Frame.__init__(self,master,bd=1,relief='raised',**kw)
 
        tk.Label(self,text="sub %r" % self.subterm.sub.name).pack(side='left')
 
        l = tk.Label(self,text="sub %r" % self.subterm.submaster.name)
 
        l.pack(side='left')
 
        sev=Subexprview(self,self.subterm.subexpr)
 
        sev.pack(side='left',fill='both',exp=1)
 

	
 
class Output:
 
    lastsendtime=0
 
    lastsendlevs=None
 
    def __init__(self,subterms):
 
        make_attributes_from_args('subterms')
 
    def send_dmx(self,t):
 

	
 
        scaledsubs=[]
 
        for st in self.subterms:
 
            scl = st.scaled(t)
 
            scaledsubs.append(scl)
 
        out = Submaster.sub_maxes(*scaledsubs)
 
        dispatcher.send("output levels",val=out.get_levels())
 
        dmxclient.outputlevels(out.get_dmx_list(),twisted=1)
 
        levs = out.get_levels()
 
        now=time.time()
 
        if now-self.lastsendtime>5 or levs!=self.lastsendlevs:
 
            dispatcher.send("output levels",val=levs)
 
            dmxclient.outputlevels(out.get_dmx_list(),
 
                                   twisted=1,clientid='curvecalc')
 
            self.lastsendtime = now
 
            self.lastsendlevs = levs
 

	
 
def create_status_lines(master):
 
    for signame,textfilter in [
 
        ('input time',lambda t: "%.2fs"%t),
 
        ('output levels',
 
         lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v)
 
                                                 for n,v in
 
                                                 levels.items()]),70)),
 
                                                 levels.items()[:5]
 
                                                 if v>0]),70)),
 
        ('update period',lambda t: "%.1fms"%(t*1000)),
 
        ]:
 
        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)
 

	
 
def savesubterms(filename,subterms):
 
    f = file(filename,'w')
 
    s=""
 
    for st in subterms:
 
        f.write("%s %s\n" % (st.sub.name,st.subexpr.expr))
 
    f.close()
 
        s=s+"%s %s\n" % (st.submaster.name,st.subexpr.expr)
 
    
 
    file(filename,'w').write(s)
 

	
 
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 save(song,subterms,curveset):
 
    savesubterms("subterms/"+song,subterms)
 
    curveset.save(basename="curves/"+song)
 
def add_one_subterm(subname, curveset, subterms, root, expr=''):
 
    term = Subterm(Submaster.Submaster(subname), Subexpr(curveset,expr))
 
    subterms.append(term)
 

	
 
    stv=Subtermview(ssv,term)
 
    # stv.pack(side='top',fill='x')
 
    global ssv
 
    ssv.add_subtermview(stv)
 

	
 
    return term
 

	
 
def subterm_adder(master, curveset, subterms, root):
 
    f=tk.Frame(master,relief='raised',bd=1)
 
    newname = tk.StringVar()
 

	
 
    def add_cmd():
 
        add_one_subterm(newname.get(), curveset, subterms, root, '')
 

	
 
    tk.Button(f,text="new subterm named:", command=add_cmd).pack(side='left')
 
    tk.Entry(f,textvariable=newname).pack(side='left',fill='x',exp=1)
 
    return f
 
    
 
#######################################################################
 
root=tk.Tk()
 
root.wm_geometry("790x930")
 
#root.tk_focusFollowsMouse()
 
root.tk_setPalette("gray50")
 
root.wm_geometry("1120x850")
 
root.tk_focusFollowsMouse()
 

	
 
music=Music()
 

	
 
zc = Zoomcontrol(root)
 
zc.pack(side='top',fill='x')
 

	
 
curveset = Curveset()
 
csv = Curvesetview(root,curveset)
 
csv.pack(side='top',fill='both',exp=1)
 

	
 
song = "16mix.wav"
 
ssv = SubtermSetView(root)
 
ssv.pack(side='top', fill='x')
 

	
 
song = sys.argv[1]
 
root.title("Curemaster 2000MX - %s" % song)
 

	
 
musicfilename = "/my/music/projects/sharlyn2004/%s.wav" % song
 
maxtime = wavelength(musicfilename)
 
dispatcher.send("max time",maxtime=maxtime)
 
dispatcher.connect(lambda: maxtime, "get max time",weak=0)
 
curveset.load(basename="curves/"+song)
 

	
 
subterms = []
 
subterm_adder(root, curveset, subterms, root).pack(side='top',fill='x')
 
for line in file("subterms/"+song):
 
    subname,expr = line.strip().split(" ",1)
 

	
 
    term = Subterm()
 

	
 
    sexpr = Subexpr(curveset)
 
    sexpr.expr = expr
 
    term = add_one_subterm(subname, curveset, subterms, root, expr)
 
    
 
    term.sub = Submaster.Submaster(subname)
 
    term.subexpr = sexpr
 
    subterms.append(term)
 
    
 
    stv=Subtermview(root,term)
 
    stv.pack(side='top',fill='x')
 
    # stv=Subtermview(root,term)
 
    # stv.pack(side='top',fill='x')
 

	
 
out = Output(subterms)
 

	
 
#save(song,subterms,curveset)
 
def savekey(*args):
 
    print "saving",song
 
    savesubterms("subterms/"+song,subterms)
 
    curveset.save(basename="curves/"+song)
 
    print "saved"
 

	
 
    
 
root.bind("<Control-Key-s>",savekey)
 

	
 
create_status_lines(root)
 
    
 
recent_t=[]
 
later = None
 
def update():
 
@@ -393,12 +579,19 @@ def update2(t):
 
    recent_t = recent_t[-50:]+[t]
 
    period = (recent_t[-1]-recent_t[0])/len(recent_t)
 
    dispatcher.send("update period",val=period)
 
    out.send_dmx(t)
 
update()
 

	
 
#def logprint(msg):
 
#    print "log",msg
 
#twisted.python.log.addObserver(logprint)
 

	
 
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=10)
 
if 0:
 
    sys.path.append("/home/drewp/projects/editor/pour")
 
    from utils import runstats
 
    runstats("reactor.run()")
 
else:
flax/dmxchanedit.py
Show inline comments
 
@@ -9,13 +9,13 @@ import Tkinter as tk
 
import sys
 
sys.path.append("../light8")
 
import Patch
 
from uihelpers import make_frame, colorlabel, eventtoparent
 
from dispatch import dispatcher
 

	
 
stdfont = ('Arial', 10)
 
stdfont = ('Arial', 12)
 

	
 
class Onelevel(tk.Frame):
 
    """a name/level pair"""
 
    def __init__(self, parent, channelnum):
 
        """channelnum is 1..68, like the real dmx"""
 
        tk.Frame.__init__(self,parent)
 
@@ -50,26 +50,29 @@ class Onelevel(tk.Frame):
 
        
 
    def setupmousebindings(self):
 
        def b1down(ev):
 
            self.desc_lab.config(bg='cyan')
 
            self._start_y=ev.y
 
            self._start_lev=self.currentlevel
 
#        self.bind("<ButtonPress-1>",b1down)
 
        def b1motion(ev):
 
            delta=self._start_y-ev.y
 
            self.changelevel(self._start_lev+delta*.005)
 
#        self.bind("<B1-Motion>",b1motion)
 
        def b1up(ev):
 
            self.desc_lab.config(bg='black')
 
#        self.bind("<B1-ButtonRelease>",b1up)
 
        def b3up(ev):
 
            self.changelevel(0.0)
 
        def b3down(ev):
 
            self.changelevel(1.0)
 

	
 
        # make the buttons work in the child windows
 
        for w in self.winfo_children():
 
            for e,func in (('<ButtonPress-1>',b1down),
 
                           ('<B1-Motion>',b1motion),
 
                           ('<ButtonRelease-1>',b1up)):
 
                           ('<ButtonRelease-1>',b1up),
 
                           ('<ButtonRelease-3>', b3up),
 
                           ('<ButtonPress-3>', b3down)):
 
                w.bind(e,func)
 
#                w.bind(e,lambda ev,e=e: eventtoparent(ev,e))
 
        
 
    def colorlabel(self):
 
        """color the level label based on its own text (which is 0..100)"""
 
        txt=self.level_lab['text'] or "0"
flax/kcclient
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 

	
 
"""send KeyboardComposer a fade request, for use from the shell"""
 

	
 
import sys,xmlrpclib
 

	
 
subname = sys.argv[1]
 
level = float(sys.argv[2])
 
fadesecs = 0
 
if len(sys.argv)>3:
 
    fadesecs = float(sys.argv[3])
 

	
 
levelserver = xmlrpclib.ServerProxy("http://localhost:8050")
 

	
 
levelserver.fadesub(subname,level,fadesecs)
 

	
 

	
flax/zoomcontrol.py
Show inline comments
 
from __future__ import division
 
import Tkinter as tk
 
from dispatch import dispatcher
 

	
 
class Zoomcontrol(object,tk.Canvas):
 

	
 
    mintime=-5
 

	
 
    def maxtime():
 
        doc = "seconds at the right edge of the bar"
 
        def fget(self): return self._maxtime
 
        def fset(self, value):
 
            self._maxtime = value
 
            self.updatewidget()
 
        return locals()
 
    maxtime = property(**maxtime())
 
    
 
    def start():
 
        def fget(self): return self._start
 
        def fset(self,v): self._start = max(0,v)
 
        def fset(self,v): self._start = max(self.mintime,v)
 
        return locals()
 
    start = property(**start())
 

	
 
    def end():
 
        def fget(self): return self._end
 
        def fset(self,v): self._end = min(self.maxtime,v)
 
@@ -36,32 +38,73 @@ class Zoomcontrol(object,tk.Canvas):
 
        self.rightbrack = self.create_line(0,0,0,0,0,0,0,0,width=5)
 
        self.shade = self.create_rectangle(0,0,0,0,fill='gray70',outline=None)
 
        self.time = self.create_line(0,0,0,0,fill='red',width=2)
 
        self.updatewidget()
 
        self.bind("<Configure>",self.updatewidget)
 

	
 
        self.bind("<ButtonPress-1>",lambda ev: setattr(self,'lastx',ev.x))
 
        self.tag_bind(self.leftbrack,"<B1-Motion>",
 
                      lambda ev: self.adjust('start',ev))
 
        self.tag_bind(self.rightbrack,"<B1-Motion>",
 
                      lambda ev: self.adjust('end',ev))
 
        self.tag_bind(self.shade,"<B1-Motion>",
 
                      lambda ev: self.adjust('offset',ev))
 
        if 0:
 
            # works, but you have to stay in the widget while you drag
 
            self.bind("<ButtonPress-1>",self.press)
 
            self.tag_bind(self.leftbrack,"<B1-Motion>",
 
                          lambda ev: self.adjust(ev,'start'))
 
            self.tag_bind(self.rightbrack,"<B1-Motion>",
 
                          lambda ev: self.adjust(ev,'end'))
 
            self.tag_bind(self.shade,"<B1-Motion>",
 
                          lambda ev: self.adjust(ev,'offset'))
 
        else:
 
            # works better
 
            # bind to buttonpress wasnt working, but Enter is good enough
 
            self.tag_bind(self.leftbrack,"<Enter>",
 
                          lambda ev: self.press(ev,'start'))
 
            self.tag_bind(self.shade,"<Enter>",
 
                          lambda ev: self.press(ev,'offset'))
 
            self.tag_bind(self.rightbrack,"<Enter>",
 
                          lambda ev: self.press(ev,'end'))
 
            self.bind("<B1-Motion>",self.adjust)
 
            self.bind("<ButtonRelease-1>",self.release)
 
        
 
        dispatcher.connect(lambda: (self.start,self.end),"zoom area",weak=0)
 
        dispatcher.connect(self.input_time,"input time")
 
        dispatcher.connect(lambda maxtime: (setattr(self,'maxtime',maxtime),
 
                                            self.updatewidget()),"max time",weak=0)
 
        dispatcher.connect(lambda maxtime: (setattr(self,'maxtime',maxtime+15),
 
                                            self.updatewidget()),
 
                           "max time",weak=0)
 
        dispatcher.connect(self.zoom_about_mouse,"zoom about mouse")
 
        dispatcher.connect(self.see_time,"see time")
 
        self.created=1
 
    def zoom_about_mouse(self,t,factor):
 
        self.start = t - factor*(t-self.start)
 
        self.end = t + factor*(self.end-t)
 
        self.updatewidget()
 
        dispatcher.send("zoom changed")
 
    def see_time(self,t):
 
        margin = (self.end-self.start)*.5 # centering is nicest
 
        if t<self.start:
 
            self.offset-=(self.start-t)+margin
 
        if t>self.end:
 
            self.offset+=(t-self.end)+margin
 
        self.updatewidget()
 
        dispatcher.send("zoom changed")
 
            
 
    def input_time(self,val):
 
        t=val
 
        x=self.can_for_t(t)
 
        self.coords(self.time,x,0,x,self.winfo_height())
 
    def press(self,ev,attr):
 
        self.adjustingattr = attr
 
        
 
    def release(self,ev):
 
        if hasattr(self,'adjustingattr'): del self.adjustingattr
 
        if hasattr(self,'lastx'): del self.lastx
 
    def adjust(self,ev,attr=None):
 

	
 
    def adjust(self,attr,ev):
 
        if not hasattr(self,'adjustingattr'):
 
            return
 
        attr = self.adjustingattr
 
        
 
        if not hasattr(self,'lastx'):
 
            return
 
            self.lastx = ev.x
 
        new = self.can_for_t(getattr(self,attr)) + (ev.x - self.lastx)
 
        self.lastx = ev.x
 
        setattr(self,attr,self.t_for_can(new))
 
        self.updatewidget()
 
        dispatcher.send("zoom changed")
 
        
 
@@ -74,26 +117,26 @@ class Zoomcontrol(object,tk.Canvas):
 
            self.start = value
 
            self.end = self.start+d
 
        return locals()
 
    offset = property(**offset())
 

	
 
    def can_for_t(self,t):
 
        return t/self.maxtime*(self.winfo_width()-30)+20
 
        return (t-self.mintime)/(self.maxtime-self.mintime)*(self.winfo_width()-30)+20
 
    def t_for_can(self,x):
 
        return (x-20)/(self.winfo_width()-30)*self.maxtime
 
        return (x-20)/(self.winfo_width()-30)*(self.maxtime-self.mintime)+self.mintime
 

	
 
    def updatewidget(self,*args):
 
        """redraw pieces based on start/end"""
 
        if not hasattr(self,'created'): return
 
        y1,y2=3,self.winfo_height()-3
 
        lip = 6
 
        scan = self.can_for_t(self.start)
 
        ecan = self.can_for_t(self.end)
 
        self.coords(self.leftbrack,scan+lip,y1,scan,y1,scan,y2,scan+lip,y2)
 
        self.coords(self.rightbrack,ecan-lip,y1,ecan,y1,ecan,y2,ecan-lip,y2)
 
        self.coords(self.shade,scan+3,y1+lip,ecan-3,y2-lip)
 
        self.coords(self.shade,scan+5,y1+lip,ecan-5,y2-lip)
 
        self.delete("tics")
 
        lastx=-1000
 
        for t in range(0,int(self.maxtime)):
 
            x = self.can_for_t(t)
 
            if 0<x<self.winfo_width() and x-lastx>30:
 
                txt=str(t)
0 comments (0 inline, 0 general)