Changeset - 0969d8a6729d
[Not reviewed]
default
0 4 0
dmcc - 22 years ago 2002-07-12 10:05:57

support for external sliders. fill in ExternalInput with real IO
4 files changed with 174 insertions and 42 deletions:
0 comments (0 inline, 0 general)
light8/ExternalInput.py
Show inline comments
 
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)
 
    server.serve_forever()
 

	
 
class ExternalSliders:
 
    def __init__(self, level_storage=[]):
 
        self.level_storage = level_storage
 
        self.spawn_server()
 
    def test(self):
 
        'Store fake inputs to test operations'
 
        pass
 
    def spawn_server(self):
 
        pass
 
        # thread.start_new_thread(start_server, (self.update))
 
    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
light8/Lightboard.py
Show inline comments
 
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):
 
        self.scalelevels = dict([(name, lev.get()) 
 
            for name, lev in scalelevels.items()])
 
        self.substate = dict([(name, subobj.get_state())
 
            for name, subobj in subs])
 
        self.windowpos = windowpos
 

	
 
class Lightboard:
 
    def __init__(self, master, parportdmx, DUMMY):
 
        self.master = master
 
        self.parportdmx = parportdmx
 
        self.DUMMY = DUMMY
 
        self.jostle_mode = 0
 

	
 
        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)
 

	
 
        self.windowpos = 0
 
        self.get_data()
 
        self.buildinterface()
 
        self.load()
 
        self.backgroundloop()
 
        self.updatestagelevels()
 
        
 
    def buildinterface(self):
 
        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)
 
        for i in range(0,len(self.channel_levels)):
 
            self.channel_levels[i].config(text=self.oldlevels[i])
 
            colorlabel(self.channel_levels[i])
 

	
 
        Console(self)
 

	
 
        # root frame
 
        controlpanel = Controlpanel(self.master, self.xfader, self.refresh, 
 
            self.quit, self.toggle_jostle)
 
        
 
        xf=Frame(self.master)
 
        xf.pack(side='right')
 

	
 
        self.master.bind('<q>', self.quit)
 
        self.master.bind('<r>', self.refresh)
 
        leveldisplay_tl.bind('<q>', self.quit)
 
        leveldisplay_tl.bind('<r>', self.refresh)
 

	
 
        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()
 

	
 
    def get_data(self,*args):
 
        Subs.reload_data(self.DUMMY)
 
        Patch.reload_data(self.DUMMY)
 
        print "Patch:", Patch.patch
 
        print "Subs:", ', '.join(Subs.subs.keys())
 

	
 
    def refresh(self, *args):
 
        'rebuild interface, reload data'
 
        self.get_data()
 
@@ -140,24 +143,29 @@ class Lightboard:
 

	
 
    # this is called on a loop, and ALSO by the Scales
 
    def changelevel(self, *args):
 
        'Amp trims slider'
 

	
 
        levels = [0] * 68
 
        for name, s in Subs.subs.items():
 
            newlevels = s.get_levels(level=self.scalelevels[name].get())
 
            for (ch, fadelev) in newlevels.items():
 
                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, 
 
                                         self.leveldisplay.number_labels):
 
            if lev != oldlev:
 
                lab.config(text="%d" % lev) # update labels in lev display
 
                colorlabel(lab)             # recolor labels
 
                if lev < oldlev:
 
                    numlab['bg'] = 'blue'
 
                else:
 
                    numlab['bg'] = 'red'
 
            else:
 
@@ -193,24 +201,25 @@ class Lightboard:
 
                    print "Couldn't set %s -> %s: %s" % (s, v,e)
 
            for name, substate in p.substate.items():
 
                try:
 
                    Subs.subs[name].set_state(substate)
 
                except Exception, e:
 
                    print "Couldn't set sub %s state: %s" % (name,e)
 
        except IOError, e:
 
            print "IOError: Couldn't load prefs (%s): %s" % (filename,e)
 
        except EOFError, e:
 
            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, ())
 
        self.changelevel()
 
    def quit(self, *args):
 
        self.save()
 
        self.master.destroy()
 
        sys.exit()
 
    def save(self, *args):
 
        filename = '/tmp/light9.prefs'
 
        if self.DUMMY:
 
            filename += '.dummy'
light8/panels.py
Show inline comments
 
"""some of the panels"""
 
from __future__ import nested_scopes
 

	
 
from Tix import *
 
from uihelpers import *
 
import Patch
 
from FlyingFader import FlyingFader
 
import Pmw
 

	
 
stdfont = ('Arial', 8)
 
monofont = ('Courier', 8)
 

	
 
class Controlpanel(Frame):
 
    def __init__(self, parent, xfader, refresh_cb, quit_cb, jostle_cb):
 
        Frame.__init__(self,parent)
 
        controlpanel = self
 
        for txt,cmd in (
 
            ('Quit',       quit_cb),
 
            ('Refresh',    refresh_cb),
 
            ('Clear all', xfader.clearallbuttons),
 
            ('On -> X',     lambda: xfader.grab('x')),
 
            ('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')
 
        self.entry.bind('<Return>',
 
                        lambda evt: self.execute(evt, self.entry.get()))
 
        self.frame.pack(fill=BOTH, expand=1)
 
        self.lightboard=lightboard
 
    
 
    def execute(self, evt, str):
 
        if str[0] == '*': # make a new sub from the current levels
 
            self.lightboard.save_sub(str,self.lightboard.stageassub())
 
        else:
 
@@ -71,24 +70,160 @@ class Leveldisplay:
 
            # current level of channel, shows intensity with color
 
            l = Label(f, width=3, bg='lightBlue', font=stdfont, anchor='e', 
 
                      padx=1, pady=0, bd=0, height=1)
 
            l.pack(side='left')
 
            colorlabel(l)
 
            channel_levels.append(l)
 
            f.pack(side='top')
 

	
 
        self.channel_levels = channel_levels
 
        # 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,
 
                 changelevel, subediting, longestname):
 
        
 
        sublist = Subs.subs.items()
 
        sublist.sort()
 

	
 
        for p in scenesparent,effectsparent,scenes:
 
            sw = ScrolledWindow(p)
 
            for but,units in ( (4,-4),(5,4) ):
 
                sw.window.bind("<ButtonPress-%s>"%but,lambda ev,s=sw.vsb,u=units: s.tk.call('tkScrollByUnits',s,'hv',u))
 
@@ -186,12 +321,20 @@ class Subpanels:
 
            
 
    def axisbuttons(self,f,s,xfader,stdfont,side1,name):
 
        for axis in ('y','x'):
 
            cvar=IntVar()
 
            eb_color = ('red', 'green')[axis == 'y']
 
            cb=Togglebutton(f,text=axis.upper(),variable=cvar,font=stdfont, 
 
                            padx=3, pady=0, bd=1, downcolor=eb_color)
 
            cb.pack(side=side1,fill='both', padx=0, pady=0)
 
            s.bind('<Key-%s>'%axis, lambda ev,cb=cb: cb.invoke)
 
            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()
light8/uihelpers.py
Show inline comments
 
@@ -17,39 +17,30 @@ windowlocations = {
 
}
 

	
 
def make_frame(parent):
 
    f = Frame(parent, bd=0)
 
    f.pack(side='left')
 
    return f
 

	
 
def bindkeys(root,key, func):
 
    root.bind(key, func)
 
    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):
 
    if s.get() == 0:
 
        s.set(100)
 
    else:
 
        s.set(0)
 

	
 
# for lambda callbacks    
 
def printout(t):
 
    print t
 

	
0 comments (0 inline, 0 general)