Changeset - a6662d61ebcd
[Not reviewed]
default
0 6 4
Drew Perttula - 18 years ago 2007-06-10 08:09:08
drewp@bigasterisk.com
SC, KC, CC now run and seem to load and save ok. CC does not have any rdf for its data files
10 files changed with 162 insertions and 26 deletions:
0 comments (0 inline, 0 general)
bin/curvecalc
Show inline comments
 
#!/usr/bin/python
 

	
 
"""
 
now launches like this:
 
% bin/curvecalc http://light9.bigasterisk.com/show/dance2007/song1
 

	
 

	
 

	
 
todo: curveview should preserve more objects, for speed maybe
 

	
 
"""
 
from __future__ import division
 
import xmlrpclib,time,socket,sys,textwrap,math,glob,random,os,optparse
 
from bisect import bisect_left,bisect,bisect_right
 
@@ -286,18 +291,18 @@ def add_one_subterm(graph, sub, curveset
 
    # stv.pack(side='top',fill='x')
 

	
 
    ssv.add_subtermview(stv)
 

	
 
    return term
 

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

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

	
 
    def reload_subs():
 
        dispatcher.send('reload all subs')
 

	
 
    tk.Button(f, text="reload subs (C-r)", 
 
@@ -311,12 +316,15 @@ def sub_commands_tk(master, curveset, su
 

	
 
def add_subterms_for_song(graph, song, curveset, subterms, root, ssv):
 
    for st in graph.objects(song, L9['subterm']):
 
        add_one_subterm(graph, graph.value(st, L9['sub']), curveset, subterms,
 
                        root, ssv, graph.value(st, L9['expression']))
 

	
 
def songFilename(uri):
 
    return uri.split('/')[-1]
 

	
 
#######################################################################
 
root=tk.Tk()
 
root.tk_setPalette("gray50")
 
toplevelat("curvecalc",root)
 
root.tk_focusFollowsMouse()
 

	
 
@@ -345,26 +353,26 @@ graph = showconfig.getGraph()
 
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)
 
curveset.load(basename=os.path.join(showconfig.curvesDir(),song))
 
curveset.load(basename=os.path.join(showconfig.curvesDir(), songFilename(song)))
 

	
 
subterms = []
 
sub_commands_tk(root, curveset, subterms, root, ssv).pack(side='top',fill='x')
 
sub_commands_tk(root, curveset, subterms, root, ssv, graph).pack(side='top',fill='x')
 

	
 
add_subterms_for_song(graph, song, curveset, subterms, root, ssv)
 

	
 
log.debug("output")
 
out = Output(subterms, music)
 

	
 
def savekey(*args):
 
    print "saving",song
 
    savesubterms(showconfig.subtermsForSong(song),subterms)
 
    curveset.save(basename=os.path.join(showconfig.curvesDir(),song))
 
    savesubterms(showconfig.subtermsForSong(songFilename(song)), subterms)
 
    curveset.save(basename=os.path.join(showconfig.curvesDir(), songFilename(song)))
 
    print "saved"
 
    
 
root.bind("<Control-Key-s>",savekey)
 
root.bind("<Control-Key-r>", lambda evt: dispatcher.send('reload all subs'))
 

	
 
create_status_lines(root)
bin/keyboardcomposer
Show inline comments
 
@@ -105,13 +105,20 @@ class KeyboardComposer(Frame, SubClient)
 
            bg='black', fg='white')
 
        self.save_stage_button.pack(side=LEFT)
 
        self.sub_name = Entry(self.buttonframe, bg='black', fg='white')
 
        self.sub_name.pack(side=LEFT)
 
        self.stop_frequent_update_time = 0
 

	
 
        self.sliders = Sliders(self.hw_slider_moved)
 
        try:
 
            self.sliders = Sliders(self.hw_slider_moved)
 
        except IOError:
 
            class _:
 
                def valueOut(self, name, value):
 
                    pass
 
            self.sliders = _()
 
            print "no hw sliders found"
 

	
 
    def make_key_hints(self):
 
        keyhintrow = Frame(self)
 

	
 
        col = 0
 
        for upkey, downkey in zip(nudge_keys['up'],
bin/subcomposer
Show inline comments
 
@@ -17,25 +17,24 @@ class Subcomposer(tk.Frame):
 
    def __init__(self, master, levelboxopts=None, dmxdummy=0, numchannels=68,
 
        use_persistentlevels=0):
 
        tk.Frame.__init__(self, master, bg='black')
 
        self.dmxdummy = dmxdummy
 
        self.numchannels = numchannels
 

	
 
        self.levels = [0]*512 # levels should never get overwritten, just edited
 
        self.levels = [0]*numchannels # levels should never get overwritten, just edited
 

	
 
        self.levelbox = Levelbox(self, num_channels=numchannels)
 
        self.levelbox.pack(side='top')
 
        # the dmx levels we edit and output, range is 0..1 (dmx chan 1 is
 
        # the 0 element)
 
        self.levelbox.setlevels(self.levels)
 

	
 
        self.savebox = EntryCommand(self, cmd=self.savenewsub)
 
        self.savebox.pack(side='top')
 

	
 
        self.loadbox = EntryCommand(self, verb="Load",
 
                               cmd=lambda x: self.loadsub(self.levels, x))
 
        self.loadbox = EntryCommand(self, verb="Load", cmd=self.loadsub)
 
        self.loadbox.pack(side='top')
 

	
 
        def alltozero():
 
            self.set_levels([0] * self.numchannels)
 
            dispatcher.send("levelchanged")
 

	
 
@@ -73,24 +72,23 @@ class Subcomposer(tk.Frame):
 
    def levelchanged(self, channel=None, newlevel=None):
 
        if channel is not None and newlevel is not None:
 
            if channel>len(self.levels):
 
                return
 
            self.levels[channel-1]=max(0,min(1,float(newlevel)))
 
        self.levelbox.setlevels(self.levels)
 
    def savenewsub(self, levels, subname):
 
    def savenewsub(self, subname):
 
        leveldict={}
 
        for i,lev in zip(range(len(self.levels)),self.levels):
 
            if lev!=0:
 
                leveldict[Patch.get_channel_name(i+1)]=lev
 

	
 
        s=Submaster.Submaster(subname,leveldict)
 
        s=Submaster.Submaster(subname,leveldict=leveldict)
 
        s.save()
 
    def loadsub(self, subname):
 
        """puts a sub into the levels, replacing old level values"""
 
        s=Submaster.Submasters().get_sub_by_name(subname)
 
        self.levels[:]=[0]*68
 
        self.levels[:]=s.get_dmx_list()
 
        dispatcher.send("levelchanged")
 
    def sendupdate(self):
 
        if not self.dmxdummy:
 
            dmxclient.outputlevels(self.levels)
 
            self.lastupdate = time.time()
 
@@ -116,13 +114,13 @@ class EntryCommand(tk.Frame):
 
        self.entry.bind("<Return>", self.action)
 
        tk.Button(self, text=verb, command=self.action).pack(side='left')
 

	
 
    def action(self, *args):
 
        subname = self.entry.get()
 
        self.cmd(subname)
 
        print "sub", verb, subname
 
        print "sub", self.cmd, subname
 

	
 
    def set(self, text):
 
        self.entry.delete(0, 'end')
 
        self.entry.insert(0, text)
 

	
 

	
light9/Submaster.py
Show inline comments
 
@@ -12,27 +12,52 @@ except ImportError:
 

	
 
class Submaster:
 
    "Contain a dictionary of levels, but you didn't need to know that"
 
    def __init__(self,
 
                 name=None,
 
                 graph=None, sub=None,
 
                 leveldict=None, temporary=0):
 
                 leveldict=None, temporary=False):
 
        """sub is the URI for this submaster, graph is a graph where
 
        we can learn about the sub. If graph is not provided, we look
 
        in a file named name.
 

	
 
        name is the filename where we can load a graph about this URI
 
        (see showconfig.subFile)
 

	
 
        passing name alone makes a new empty sub
 

	
 
        temporary means the sub won't get saved or loaded
 

	
 

	
 
        pass:
 
          name, temporary=True  -  no rdf involved
 
          sub, filename         -  read sub URI from graph at filename
 
          
 
          name - new sub
 
          sub - n
 
          name, sub - new 
 
        
 
        """
 
        if name is sub is leveldict is None:
 
            raise TypeError("more args are needed")
 
        if sub is not None:
 
            name = graph.label(sub)
 
        if graph is not None:
 
            # old code was passing leveldict as second positional arg
 
            assert isinstance(graph, Graph)
 
        self.name = name
 
        self.temporary = temporary
 
        if leveldict:
 
            self.levels = leveldict
 
        else:
 
            self.levels = {}
 
            self.reload(quiet=True)
 
        if not self.temporary:
 
            dispatcher.connect(self.reload, 'reload all subs')
 
            
 
    def reload(self, quiet=False):
 
        print "no submaster reload"
 
        return
 
        if self.temporary:
 
            return
 
        try:
 
            oldlevels = self.levels.copy()
 
            self.levels.clear()
 
            patchGraph = showconfig.getGraph()
 
@@ -55,21 +80,26 @@ class Submaster:
 
            return
 

	
 
        graph = Graph()
 
        subUri = L9['sub/%s' % self.name]
 
        graph.add((subUri, RDFS.label, Literal(self.name)))
 
        for chan in self.levels.keys():
 
            try:
 
                chanUri = Patch.get_channel_uri(chan)
 
            except KeyError:
 
                print "saving dmx channels with no :Channel node is not supported yet. Give channel %s a URI for it to be saved. Omitting this channel from the sub." % chan
 
                continue
 
            lev = BNode()
 
            graph.add((subUri, L9['lightLevel'], lev))
 
            graph.add((lev, L9['channel'], L9['dmx/%s' % chan]))
 
            graph.add((lev, L9['channel'], chanUri))
 
            graph.add((lev, L9['level'],
 
                       Literal(self.levels[chan], datatype=XSD['decimal'])))
 

	
 
        graph.serialize(showconfig.subFile(self.name), format="nt")
 

	
 
    def set_level(self, channelname, level, save=1):
 
    def set_level(self, channelname, level, save=True):
 
        self.levels[Patch.resolve_name(channelname)] = level
 
        if save:
 
            self.save()
 
    def set_all_levels(self, leveldict):
 
        self.levels.clear()
 
        for k, v in leveldict.items():
 
@@ -78,33 +108,36 @@ class Submaster:
 
    def get_levels(self):
 
        return self.levels
 
    def no_nonzero(self):
 
        return (not self.levels.values()) or not (max(self.levels.values()) > 0)
 
    def __mul__(self, scalar):
 
        return Submaster("%s*%s" % (self.name, scalar), 
 
            dict_scale(self.levels, scalar), temporary=1)
 
                         leveldict=dict_scale(self.levels, scalar),
 
                         temporary=True)
 
    __rmul__ = __mul__
 
    def max(self, *othersubs):
 
        return sub_maxes(self, *othersubs)
 
    def __repr__(self):
 
        items = self.levels.items()
 
        items.sort()
 
        levels = ' '.join(["%s:%.2f" % item for item in items])
 
        return "<'%s': [%s]>" % (self.name, levels)
 
    def get_dmx_list(self):
 
        leveldict = self.get_levels() # gets levels of sub contents
 

	
 
        levels = [0] * 68
 
        levels = []
 
        for k, v in leveldict.items():
 
            if v == 0:
 
                continue
 
            try:
 
                dmxchan = Patch.get_dmx_channel(k) - 1
 
            except ValueError:
 
                print "error trying to compute dmx levels for submaster %s" % self.name
 
                raise
 
            if dmxchan >= len(levels):
 
                levels.extend([0] * (dmxchan - len(levels) + 1))
 
            levels[dmxchan] = max(v, levels[dmxchan])
 

	
 
        return levels
 
    def normalize_patch_names(self):
 
        """Use only the primary patch names."""
 
        # possibly busted -- don't use unless you know what you're doing
 
@@ -132,14 +165,16 @@ class Submaster:
 
                                 linear_fade(self.levels.get(k, 0),
 
                                             otherlevels.get(k, 0),
 
                                             amount))
 

	
 
        return xfaded_sub
 
    def __cmp__(self, other):
 
        raise NotImplementedError
 
        return cmp(repr(self), repr(other))
 
    def __hash__(self):
 
        raise NotImplementedError
 
        return hash(repr(self))
 
                                            
 
def linear_fade(start, end, amount):
 
    """Fades between two floats by an amount.  amount is a float between
 
    0 and 1.  If amount is 0, it will return the start value.  If it is 1,
 
    the end value will be returned."""
 
@@ -147,13 +182,13 @@ def linear_fade(start, end, amount):
 
    return level
 

	
 
def sub_maxes(*subs):
 
    nonzero_subs = [s for s in subs if not s.no_nonzero()]
 
    name = "max(%s)" % ", ".join([repr(s) for s in nonzero_subs])
 
    return Submaster(name,
 
                     dict_max(*[sub.levels for sub in nonzero_subs]),
 
                     leveldict=dict_max(*[sub.levels for sub in nonzero_subs]),
 
                     temporary=1)
 

	
 
def combine_subdict(subdict, name=None, permanent=False):
 
    """A subdict is { Submaster objects : levels }.  We combine all
 
    submasters first by multiplying the submasters by their corresponding
 
    levels and then max()ing them together.  Returns a new Submaster
 
@@ -179,12 +214,13 @@ class Submasters:
 
        for filename in files:
 
            # we don't want these files
 
            if filename.startswith('.') or filename.endswith('~') or \
 
               filename.startswith('CVS'):
 
                continue
 
            self.submasters[filename] = Submaster(filename)
 
        print "loaded subs", self.submasters
 
    def get_all_subs(self):
 
        "All Submaster objects"
 
        l = self.submasters.items()
 
        l.sort()
 
        l = [x[1] for x in l]
 
        songs = []
light9/curve.py
Show inline comments
 
@@ -127,12 +127,13 @@ class Sketch:
 

	
 

	
 
class Curveview(tk.Canvas):
 
    def __init__(self,master,curve,**kw):
 
        self.curve=curve
 
        self._time = 0
 
        self.last_mouse_world = None
 
        tk.Canvas.__init__(self,master,width=10,height=10,
 
                           relief='sunken',bd=1,
 
                           closeenough=5,takefocus=1, **kw)
 
        self.selected_points=[] # idx of points being dragged
 
        self.update_curve()
 
        # self.bind("<Enter>",self.focus)
light9/dmxchanedit.py
Show inline comments
 
@@ -27,13 +27,13 @@ def gradient(lev, low=(80,80,180), high=
 
     return col
 

	
 
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)
 
        tk.Frame.__init__(self,parent, height=20)
 

	
 
        self.channelnum=channelnum
 
        self.currentlevel=0 # the level we're displaying, 0..1
 
        
 
        # 3 widgets, left-to-right:
 

	
 
@@ -53,16 +53,22 @@ class Onelevel(tk.Frame):
 
                               padx=0, pady=0, bd=0, 
 
                 height=1, bg='black', fg='white')
 
        self.desc_lab.pack(side='left')
 

	
 
        # current level of channel, shows intensity with color
 
        self.level_lab = tk.Label(self, width=3, bg='lightBlue',
 
                                  font=stdfont,
 
                                  anchor='e', 
 
                                  padx=1, pady=0, bd=0, height=1)
 
        self.level_lab.pack(side='left')
 
        # setting the font in the label somehow makes tk run a low
 
        # slower. Magically, startup is much faster if tk can layout
 
        # the window with some standard font in the rows (so the row
 
        # heights are all fixed and taller?), and then I replace the
 
        # last font. Tk resizes the window faster than you can see,
 
        # but startup is still fast. Very weird.
 
        self.after(1, lambda: self.level_lab.config(font=stdfont))
 

	
 
        self.setlevel(0)
 
        self.setupmousebindings()
 
        
 
    def setupmousebindings(self):
 
        def b1down(ev):
 
@@ -122,20 +128,19 @@ class Onelevel(tk.Frame):
 
        dispatcher.send("levelchanged",channel=self.channelnum,newlevel=newlev)
 
    
 
class Levelbox(tk.Frame):
 
    def __init__(self, parent, num_channels=68):
 
        tk.Frame.__init__(self,parent)
 
        global stdfont
 
        stdfont = tkFont.Font(size=9)
 
        stdfont = tkFont.Font(size=8)
 
        self.levels = [] # Onelevel objects
 

	
 
        rows = 48
 
        frames = [make_frame(self) for x in range((num_channels // rows) + 1)]
 

	
 
        for channel in range(1, num_channels+1):
 
            print "setup chan", channel
 
            # frame for this channel
 
            f = Onelevel(frames[channel // rows],channel)
 

	
 
            self.levels.append(f)
 
            f.pack(side='top')
 
        #dispatcher.connect(setalevel,"setlevel")
readme
Show inline comments
 
new file 100644
 
on dash:
 

	
 
dash(pts/35):/my/dl/modified/mpd% src/mpd --no-daemon --verbose
 

	
 

	
test/run_local.py
Show inline comments
 
new file 100644
 
import shutil
 
import sys,os
 
sys.path.insert(0,os.path.join(os.path.dirname(__file__),".."))
 

	
 
os.environ['LIGHT9_SHOW'] = "_test_show"
 
try:
 
    shutil.rmtree("_test_show")
 
except OSError:
 
    pass
 
os.mkdir("_test_show")
 
f = open("_test_show/config.n3", "w")
 
f.write("""
 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 
@prefix : <http://light9.bigasterisk.com/> .
 
@prefix ch: <http://light9.bigasterisk.com/theater/skyline/channel/> .
 
@prefix dmx: <http://light9.bigasterisk.com/dmx/> .
 

	
 
ch:frontLeft a :Channel; rdfs:label "frontLeft"; :altName "b1"; :output dmx:c1 .
 
ch:frontRight a :Channel; rdfs:label "frontRight"; :output dmx:c2 . 
 

	
 
dmx:c1 :dmxAddress 1 .
 
dmx:c2 :dmxAddress 2 .
 

	
 
""")
 
f.close()
test/subload.py
Show inline comments
 
new file 100644
 
# run this with py.test
 
import run_local
 
import os, shutil
 
import py.test
 
from light9 import dmxclient, Patch, Submaster
 
from light9.namespaces import L9
 

	
 
def testCreateArgs():
 
    py.test.raises(TypeError, Submaster.Submaster)
 
    assert Submaster.Submaster("newname", leveldict={})
 
    assert Submaster.Submaster(sub=L9['sub/newname'])
 
    assert Submaster.Submaster(name="newname", sub=L9["sub/newname"])
 
    py.test.raises(ValueError, Submaster.Submaster(name="newname",
 
                                                   sub=L9["other/newname"]))
 

	
 
    # old code might try to pass leveldict positionally
 
    py.test.raises(Exception, Submaster.Submaster("newname", {}))
 

	
 
def testLevels():
 
    levels = {'1' : .5, '2' : 1}
 
    s = Submaster.Submaster("newname", leveldict=levels)
 
    assert s.get_levels() == levels
 

	
 
    s.set_level('3', .5, save=False)
 
    assert s.get_levels()['3'] == .5
 

	
 
    assert s.get_dmx_list()[:3] == [.5, 1, .5]
 
    
 
    
 
    #s = Submaster.Submasters().get_sub_by_name("t1")
 
    #assert s.get_dmx_list() == [0]
test/test_patch.py
Show inline comments
 
new file 100644
 
import run_local
 
from light9 import dmxclient, Patch, Submaster
 
from light9.namespaces import L9
 

	
 
def test():
 
    assert Patch.get_channel_name(1) == "frontLeft"
 
    assert Patch.get_channel_name("1") == "frontLeft"
 
    assert Patch.get_channel_name("frontLeft") == "frontLeft"
 
    
 
    assert Patch.get_dmx_channel(1) == 1
 
    assert Patch.get_dmx_channel("1") == 1
 
    assert Patch.get_dmx_channel("frontLeft") == 1
 
    
 
    assert Patch.get_channel_name("b1") == "frontLeft"
 
    assert Patch.get_dmx_channel("b1") == 1
 
    assert Patch.resolve_name("b1") == "frontLeft"
 
    assert Patch.resolve_name("frontLeft") == "frontLeft"
 

	
 
    assert Patch.get_channel_uri("frontLeft") == L9['theater/skyline/channel/frontLeft']
 
    
0 comments (0 inline, 0 general)