changeset 71:177e9ba0b4a7

simple DMX server
author dmcc
date Thu, 11 Jul 2002 09:33:02 +0000
parents 45664ac19f65
children 609cb9ae53b1
files light8/Lightboard.py light8/Subs.py light8/io.py
diffstat 3 files changed, 132 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/light8/Lightboard.py	Thu Jul 11 08:36:45 2002 +0000
+++ b/light8/Lightboard.py	Thu Jul 11 09:33:02 2002 +0000
@@ -4,7 +4,6 @@
 from time import sleep
 from signal import signal, SIGINT
 import sys, cPickle
-# import shelve
 
 import io
 from uihelpers import *
@@ -35,8 +34,6 @@
         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()
@@ -150,11 +147,15 @@
                 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:
@@ -164,9 +165,12 @@
             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)
--- a/light8/Subs.py	Thu Jul 11 08:36:45 2002 +0000
+++ b/light8/Subs.py	Thu Jul 11 09:33:02 2002 +0000
@@ -170,11 +170,19 @@
         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
@@ -191,7 +199,8 @@
     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
@@ -199,10 +208,12 @@
         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)) 
-            for ch, lev in d.items()])
+            return dict([(self.resolve_name(ch), float(lev) * float(level)) 
+                for ch, lev in d.items()])
 
     #
     # methods for Subediting to use
--- a/light8/io.py	Thu Jul 11 08:36:45 2002 +0000
+++ b/light8/io.py	Thu Jul 11 09:33:02 2002 +0000
@@ -1,15 +1,113 @@
 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()