changeset 351:a6662d61ebcd

SC, KC, CC now run and seem to load and save ok. CC does not have any rdf for its data files
author Drew Perttula <drewp@bigasterisk.com>
date Sun, 10 Jun 2007 08:09:08 +0000
parents c7478a778992
children 9d1f323fb3d3
files bin/curvecalc bin/keyboardcomposer bin/subcomposer light9/Submaster.py light9/curve.py light9/dmxchanedit.py readme test/run_local.py test/subload.py test/test_patch.py
diffstat 10 files changed, 162 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/bin/curvecalc	Sun Jun 10 07:41:48 2007 +0000
+++ b/bin/curvecalc	Sun Jun 10 08:09:08 2007 +0000
@@ -1,6 +1,11 @@
 #!/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
 
 """
@@ -289,12 +294,12 @@
 
     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():
@@ -314,6 +319,9 @@
         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")
@@ -348,10 +356,10 @@
 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)
 
@@ -360,8 +368,8 @@
 
 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)
--- a/bin/keyboardcomposer	Sun Jun 10 07:41:48 2007 +0000
+++ b/bin/keyboardcomposer	Sun Jun 10 08:09:08 2007 +0000
@@ -108,7 +108,14 @@
         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)
--- a/bin/subcomposer	Sun Jun 10 07:41:48 2007 +0000
+++ b/bin/subcomposer	Sun Jun 10 08:09:08 2007 +0000
@@ -20,7 +20,7 @@
         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')
@@ -31,8 +31,7 @@
         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():
@@ -76,18 +75,17 @@
                 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):
@@ -119,7 +117,7 @@
     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')
--- a/light9/Submaster.py	Sun Jun 10 07:41:48 2007 +0000
+++ b/light9/Submaster.py	Sun Jun 10 08:09:08 2007 +0000
@@ -15,9 +15,35 @@
     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:
@@ -27,9 +53,8 @@
             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:
@@ -58,15 +83,20 @@
         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()
@@ -81,7 +111,8 @@
         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)
@@ -93,7 +124,7 @@
     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
@@ -102,6 +133,8 @@
             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
@@ -135,8 +168,10 @@
 
         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):
@@ -150,7 +185,7 @@
     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):
@@ -182,6 +217,7 @@
                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()
--- a/light9/curve.py	Sun Jun 10 07:41:48 2007 +0000
+++ b/light9/curve.py	Sun Jun 10 08:09:08 2007 +0000
@@ -130,6 +130,7 @@
     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)
--- a/light9/dmxchanedit.py	Sun Jun 10 07:41:48 2007 +0000
+++ b/light9/dmxchanedit.py	Sun Jun 10 08:09:08 2007 +0000
@@ -30,7 +30,7 @@
     """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
@@ -56,10 +56,16 @@
 
         # 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()
@@ -125,14 +131,13 @@
     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)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme	Sun Jun 10 08:09:08 2007 +0000
@@ -0,0 +1,5 @@
+on dash:
+
+dash(pts/35):/my/dl/modified/mpd% src/mpd --no-daemon --verbose
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/run_local.py	Sun Jun 10 08:09:08 2007 +0000
@@ -0,0 +1,25 @@
+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()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/subload.py	Sun Jun 10 08:09:08 2007 +0000
@@ -0,0 +1,31 @@
+# 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]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_patch.py	Sun Jun 10 08:09:08 2007 +0000
@@ -0,0 +1,20 @@
+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']
+