Mercurial > code > home > repos > light9
changeset 353:941cfe1e1691
lightsim now reads levels from dmxserver
author | drewp@bigasterisk.com |
---|---|
date | Mon, 11 Jun 2007 00:53:16 +0000 |
parents | 9d1f323fb3d3 |
children | f3909c2df943 |
files | bin/dmxserver bin/lightsim lightsim/openglsim.py lightsim/skyline/layers.xcf |
diffstat | 4 files changed, 150 insertions(+), 87 deletions(-) [+] |
line wrap: on
line diff
--- a/bin/dmxserver Sun Jun 10 17:25:23 2007 +0000 +++ b/bin/dmxserver Mon Jun 11 00:53:16 2007 +0000 @@ -78,13 +78,16 @@ reactor.callLater(1,self.purgeclients) now=time.time() - cids=self.clientlevels.keys() + cids = self.lastseen.keys() for cid in cids: lastseen=self.lastseen[cid] - if lastseen<now-purge_age: + if lastseen < now - purge_age: print ("forgetting client %s (no activity for %s sec)" % (cid,purge_age)) - del self.clientlevels[cid] + try: + del self.clientlevels[cid] + except KeyError: + pass del self.clientfreq[cid] del self.lastseen[cid] @@ -167,18 +170,33 @@ if levellist!=self.clientlevels.get(cid,None): self.clientlevels[cid]=levellist self.clientschanged=1 - if cid not in self.lastseen: - print "hello new client %s" % cid - self.clientfreq[cid]=Updatefreq() - + self.trackClientFreq(cid) + return "ok" + + def xmlrpc_currentlevels(self, cid): + """get a list of levels we're currently sending out. All + channels beyond the list you get back, they're at zero.""" + # if this is still too slow, it might help to return a single + # pickled string + self.trackClientFreq(cid) + trunc = self.combinedlevels[:] + i = len(trunc) - 1 + if i < 0: + return [] + while trunc[i] == 0 and i >= 0: + i -= 1 + if i < 0: + return [] + trunc = trunc[:i+1] + return trunc + + def trackClientFreq(self, cid): + if cid not in self.lastseen: + print "hello new client %s" % cid + self.clientfreq[cid]=Updatefreq() self.lastseen[cid]=time.time() self.clientfreq[cid].update() - return "ok" - - def xmlrpc_currentlevels(self): - """get a list of levels we're currently sending out. All - channels beyond the list you get back, they're at zero.""" - return self.combinedlevels + parser=OptionParser() parser.add_option("-f","--fast-updates",action='store_true',
--- a/bin/lightsim Sun Jun 10 17:25:23 2007 +0000 +++ b/bin/lightsim Mon Jun 11 00:53:16 2007 +0000 @@ -12,9 +12,9 @@ logging.basicConfig(format="%(asctime)s %(levelname)-5s %(name)s %(filename)s:%(lineno)d: %(message)s") log.setLevel(logging.DEBUG) import Tkinter as tk -from light9 import networking, Patch, showconfig, dmxclient +from light9 import networking, Patch, showconfig, dmxclient, updatefreq from light9.namespaces import L9 - +from louie import dispatcher try: from OpenGL import Tk as Togl @@ -26,57 +26,81 @@ from lightsim.openglsim import Surface - - +def poll(graph, serv, pollFreq): + pollFreq.update() + dispatcher.send("status", key="pollFreq", value=str(pollFreq)) + d = serv.callRemote("currentlevels", dmxclient._id) + def received(dmxLevels): + level = {} # filename : level + for i, lev in enumerate(dmxLevels): + if lev == 0: + continue -def poll(graph, serv): - dmxLevels = serv.currentlevels(dmxclient._id) - level = {} # filename : level - for i, lev in enumerate(dmxLevels): - if lev == 0: - continue + try: + chan = Patch.get_channel_uri(Patch.get_channel_name(i + 1)) + except KeyError: + continue + + for lyr in graph.objects(chan, L9['previewLayer']): + for imgPath in graph.objects(lyr, L9['path']): + level[str(imgPath)] = lev - try: - chan = Patch.get_channel_uri(Patch.get_channel_name(i + 1)) - except KeyError: - continue + ogl.newLevels(levels=level) + d.addCallback(received) + return d - for lyr in graph.objects(chan, L9['previewLayer']): - for imgPath in graph.objects(lyr, L9['path']): - level[str(imgPath)] = lev - - print level - ogl.newLevels(levels=level) - +class StatusKeys(tk.Frame): + # watch out- this might be an accidental redo of what curvecalc + # has. Or, maybe CC should use this obj + def __init__(self, master): + tk.Frame.__init__(self, master) + dispatcher.connect(self.status, "status") + self.row = {} # key name : (Frame, value Label) + + def status(self, key, value): + if key not in self.row: + f = tk.Frame(self) + f.pack(side='top') + tk.Label(f, text=key, font="arial 8").pack(side='left') + l = tk.Label(f, text=value, font="arial 8") + l.pack(side='left') + self.row[key] = (f, l) + else: + row, lab = self.row[key] + lab.config(text=value) root = tk.Frame() root.pack(expand=True, fill='both') -QuitButton = tk.Button(root, {'text':'Quit'}) -QuitButton.bind('<ButtonRelease-1>', sys.exit) -QuitButton.pack() - -filenames=['lightsim/skyline/bg.png', - 'lightsim/skyline/cyc-lo-red.png', - 'lightsim/skyline/cyc-lo-grn.png', - ] +pollFreq = updatefreq.Updatefreq(samples=5) +graph = showconfig.getGraph() +filenames = [] +for lyr in graph.objects(None, L9['previewLayer']): + for p in graph.objects(lyr, L9['path']): + filenames.append(str(p)) -scales = {} # filename : scale -for f in filenames: - scales[f] = tk.Scale( - root, label=f, from_=0, to=1, res=.05, orient='horiz', - command=lambda *args: ogl.newLevels( - levels=dict([(f, s.get()) for f,s in scales.items()]))) - scales[f].pack() -ogl = Surface(root, filenames) +ogl = Surface(root, filenames, width=120, height=80, imgRescaleTo=128) ogl.pack(side='top', expand=True, fill='both') -graph = showconfig.getGraph() -serv = Proxy(networking.dmxServerUrl()) -LoopingCall(poll, graph, serv).start(1) +sk = StatusKeys(root) +sk.pack(side='top', fill='x') + -root.winfo_toplevel().bind("<Control-Key-q>",lambda ev: reactor.stop) -root.winfo_toplevel().bind("<Destroy>",lambda ev: reactor.stop) -root.winfo_toplevel().protocol('WM_DELETE_WINDOW', reactor.stop) +serv = Proxy(networking.dmxServerUrl()) +LoopingCall(poll, graph, serv, pollFreq).start(.1) + +top = root.winfo_toplevel() +top.wm_title(dmxclient._id) +top.bind("<Control-Key-q>",lambda ev: reactor.stop) +top.bind("<Destroy>",lambda ev: reactor.stop) +top.protocol('WM_DELETE_WINDOW', reactor.stop) tksupport.install(ogl, ms=20) -reactor.run() + +if 0: + import hotshot, hotshot.stats + p = hotshot.Profile("/tmp/pro") + p.runcall(reactor.run) + p.close() + hotshot.stats.load("/tmp/pro").sort_stats('time').print_stats() +else: + reactor.run()
--- a/lightsim/openglsim.py Sun Jun 10 17:25:23 2007 +0000 +++ b/lightsim/openglsim.py Mon Jun 11 00:53:16 2007 +0000 @@ -6,7 +6,7 @@ import numarray as num import Tkinter as tk import Image - +from louie import dispatcher try: from OpenGL import Tk as Togl from OpenGL.GL import * @@ -27,20 +27,24 @@ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, imgString) class Surface(Togl.Opengl): - width = 512 - height = 270 - imgRescaleTo = 100 - def __init__(self, master, filenames): - Togl.Opengl.__init__(self, master=master, width = self.width, - height = self.height, double = True, depth = 0) + """widget that adds multiple image files together with adjustable scales""" + def __init__(self, master, filenames, width=512, height=270, + imgRescaleTo=None): + """ + imgRescaleTo can be a length of pixels to reduce all the input + images into. Try 64 for a low res drawing. + """ + Togl.Opengl.__init__(self, master=master, width=width, + height=height, double=True, depth=0) + self.width, self.height = width, height self.levels = {} # filename : brightness self.image = {} # filename : imgstr for filename in filenames: im = Image.open(filename) - if self.imgRescaleTo: - im.thumbnail((self.imgRescaleTo, self.imgRescaleTo)) + if imgRescaleTo: + im.thumbnail((imgRescaleTo, imgRescaleTo)) im = im.transpose(Image.FLIP_TOP_BOTTOM) self.imageWidth = im.size[0] self.imageHeight = im.size[1] @@ -57,9 +61,35 @@ self.bind("<Configure>", self.configure) def configure(self, ev): -# import pdb; pdb.set_trace() self.width, self.height = ev.width, ev.height + def redraw(self, event=None): + """you set self.levels to dict and call tkRedraw""" + assert 'GL_ARB_imaging' in glGetString(GL_EXTENSIONS).split() + start = time.time() + + glClearColor(0.0, 0.0, 0.0, 0) + glClear( GL_COLOR_BUFFER_BIT |GL_ACCUM_BUFFER_BIT) + glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE) # add + +# l=glGenLists(1) +# glNewList(l,GL_COMPILE) +# glEndList() + + # drawing to glAccum might be good + layerTimes = [] + for filename, mag in self.levels.items(): + #print "pic %s at %f" % (filename, mag) + t = time.time() + self.drawWithAlpha(self.image[filename], + self.imageWidth, self.imageHeight, mag) + layerTimes.append(time.time() - t) + + dispatcher.send("status", key="redraw", + value="%.1fms" % ((time.time() - start) * 1000)) + + def drawWithAlpha(self, imgString, w, h, alpha): """without opengl extensions""" if alpha == 0: @@ -72,32 +102,23 @@ ar[:,3] *= alpha #print " scl", time.time() - t + + # this might be a good way to scale the color channels too, + # but the blend might take two steps. Anyway, + # GL_CONSTANT_COLOR seems not to work, so i'm not exploring + # this right now. + #glBlendFunc(GL_CONSTANT_COLOR, GL_ONE) + #glBlendColor(.8, .5, .5, .5) + glPixelZoom(self.width / w, self.height / h) glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ar.tostring()) #print " draw", time.time() - t - def redraw(self, event=None): - """you set self.levels to dict and call tkRedraw""" - assert 'GL_ARB_imaging' in glGetString(GL_EXTENSIONS).split() - - glClearColor(0.0, 0.0, 0.0, 0) - glClear( GL_COLOR_BUFFER_BIT |GL_ACCUM_BUFFER_BIT) - glEnable(GL_BLEND) - glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA) -# l=glGenLists(1) -# glNewList(l,GL_COMPILE) -# glEndList() - - # drawing to glAccum might be good - for filename, mag in self.levels.items(): - #print "pic %s at %f" % (filename, mag) - self.drawWithAlpha(self.image[filename], - self.imageWidth, self.imageHeight, mag) - def newLevels(self, event=None, levels=None): - self.levels = levels - self.tkRedraw() + if levels != self.levels: + self.levels = levels + self.tkRedraw() def main(): root = tk.Frame()