annotate light8/dmxserver.py @ 54:3011c1028eb7

Cue math error fixed. Cue math error fixed. Bad cues in ConfigDummy fixed, not fixed in Config yet. Cue fader back in rsn. Oh yeah.
author dmcc
date Mon, 08 Jul 2002 15:50:00 +0000
parents 45b12307c695
children afbdae5e1359
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
45b12307c695 Initial revision
drewp
parents:
diff changeset
1 #!/usr/bin/python
45b12307c695 Initial revision
drewp
parents:
diff changeset
2 """
45b12307c695 Initial revision
drewp
parents:
diff changeset
3
45b12307c695 Initial revision
drewp
parents:
diff changeset
4 this is the only process to talk to the dmx hardware. other clients
45b12307c695 Initial revision
drewp
parents:
diff changeset
5 can connect to this server and present dmx output, and this server
45b12307c695 Initial revision
drewp
parents:
diff changeset
6 will max ('pile-on') all the client requests.
45b12307c695 Initial revision
drewp
parents:
diff changeset
7
45b12307c695 Initial revision
drewp
parents:
diff changeset
8 this server has a level display which is the final set of values that
45b12307c695 Initial revision
drewp
parents:
diff changeset
9 goes to the hardware.
45b12307c695 Initial revision
drewp
parents:
diff changeset
10
45b12307c695 Initial revision
drewp
parents:
diff changeset
11 clients shall connect to the xmlrpc server and send:
45b12307c695 Initial revision
drewp
parents:
diff changeset
12
45b12307c695 Initial revision
drewp
parents:
diff changeset
13 their PID (or some other cookie)
45b12307c695 Initial revision
drewp
parents:
diff changeset
14
45b12307c695 Initial revision
drewp
parents:
diff changeset
15 a length-n list of 0..1 levels which will represent the channel
45b12307c695 Initial revision
drewp
parents:
diff changeset
16 values for the n first dmx channels.
45b12307c695 Initial revision
drewp
parents:
diff changeset
17
45b12307c695 Initial revision
drewp
parents:
diff changeset
18 server is port 8030; xmlrpc method is called outputlevels(pid,levellist).
45b12307c695 Initial revision
drewp
parents:
diff changeset
19
45b12307c695 Initial revision
drewp
parents:
diff changeset
20 todo:
45b12307c695 Initial revision
drewp
parents:
diff changeset
21 save dmx on quit and restore on restart
45b12307c695 Initial revision
drewp
parents:
diff changeset
22 if parport fails, run in dummy mode (and make an option for that too)
45b12307c695 Initial revision
drewp
parents:
diff changeset
23 """
45b12307c695 Initial revision
drewp
parents:
diff changeset
24
45b12307c695 Initial revision
drewp
parents:
diff changeset
25 from __future__ import division
45b12307c695 Initial revision
drewp
parents:
diff changeset
26 from twisted.internet import reactor
45b12307c695 Initial revision
drewp
parents:
diff changeset
27 from twisted.web import xmlrpc, server
45b12307c695 Initial revision
drewp
parents:
diff changeset
28 import sys,time,os
45b12307c695 Initial revision
drewp
parents:
diff changeset
29 from optparse import OptionParser
45b12307c695 Initial revision
drewp
parents:
diff changeset
30 from io import ParportDMX
45b12307c695 Initial revision
drewp
parents:
diff changeset
31 from updatefreq import Updatefreq
45b12307c695 Initial revision
drewp
parents:
diff changeset
32
45b12307c695 Initial revision
drewp
parents:
diff changeset
33 class XMLRPCServe(xmlrpc.XMLRPC):
45b12307c695 Initial revision
drewp
parents:
diff changeset
34 def __init__(self,options):
45b12307c695 Initial revision
drewp
parents:
diff changeset
35
45b12307c695 Initial revision
drewp
parents:
diff changeset
36 xmlrpc.XMLRPC.__init__(self)
45b12307c695 Initial revision
drewp
parents:
diff changeset
37
45b12307c695 Initial revision
drewp
parents:
diff changeset
38 self.clientlevels={} # clientID : list of levels
45b12307c695 Initial revision
drewp
parents:
diff changeset
39 self.lastseen={} # clientID : time last seen
45b12307c695 Initial revision
drewp
parents:
diff changeset
40 self.clientfreq={} # clientID : updatefreq
45b12307c695 Initial revision
drewp
parents:
diff changeset
41
45b12307c695 Initial revision
drewp
parents:
diff changeset
42 self.combinedlevels=[] # list of levels, after max'ing the clients
45b12307c695 Initial revision
drewp
parents:
diff changeset
43 self.clientschanged=1 # have clients sent anything since the last send?
45b12307c695 Initial revision
drewp
parents:
diff changeset
44 self.options=options
45b12307c695 Initial revision
drewp
parents:
diff changeset
45 self.lastupdate=0 # time of last dmx send
45b12307c695 Initial revision
drewp
parents:
diff changeset
46 self.laststatsprint=0 # time
45b12307c695 Initial revision
drewp
parents:
diff changeset
47
45b12307c695 Initial revision
drewp
parents:
diff changeset
48 # desired seconds between sendlevels() calls
45b12307c695 Initial revision
drewp
parents:
diff changeset
49 self.calldelay=1/options.updates_per_sec
45b12307c695 Initial revision
drewp
parents:
diff changeset
50
45b12307c695 Initial revision
drewp
parents:
diff changeset
51 print "starting parport connection"
45b12307c695 Initial revision
drewp
parents:
diff changeset
52 self.parportdmx=ParportDMX()
45b12307c695 Initial revision
drewp
parents:
diff changeset
53 if os.environ.get('DMXDUMMY',0):
45b12307c695 Initial revision
drewp
parents:
diff changeset
54 self.parportdmx.godummy()
45b12307c695 Initial revision
drewp
parents:
diff changeset
55 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
56 self.parportdmx.golive()
45b12307c695 Initial revision
drewp
parents:
diff changeset
57
45b12307c695 Initial revision
drewp
parents:
diff changeset
58
45b12307c695 Initial revision
drewp
parents:
diff changeset
59 self.updatefreq=Updatefreq() # freq of actual dmx sends
45b12307c695 Initial revision
drewp
parents:
diff changeset
60 self.num_unshown_updates=None
45b12307c695 Initial revision
drewp
parents:
diff changeset
61 self.lastshownlevels=None
45b12307c695 Initial revision
drewp
parents:
diff changeset
62 # start the loop
45b12307c695 Initial revision
drewp
parents:
diff changeset
63 self.sendlevels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
64
45b12307c695 Initial revision
drewp
parents:
diff changeset
65 # the other loop
45b12307c695 Initial revision
drewp
parents:
diff changeset
66 self.purgeclients()
45b12307c695 Initial revision
drewp
parents:
diff changeset
67
45b12307c695 Initial revision
drewp
parents:
diff changeset
68 def purgeclients(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
69
45b12307c695 Initial revision
drewp
parents:
diff changeset
70 """forget about any clients who haven't sent levels in a while.
45b12307c695 Initial revision
drewp
parents:
diff changeset
71 this runs in a loop"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
72
45b12307c695 Initial revision
drewp
parents:
diff changeset
73 purge_age=10 # seconds
45b12307c695 Initial revision
drewp
parents:
diff changeset
74
45b12307c695 Initial revision
drewp
parents:
diff changeset
75 reactor.callLater(1,self.purgeclients)
45b12307c695 Initial revision
drewp
parents:
diff changeset
76
45b12307c695 Initial revision
drewp
parents:
diff changeset
77 now=time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
78 cids=self.clientlevels.keys()
45b12307c695 Initial revision
drewp
parents:
diff changeset
79 for cid in cids:
45b12307c695 Initial revision
drewp
parents:
diff changeset
80 lastseen=self.lastseen[cid]
45b12307c695 Initial revision
drewp
parents:
diff changeset
81 if lastseen<now-purge_age:
45b12307c695 Initial revision
drewp
parents:
diff changeset
82 print ("forgetting client %s (no activity for %s sec)" %
45b12307c695 Initial revision
drewp
parents:
diff changeset
83 (cid,purge_age))
45b12307c695 Initial revision
drewp
parents:
diff changeset
84 del self.clientlevels[cid]
45b12307c695 Initial revision
drewp
parents:
diff changeset
85 del self.clientfreq[cid]
45b12307c695 Initial revision
drewp
parents:
diff changeset
86 del self.lastseen[cid]
45b12307c695 Initial revision
drewp
parents:
diff changeset
87
45b12307c695 Initial revision
drewp
parents:
diff changeset
88 def sendlevels(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
89
45b12307c695 Initial revision
drewp
parents:
diff changeset
90 """sends to dmx if levels have changed, or if we havent sent
45b12307c695 Initial revision
drewp
parents:
diff changeset
91 in a while"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
92
45b12307c695 Initial revision
drewp
parents:
diff changeset
93 reactor.callLater(self.calldelay,self.sendlevels)
45b12307c695 Initial revision
drewp
parents:
diff changeset
94
45b12307c695 Initial revision
drewp
parents:
diff changeset
95 if self.clientschanged:
45b12307c695 Initial revision
drewp
parents:
diff changeset
96 # recalc levels
45b12307c695 Initial revision
drewp
parents:
diff changeset
97
45b12307c695 Initial revision
drewp
parents:
diff changeset
98 self.calclevels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
99
45b12307c695 Initial revision
drewp
parents:
diff changeset
100 if (self.num_unshown_updates is None or # first time
45b12307c695 Initial revision
drewp
parents:
diff changeset
101 self.options.fast_updates or # show always
45b12307c695 Initial revision
drewp
parents:
diff changeset
102 (self.combinedlevels!=self.lastshownlevels and # changed
45b12307c695 Initial revision
drewp
parents:
diff changeset
103 self.num_unshown_updates>5)): # not too frequent
45b12307c695 Initial revision
drewp
parents:
diff changeset
104 self.num_unshown_updates=0
45b12307c695 Initial revision
drewp
parents:
diff changeset
105 self.printlevels()
45b12307c695 Initial revision
drewp
parents:
diff changeset
106 self.lastshownlevels=self.combinedlevels[:]
45b12307c695 Initial revision
drewp
parents:
diff changeset
107 else:
45b12307c695 Initial revision
drewp
parents:
diff changeset
108 self.num_unshown_updates+=1
45b12307c695 Initial revision
drewp
parents:
diff changeset
109
45b12307c695 Initial revision
drewp
parents:
diff changeset
110 if time.time()>self.laststatsprint+2:
45b12307c695 Initial revision
drewp
parents:
diff changeset
111 self.laststatsprint=time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
112 self.printstats()
45b12307c695 Initial revision
drewp
parents:
diff changeset
113
45b12307c695 Initial revision
drewp
parents:
diff changeset
114 if self.clientschanged or time.time()>self.lastupdate+1:
45b12307c695 Initial revision
drewp
parents:
diff changeset
115 self.lastupdate=time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
116 self.sendlevels_dmx()
45b12307c695 Initial revision
drewp
parents:
diff changeset
117
45b12307c695 Initial revision
drewp
parents:
diff changeset
118 self.clientschanged=0 # clear the flag
45b12307c695 Initial revision
drewp
parents:
diff changeset
119
45b12307c695 Initial revision
drewp
parents:
diff changeset
120 def calclevels(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
121 """combine all the known client levels into self.combinedlevels"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
122 self.combinedlevels=[]
45b12307c695 Initial revision
drewp
parents:
diff changeset
123 for chan in range(0,self.parportdmx.dimmers):
45b12307c695 Initial revision
drewp
parents:
diff changeset
124 x=0
45b12307c695 Initial revision
drewp
parents:
diff changeset
125 for clientlist in self.clientlevels.values():
45b12307c695 Initial revision
drewp
parents:
diff changeset
126 if len(clientlist)>chan:
45b12307c695 Initial revision
drewp
parents:
diff changeset
127 # clamp client levels to 0..1
45b12307c695 Initial revision
drewp
parents:
diff changeset
128 cl=max(0,min(1,clientlist[chan]))
45b12307c695 Initial revision
drewp
parents:
diff changeset
129 x=max(x,cl)
45b12307c695 Initial revision
drewp
parents:
diff changeset
130 self.combinedlevels.append(x)
45b12307c695 Initial revision
drewp
parents:
diff changeset
131
45b12307c695 Initial revision
drewp
parents:
diff changeset
132 def printlevels(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
133 """write all the levels to stdout"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
134 print "Levels:","".join(["% 2d "%(x*100) for
45b12307c695 Initial revision
drewp
parents:
diff changeset
135 x in self.combinedlevels])
45b12307c695 Initial revision
drewp
parents:
diff changeset
136
45b12307c695 Initial revision
drewp
parents:
diff changeset
137 def printstats(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
138 """print the clock, freq, etc, with a \r at the end"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
139
45b12307c695 Initial revision
drewp
parents:
diff changeset
140 sys.stdout.write("dmxserver up at %s, [polls %s] "%
45b12307c695 Initial revision
drewp
parents:
diff changeset
141 (time.strftime("%H:%M:%S"),
45b12307c695 Initial revision
drewp
parents:
diff changeset
142 str(self.updatefreq),
45b12307c695 Initial revision
drewp
parents:
diff changeset
143 ))
45b12307c695 Initial revision
drewp
parents:
diff changeset
144 for cid,freq in self.clientfreq.items():
45b12307c695 Initial revision
drewp
parents:
diff changeset
145 sys.stdout.write("[%s %s] " % (cid,str(freq)))
45b12307c695 Initial revision
drewp
parents:
diff changeset
146 sys.stdout.write("\r")
45b12307c695 Initial revision
drewp
parents:
diff changeset
147 sys.stdout.flush()
45b12307c695 Initial revision
drewp
parents:
diff changeset
148
45b12307c695 Initial revision
drewp
parents:
diff changeset
149 def sendlevels_dmx(self):
45b12307c695 Initial revision
drewp
parents:
diff changeset
150 """output self.combinedlevels to dmx, and keep the updates/sec stats"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
151 # they'll get divided by 100
45b12307c695 Initial revision
drewp
parents:
diff changeset
152 if self.parportdmx:
45b12307c695 Initial revision
drewp
parents:
diff changeset
153 self.parportdmx.sendlevels([l*100 for l in self.combinedlevels])
45b12307c695 Initial revision
drewp
parents:
diff changeset
154 self.updatefreq.update()
45b12307c695 Initial revision
drewp
parents:
diff changeset
155
45b12307c695 Initial revision
drewp
parents:
diff changeset
156 def xmlrpc_echo(self,x):
45b12307c695 Initial revision
drewp
parents:
diff changeset
157 return x
45b12307c695 Initial revision
drewp
parents:
diff changeset
158
45b12307c695 Initial revision
drewp
parents:
diff changeset
159 def xmlrpc_outputlevels(self,cid,levellist):
45b12307c695 Initial revision
drewp
parents:
diff changeset
160 """send a unique id for your client (name+pid maybe), then
45b12307c695 Initial revision
drewp
parents:
diff changeset
161 the variable-length dmx levellist (scaled 0..1)"""
45b12307c695 Initial revision
drewp
parents:
diff changeset
162 if levellist!=self.clientlevels.get(cid,None):
45b12307c695 Initial revision
drewp
parents:
diff changeset
163 self.clientlevels[cid]=levellist
45b12307c695 Initial revision
drewp
parents:
diff changeset
164 self.clientschanged=1
45b12307c695 Initial revision
drewp
parents:
diff changeset
165 if cid not in self.lastseen:
45b12307c695 Initial revision
drewp
parents:
diff changeset
166 print "hello new client %s" % cid
45b12307c695 Initial revision
drewp
parents:
diff changeset
167 self.clientfreq[cid]=Updatefreq()
45b12307c695 Initial revision
drewp
parents:
diff changeset
168
45b12307c695 Initial revision
drewp
parents:
diff changeset
169 self.lastseen[cid]=time.time()
45b12307c695 Initial revision
drewp
parents:
diff changeset
170 self.clientfreq[cid].update()
45b12307c695 Initial revision
drewp
parents:
diff changeset
171 return "ok"
45b12307c695 Initial revision
drewp
parents:
diff changeset
172
45b12307c695 Initial revision
drewp
parents:
diff changeset
173 parser=OptionParser()
45b12307c695 Initial revision
drewp
parents:
diff changeset
174 parser.add_option("-f","--fast-updates",action='store_true',
45b12307c695 Initial revision
drewp
parents:
diff changeset
175 help=('display all dmx output to stdout instead '
45b12307c695 Initial revision
drewp
parents:
diff changeset
176 'of the usual reduced output'))
45b12307c695 Initial revision
drewp
parents:
diff changeset
177 parser.add_option("-r","--updates-per-sec",type='float',default=20,
45b12307c695 Initial revision
drewp
parents:
diff changeset
178 help=('dmx output frequency'))
45b12307c695 Initial revision
drewp
parents:
diff changeset
179 (options,songfiles)=parser.parse_args()
45b12307c695 Initial revision
drewp
parents:
diff changeset
180
45b12307c695 Initial revision
drewp
parents:
diff changeset
181 print options
45b12307c695 Initial revision
drewp
parents:
diff changeset
182
45b12307c695 Initial revision
drewp
parents:
diff changeset
183 print "starting xmlrpc server on port 8030"
45b12307c695 Initial revision
drewp
parents:
diff changeset
184 reactor.listenTCP(8030,server.Site(XMLRPCServe(options)))
45b12307c695 Initial revision
drewp
parents:
diff changeset
185 reactor.run()
45b12307c695 Initial revision
drewp
parents:
diff changeset
186