changeset 78:0969d8a6729d

support for external sliders. fill in ExternalInput with real IO
author dmcc
date Fri, 12 Jul 2002 10:05:57 +0000
parents 5649f5d9c798
children 233fe8cefa36
files light8/ExternalInput.py light8/Lightboard.py light8/panels.py light8/uihelpers.py
diffstat 4 files changed, 174 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/light8/ExternalInput.py	Fri Jul 12 10:02:31 2002 +0000
+++ b/light8/ExternalInput.py	Fri Jul 12 10:05:57 2002 +0000
@@ -1,20 +1,10 @@
-import thread, SocketServer, socket
-
-
-currentlevels = [0,0,0,0]
-
+import thread, SocketServer
 
 class NetSliderHandler(SocketServer.StreamRequestHandler):
     def handle(self):
         data = self.rfile.readline(1000)
-        currentlevels[:] = [round(self.bounds(float(x)/255),3) for x in list(data.split())]
-    def bounds(self,x):
-        # the last .1 both ways shall not do anything
-        x=x*1.1-.05
-        x=min(1,max(0,x))
-        return x
 
-def start_server(levelstorage=0):
+def start_server(levelstorage):
     server = SocketServer.TCPServer(
         ('', socket.getservbyname('rlslider', 'tcp')), 
         NetSliderHandler)
@@ -33,8 +23,7 @@
     def update(self, *args):
         self.level_storage[:] = args
     def get_levels(self):
-        return currentlevels
-#        import math, time
-#        return [max(0, math.sin(time.time() + i)) for i in range(4)] # bogus
+        import math, time
+        return [max(0, math.sin(time.time() + i)) for i in range(4)] # bogus
             
         # return self.level_storage
--- a/light8/Lightboard.py	Fri Jul 12 10:02:31 2002 +0000
+++ b/light8/Lightboard.py	Fri Jul 12 10:05:57 2002 +0000
@@ -1,18 +1,15 @@
 from __future__ import nested_scopes
 
 from Tix import *
-import random
 from signal import signal, SIGINT
-import sys, cPickle
+import sys, cPickle, random
 
-import io
 from uihelpers import *
 from panels import *
 from Xfader import *
 from subediting import Subediting
 from Fader import Fader
-import stage
-import Subs, Patch
+import io, stage, Subs, Patch, ExternalInput
 
 class Pickles:
     def __init__(self, scalelevels, subs=None, windowpos=None):
@@ -31,7 +28,8 @@
 
         self.channel_levels = []
         self.scalelevels = {}
-        self.xfader = Xfader(self.scalelevels) # doesn't draw any UI yet-- look for self.xfader.setupwidget()
+        # doesn't draw any UI yet-- look for self.xfader.setupwidget()
+        self.xfader = Xfader(self.scalelevels) 
         self.oldlevels = [None] * 68 # never replace this; just clear it
         self.subediting = Subediting(currentoutputlevels=self.oldlevels)
 
@@ -46,22 +44,27 @@
         for w in self.master.winfo_children():
             w.destroy()
 
-        stage_tl = toplevelat('stage', self.windowpos)
+        stage_tl = toplevelat('stage')
         s = stage.Stage(stage_tl)
         stage.createlights(s)
         s.setsubediting(self.subediting)
         s.pack()
         self.stage = s # save it
 
-        sub_tl = toplevelat('sub', self.windowpos)
-        scene_tl = toplevelat('scenes',self.windowpos)
-        effect_tl = toplevelat('effect', self.windowpos)
+        sub_tl = toplevelat('sub')
+        scene_tl = toplevelat('scenes')
+        effect_tl = toplevelat('effect')
+
+        mapping_tl = toplevelat('mapping')
+        self.slidermapper = ExtSliderMapper(mapping_tl, self.scalelevels, 
+                ExternalInput.ExternalSliders())
+        self.slidermapper.pack()
 
         self.subpanels = Subpanels(sub_tl, effect_tl, scene_tl, self, self.scalelevels,
                                    Subs, self.xfader, self.changelevel,
                                    self.subediting, Subs.longestsubname())
 
-        leveldisplay_tl = toplevelat('leveldisplay', self.windowpos)
+        leveldisplay_tl = toplevelat('leveldisplay')
         leveldisplay_tl.bind('<Escape>', sys.exit)
 
         self.leveldisplay = Leveldisplay(leveldisplay_tl, self.channel_levels)
@@ -86,7 +89,7 @@
         self.xfader.setupwidget(xf)
         controlpanel.pack()
 
-        cuefader_tl = toplevelat('cuefader', self.windowpos)
+        cuefader_tl = toplevelat('cuefader')
         cuefader = Fader(cuefader_tl, Subs.cues, self.scalelevels)
         cuefader.pack()
 
@@ -149,6 +152,11 @@
                 levels[ch-1] = max(levels[ch-1], fadelev)
 
         levels = [int(l) for l in levels]
+
+        # load levels from external sliders
+        extlevels = self.slidermapper.get_levels()
+        for name, val in extlevels.items():
+            self.scalelevels[name].set(val)
         
         for lev,lab,oldlev,numlab in zip(levels, self.channel_levels, 
                                          self.oldlevels, 
@@ -202,6 +210,7 @@
             print "EOFrror: Couldn't load prefs (%s): %s" % (filename,e)
         except Exception,e:
             print "Couldn't load prefs (%s): %s" % (filename,e)
+        self.slidermapper.setup()
 
     def backgroundloop(self, *args):
         self.master.after(50, self.backgroundloop, ())
--- a/light8/panels.py	Fri Jul 12 10:02:31 2002 +0000
+++ b/light8/panels.py	Fri Jul 12 10:05:57 2002 +0000
@@ -5,7 +5,6 @@
 from uihelpers import *
 import Patch
 from FlyingFader import FlyingFader
-import Pmw
 
 stdfont = ('Arial', 8)
 monofont = ('Courier', 8)
@@ -22,16 +21,16 @@
             ('Clear X',     lambda: xfader.clearallbuttons('x')),
             ('On -> Y',     lambda: xfader.grab('y')),
             ('Clear Y',     lambda: xfader.clearallbuttons('y'))):
-            # ('Jostle',     jostle_cb)):
             Button(controlpanel, text=txt, command=cmd).pack(side='top', 
                 fill='x')
+        # jostle button
         Checkbutton(controlpanel, text="Jostle", 
             command=jostle_cb).pack(side=TOP, fill=X)
 
 class Console:
     def __init__(self,lightboard):
         print "Light 8: Everything's under control"
-        t=toplevelat('console', lightboard.windowpos)
+        t=toplevelat('console')
         self.frame = Frame(t)
         self.entry=Entry(self.frame)
         self.entry.pack(expand=1, fill='x')
@@ -80,6 +79,142 @@
         # channel_levels is an output - changelevel will use it to access 
         # these labels
 
+class ExtSliderMapper(Frame):
+    def __init__(self, parent, sliderlevels, sliderinput, filename='slidermapping',
+                 numsliders=4):
+        'Slider levels is scalelevels, sliderinput is an ExternalInput object'
+        Frame.__init__(self, parent)
+        self.parent = parent
+        self.sliderlevels = sliderlevels
+        self.sliderinput = sliderinput
+        self.filename = filename
+        self.numsliders = numsliders
+        self.file = None
+
+        # self.setup()
+    def setup(self):
+        self.subnames = self.sliderlevels.keys()
+        self.subnames.sort()
+        self.presets = {}
+        self.load_presets()
+
+        self.current_mapping_name = StringVar()
+        self.current_mapping = []
+        self.attached = []
+        self.levels_read = []
+        for i in range(self.numsliders):
+            self.current_mapping.append(StringVar())
+            self.attached.append(BooleanVar())
+            self.levels_read.append(DoubleVar())
+
+        self.reallevellabels = []
+        self.draw_interface()
+    def load_presets(self):
+        self.file = open(self.filename, 'r')
+        lines = self.file.readlines()
+        for l in lines:
+            tokens = l[:-1].split('\t')
+            name = tokens.pop(0)
+            self.presets[name] = tokens
+        self.file.close()
+    def save_presets(self):
+        self.file = open(self.filename, 'w')
+        self.file.seek(0)
+        preset_names = self.presets.keys()
+        preset_names.sort()
+        for p in preset_names:
+            s = '\t'.join([p] + self.presets[p]) + '\n'
+            self.file.write(s)
+        self.file.close()
+    def load_scalelevels(self):
+        for m, rll in zip(self.current_mapping, self.reallevellabels):
+            try:
+                v = self.sliderlevels[m.get()]
+                rll.configure(textvariable=v)
+            except KeyError:
+                pass
+                
+    def get_levels(self):
+        'To be called by changelevels, I think'
+        if not self.current_mapping_name: return {}
+        if not self.sliderinput: return {}
+
+        self.load_scalelevels()
+
+        rawlevels = self.sliderinput.get_levels()
+        for rawlev, levlabvar in zip(rawlevels, self.levels_read):
+            levlabvar.set(rawlev)
+        outputlevels = {}
+        return dict([(name.get(), lev) 
+            for name, lev, att in zip(self.current_mapping, 
+                                      rawlevels, 
+                                      self.attached) 
+            if att.get()])
+
+    def draw_interface(self):
+        self.reallevellabels = []
+        subchoiceframe = Frame(self)
+        for i, mapping, isattached, lev in zip(range(self.numsliders), 
+                                               self.current_mapping, 
+                                               self.attached,
+                                               self.levels_read):
+            f = Frame(subchoiceframe)
+            # Label(f, text="Slider %d" % (i+1)).pack(side=LEFT)
+            c = ComboBox(f, variable=mapping)
+            for s in self.subnames:
+                c.slistbox.listbox.insert(END, s)
+            c.entry.configure(width=12)
+            statframe = Frame(f)
+            Checkbutton(statframe, variable=isattached, 
+                text="Attached").grid(columnspan=2, sticky=W)
+            Label(statframe, text="Input", fg='red').grid(row=1, sticky=W)
+            Label(statframe, textvariable=lev, fg='red', width=5).grid(row=1, column=1)
+            Label(statframe, text="Real").grid(row=2, sticky=W)
+            l = Label(statframe, text="N/A", width=5)
+            l.grid(row=2, column=1)
+            self.reallevellabels.append(l)
+            statframe.pack(side=BOTTOM, expand=1, fill=X)
+            c.pack()
+            f.pack(side=LEFT)
+        subchoiceframe.pack()
+        
+        presetframe = Frame(self)
+        Label(presetframe, text="Preset:").pack(side=LEFT)
+        self.presetcombo = ComboBox(presetframe, variable=self.current_mapping_name, 
+                                    editable=1, command=self.apply_preset)
+        self.draw_presets()
+        self.presetcombo.pack(side=LEFT)
+        Button(presetframe, text="Add", padx=0, pady=0, 
+                command=self.add_preset).pack(side=LEFT)
+        Button(presetframe, text="Delete", padx=0, pady=0, 
+                command=self.delete_preset).pack(side=LEFT)
+        presetframe.pack(side=BOTTOM)
+    def apply_preset(self, preset):
+        if not preset: return
+        mapping = self.presets.get(preset)
+        if not mapping: return
+        for name, var, att in zip(mapping, self.current_mapping, self.attached):
+            var.set(name)
+            att.set(0) # detach all sliders
+    def delete_preset(self, *args):
+        del self.presets[self.current_mapping_name.get()]
+        self.presetcombo.slistbox.listbox.delete(0, END)
+        self.draw_presets()
+        self.save_presets()
+    def add_preset(self, *args):
+        self.presets[self.current_mapping_name.get()] = [m.get() 
+                for m in self.current_mapping]
+        self.presetcombo.slistbox.listbox.delete(0, END)
+        self.draw_presets()
+        self.save_presets()
+    def draw_presets(self):
+        preset_names = self.presets.keys()
+        preset_names.sort()
+        for p in preset_names:
+            self.presetcombo.slistbox.listbox.insert(END, p)
+
+                
+
 class Subpanels:
     def __init__(self, scenesparent, effectsparent, scenes, lightboard,
                  scalelevels, Subs, xfader,
@@ -195,3 +330,11 @@
             xfader.registerbutton(name,axis,cvar)
 
                     
+if __name__ == '__main__':
+    print "testing external sliders"
+    root = Tk()
+    fakesliderlevels = dict([('sub%d' % n, DoubleVar()) for n in range(12)])
+    esm = ExtSliderMapper(root, fakesliderlevels, None)
+    esm.pack()
+    
+    mainloop()
--- a/light8/uihelpers.py	Fri Jul 12 10:02:31 2002 +0000
+++ b/light8/uihelpers.py	Fri Jul 12 10:05:57 2002 +0000
@@ -26,21 +26,12 @@
     for w in root.winfo_children():
         w.bind(key, func)
 
-# def toplevelat(x,y,w=None,h=None):
-def toplevelat(name, windowpos=None):
+def toplevelat(name):
     tl = Toplevel()
 
-    tl.wm_geometry(windowlocations[name])
+    if name in windowlocations:
+        tl.wm_geometry(windowlocations[name])
 
-    # if name in windowpos:
-        # tkname, geom = windowpos[name]
-        # tl.wm_geometry(geom)
-        # windowpos[name] = str(tl), geom
-
-    # if w and h:
-        # tl.wm_geometry("%dx%d+%d+%d" % (w,h,x,y))
-    # else:
-        # tl.wm_geometry("+%d+%d" % (x,y))
     return tl
 
 def toggle_slider(s):