Changeset - 177e9ba0b4a7
[Not reviewed]
default
0 3 0
dmcc - 22 years ago 2002-07-11 09:33:02

simple DMX server
3 files changed with 131 insertions and 18 deletions:
0 comments (0 inline, 0 general)
light8/Lightboard.py
Show inline comments
 
from __future__ import nested_scopes
 

	
 
from Tix import *
 
from time import sleep
 
from signal import signal, SIGINT
 
import sys, cPickle
 
# import shelve
 

	
 
import io
 
from uihelpers import *
 
from panels import *
 
from Xfader import *
 
from subediting import Subediting
 
from Fader import Fader
 
import stage
 
import Subs, Patch
 

	
 
class Pickles:
 
    def __init__(self, scalelevels, subs=None, windowpos=None):
 
@@ -26,26 +25,24 @@ class Pickles:
 
class Lightboard:
 
    def __init__(self, master, parportdmx, DUMMY):
 
        self.master = master
 
        self.parportdmx = parportdmx
 
        self.DUMMY = DUMMY
 

	
 
        self.channel_levels = []
 
        self.scalelevels = {}
 
        self.xfader = Xfader(self.scalelevels) # doesn't draw any UI yet-- look for self.xfader.setupwidget()
 
        self.oldlevels = [None] * 68 # never replace this; just clear it
 
        self.subediting = Subediting(currentoutputlevels=self.oldlevels)
 

	
 
        # self.shelf = shelve.open('/tmp/light9.newprefs')
 
        # self.windowpos = self.shelf.get('window', {})
 
        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)
 
@@ -141,41 +138,48 @@ 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]
 
        lenlevels = len(levels)
 
        changed = [] # list of changed levels
 

	
 
        for lev,lab,oldlev,numlab in zip(levels, self.channel_levels, 
 
        for lev,lab,oldlev,numlab,idx in zip(levels, self.channel_levels, 
 
                                         self.oldlevels, 
 
                                         self.leveldisplay.number_labels):
 
                                         self.leveldisplay.number_labels,
 
                                         xrange(1, lenlevels + 2)):
 
            if lev != oldlev:
 
                changed.extend((idx, lev))
 
                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:
 
                numlab['bg'] = 'lightPink'
 

	
 
        self.oldlevels[:] = levels[:] # replace the elements in oldlevels - don't make a new list (Subediting is watching it)
 
        # replace the elements in oldlevels - don't make a new list 
 
        # (Subediting is watching it)
 
        self.oldlevels[:] = levels[:] 
 
            
 
        self.parportdmx.sendlevels(levels)
 
        # self.parportdmx.sendlevels(levels)
 
        self.parportdmx.sendupdates(changed)
 

	
 
    def updatestagelevels(self):
 
        self.master.after(100, self.updatestagelevels)
 
        for lev, idx in zip(self.oldlevels, xrange(0, 68 + 1)):
 
            self.stage.updatelightlevel(Patch.get_channel_name(idx + 1), lev)
 

	
 
    def load(self):
 
        try:
 
            filename = '/tmp/light9.prefs'
 
            if self.DUMMY:
 
                filename += '.dummy'
 
            print "Loading from", filename
light8/Subs.py
Show inline comments
 
@@ -161,56 +161,67 @@ class SliderAdjuster:
 
        except KeyError:
 
            pass
 
        return state
 
    # no setstate needed
 

	
 
class Sub:
 
    def __init__(self, name, levels, dimmers=68, color=None):
 
        self.name = name # keep this consistent please
 
        self.levels = levels
 
        self.dimmers = dimmers # needed?
 
        self.is_effect = callable(self.levels)
 
        self.slideradjuster = SliderAdjuster()
 
        self.namecache = {}
 
        if self.is_effect:
 
            self.params = Params()
 
            self.generator = self.levels(self.params, self.slideradjuster)
 
            self.generator.next()
 
        self.color = color
 
    def resolve_name(self, ch_name):
 
        if ch_name in self.namecache:
 
            return self.namecache[ch_name]
 
        else:
 
            resolved = get_dmx_channel(ch_name)
 
            self.namecache[ch_name] = resolved
 
            return resolved
 
    def set_slider_var(self, slidervar):
 
        if self.is_effect:
 
            self.slideradjuster.var = slidervar
 
    def draw_tk(self, frame):
 
        if self.is_effect:
 
            self.params.draw_tk(frame)
 
    def get_state(self):
 
        state = self.__dict__.copy()
 
        if self.is_effect:
 
            del state['levels']
 
            del state['generator']
 

	
 
        return state
 
    def set_state(self, statedict):
 
        self.__dict__.update(statedict)
 
    def get_levels(self, level):
 
        """returns a scaled version of the levels in the sub; channel names are resolved to numbers"""
 
        """returns a scaled version of the levels in the sub; channel names 
 
        are resolved to numbers"""
 
        d = {}
 
        if level == 0: 
 
            self.slideradjuster.atzero = 1
 
            return d
 
        if self.is_effect: # effect
 
            d = self.generator.next()
 
            self.slideradjuster.atzero = 0
 
            return dict([(get_dmx_channel(ch), float(lev) * float(level)) 
 
                for ch, lev in d.items()])
 
        else: # dictionary (standard)
 
            d = self.levels
 
        return dict([(get_dmx_channel(ch), float(lev) * float(level)) 
 
            return dict([(self.resolve_name(ch), float(lev) * float(level)) 
 
            for ch, lev in d.items()])
 

	
 
    #
 
    # methods for Subediting to use
 
    #
 
    def getlevels(self):
 
        return self.levels.copy()
 
    def reviselevels(self,levels):
 
        # we can accept these new levels; subediting has done all the work
 
        self.levels.update(levels)
 
                
 
    
light8/io.py
Show inline comments
 
from parport import *
 
import socket, os
 

	
 
lastlevels = {}
 

	
 
def gethostlist(host):
 
    return lastlevels[host]
 

	
 
def parselist(levels):
 
    newlist = [0] * 68
 
    # levels has at least one pair
 
    ch, lev = None, None
 
    while len(levels) >= 2:
 
        ch, lev = levels.pop(0), levels.pop(0)
 

	
 
        # off by one errors -- i hate them sooo much
 
        newlist[int(ch) - 1] = int(lev)
 
    return newlist
 

	
 
def sethostlist(host, changes):
 
    if not changes: return
 
    global lastlevels
 
    if host not in lastlevels:
 
        lastlevels[host] = [0] * 68
 

	
 
class ParportDMX:
 
    def __init__(self, dummy=1, dimmers=68):
 
    lastlevels[host] = parselist(changes)
 
    '''
 
    # changes has at least one pair
 
    ch, lev = None, None
 
    while len(changes) >= 2:
 
        ch, lev = changes.pop(0), changes.pop(0)
 

	
 
        # off by one errors -- i hate them sooo much
 
        lastlevels[host][ch - 1] = lev 
 
    '''
 

	
 

	
 
def sendlevels(levels):
 
    print "sendlevels: i'm a level hobo:", levels
 
    levels = levels + [0]
 
    # if levels[14] > 0: levels[14] = 100 # non-dim
 
    print "sendlevels: wait for it... length =", len(levels)
 
    outstart()
 
    for p in range(1, 68 + 2):
 
        outbyte(levels[p-1]*255 / 100)
 
    print "sendlevels: done"
 

	
 
class ParportDMX: # ethdmx client or standalone server
 
    def __init__(self, dummy=1, dimmers=68, machine_name='localhost', 
 
                 standalone=0):
 
        self.dimmers = dimmers
 
        self.dummy = dummy
 
        if not dummy:
 
            getparport()
 
    def sendlevels(self, levels):
 
        if self.dummy: return
 
        levels = list(levels) + [0]
 
        # if levels[14] > 0: levels[14] = 100 # non-dim
 
        outstart()
 
        for p in range(1, self.dimmers + 2):
 
            outbyte(levels[p-1]*255 / 100)
 

	
 
        self.standalone = standalone
 
        self.machine_name = machine_name
 

	
 
    def sendupdates(self, levels):
 
        if (not self.dummy) and levels:
 
            print "update:", levels
 

	
 
            if self.standalone:
 
                print "standalone sendlevels", levels
 
                sendlevels(parselist(levels))
 
                return
 

	
 
            pid = os.getpid()
 
            s = ('%d ' % pid) + ' '.join([str(l) for l in levels]) + '\n'
 
            # print "sending", s
 
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
            self.sock.connect((self.machine_name, 
 
                socket.getservbyname('ethdmx', 'tcp')))
 
            self.sock.send(s)
 

	
 
            # response = self.sock.recv(100)
 
            # print "response", response
 
            # if response != 'ACK\n':
 
                # raise "Didn't get ACK from DMX server"
 

	
 
if __name__ == '__main__':
 
    import SocketServer
 
    getparport()
 
            
 
    class DMXHandler(SocketServer.StreamRequestHandler):
 
        def handle(self):
 
            global lastlevels
 
            changed = self.rfile.readline(1000)
 
            # self.wfile.write("ACK\n")
 
            pairs = changed.split()
 
            pid = pairs[0]
 
            changes = pairs[1:]
 

	
 
            # print 'pairs', pairs
 
            sethostlist(pid, changes)
 

	
 
            self.preplevels()
 
        def preplevels(self):
 
            global lastlevels
 
            hosts = lastlevels.keys()
 
            maxlevels = [0] * 68
 
            for h in hosts:
 
                maxlevels = [max(hostlev, maxlev) 
 
                    for hostlev, maxlev in zip(maxlevels, gethostlist(h))]
 
            print "dmxhandler sending levels:", maxlevels
 
            sendlevels(maxlevels)
 

	
 
    print "Running DMX over Ethernet socket server.  Everything is under " + \
 
          "control."
 

	
 
    server = SocketServer.TCPServer(('', 
 
        socket.getservbyname('ethdmx', 'tcp')), DMXHandler)
 
    server.serve_forever()
0 comments (0 inline, 0 general)