diff --git a/bin/lightsim b/bin/lightsim --- a/bin/lightsim +++ b/bin/lightsim @@ -2,18 +2,17 @@ from __future__ import division import run_local -import xmlrpclib, sys, logging +import sys, logging sys.path.append("lib") import qt4reactor qt4reactor.install() -from rdflib import Literal, URIRef from twisted.internet import reactor from twisted.internet.task import LoopingCall from twisted.web.xmlrpc import Proxy from louie import dispatcher -from PyQt4 import QtCore, QtGui, QtOpenGL +from PyQt4.QtGui import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QMainWindow from OpenGL.GL import * from OpenGL.GLU import * @@ -25,11 +24,21 @@ log = logging.getLogger() logging.basicConfig(format="%(asctime)s %(levelname)-5s %(name)s %(filename)s:%(lineno)d: %(message)s") log.setLevel(logging.DEBUG) +def filenamesForChan(graph, chan): + for lyr in graph.objects(chan, L9['previewLayer']): + for imgPath in graph.objects(lyr, L9['path']): + yield imgPath + +_lastLevels = None def poll(graph, serv, pollFreq, oglSurface): pollFreq.update() dispatcher.send("status", key="pollFreq", value=str(pollFreq)) d = serv.callRemote("currentlevels", dmxclient._id) def received(dmxLevels): + global _lastLevels + if dmxLevels == _lastLevels: + return + _lastLevels = dmxLevels level = {} # filename : level for i, lev in enumerate(dmxLevels): if lev == 0: @@ -40,79 +49,77 @@ def poll(graph, serv, pollFreq, oglSurfa except KeyError: continue - for lyr in graph.objects(chan, L9['previewLayer']): - for imgPath in graph.objects(lyr, L9['path']): - level[str(imgPath)] = lev + for imgPath in filenamesForChan(graph, chan): + level[str(imgPath)] = lev oglSurface.newLevels(levels=level) d.addCallback(received) return d -class StatusKeys(object): - # 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) +class StatusKeys(QWidget): + """listens for dispatcher signal 'status' and displays the key/value args""" + def __init__(self, parent): + QWidget.__init__(self) + self.layout = QVBoxLayout() + self.setLayout(self.layout) + self.row = {} # key name : (Frame, value Label) 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) + row = QWidget() + self.layout.addWidget(row) + cols = QHBoxLayout() + row.setLayout(cols) + lab1 = QLabel(key) + lab2 = QLabel(value) + cols.addWidget(lab1) + cols.addWidget(lab2) + self.row[key] = lab2 else: - row, lab = self.row[key] - lab.config(text=value) - + lab = self.row[key] + lab.setText(value) - -class Window(QtGui.QMainWindow): +class Window(QMainWindow): def __init__(self, filenames): - QtGui.QMainWindow.__init__(self, None) + QMainWindow.__init__(self, None) + self.setWindowTitle(dmxclient._id) - self.w = QtGui.QWidget() - self.setCentralWidget(self.w) + w = QWidget() + self.setCentralWidget(w) + mainLayout = QVBoxLayout() + w.setLayout(mainLayout) - self.glWidget = Surface(self, filenames, - width=120*3, height=80*3, - imgRescaleTo=128) + self.glWidget = Surface(self, filenames, imgRescaleTo=128*2) + + mainLayout.addWidget(self.glWidget) + + status = StatusKeys(mainLayout) + mainLayout.addWidget(status) - self.glWidget.newLevels(levels={ - "lightsim/skyline/front-left.png" : .4, - "lightsim/skyline/front-right.png" : .8}) - - mainLayout = QtGui.QHBoxLayout() - mainLayout.addWidget(self.glWidget) - self.w.setLayout(mainLayout) - - self.setWindowTitle(dmxclient._id) +def requiredImages(graph): + """filenames that we'll need to show, based on a config structure + like this: + ch:frontLeft a :Channel; + :previewLayer [ :path "lightsim/skyline/front-left.png" ] . + """ + filenames = [] + for lyr in graph.objects(None, L9['previewLayer']): + for p in graph.objects(lyr, L9['path']): + filenames.append(str(p)) + return filenames if __name__ == '__main__': app = reactor.qApp graph = showconfig.getGraph() - filenames = [] - for lyr in graph.objects(None, L9['previewLayer']): - for p in graph.objects(lyr, L9['path']): - filenames.append(str(p)) - filenames.append("lightsim/skyline/front-left.png") # test - filenames.append("lightsim/skyline/front-right.png") # test - window = Window(filenames) + window = Window(requiredImages(graph)) window.show() serv = Proxy(networking.dmxServerUrl()) - pollFreq = updatefreq.Updatefreq(samples=5) - LoopingCall(poll, graph, serv, pollFreq, window.glWidget).start(.1) + pollFreq = updatefreq.Updatefreq() + LoopingCall(poll, graph, serv, pollFreq, window.glWidget).start(.05) reactor.run() - -###################################################### -#sk = StatusKeys(root) -#sk.pack(side='top', fill='x') -#prof.run(reactor.run, profile=False) diff --git a/lightsim/openglsim.py b/lightsim/openglsim.py --- a/lightsim/openglsim.py +++ b/lightsim/openglsim.py @@ -8,7 +8,8 @@ import Tkinter as tk import Image from louie import dispatcher -from PyQt4 import QtCore, QtOpenGL +from PyQt4.QtCore import QSize +from PyQt4.QtOpenGL import QGLWidget from OpenGL.GL import * def xxxdrawWithAlpha(imgString, w, h, alpha): @@ -21,15 +22,14 @@ def xxxdrawWithAlpha(imgString, w, h, al #glBlendColor(1, 1, 1, mag) # needs ARB_imaging glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, imgString) -class Surface(QtOpenGL.QGLWidget): +class Surface(QGLWidget): """widget that adds multiple image files together with adjustable scales""" - def __init__(self, parent, filenames, width=512, height=270, - imgRescaleTo=None): + def __init__(self, parent, filenames, imgRescaleTo=None): """ imgRescaleTo can be a length of pixels to reduce all the input images into. Try 64 for a low res drawing. """ - QtOpenGL.QGLWidget.__init__(self, parent) + QGLWidget.__init__(self, parent) self.levels = {} # filename : brightness @@ -37,6 +37,7 @@ class Surface(QtOpenGL.QGLWidget): for filename in filenames: print "open", filename im = Image.open(filename) + self.origImageSize = im.size[0], im.size[1] if imgRescaleTo: im.thumbnail((imgRescaleTo, imgRescaleTo)) im = im.transpose(Image.FLIP_TOP_BOTTOM) @@ -44,8 +45,6 @@ class Surface(QtOpenGL.QGLWidget): self.imageHeight = im.size[1] self.image[filename] = im.convert("RGBA").tostring() - #self.set_centerpoint(0, 0, 0) - def initializeGL(self): glDisable(GL_CULL_FACE) glShadeModel(GL_FLAT) @@ -53,11 +52,8 @@ class Surface(QtOpenGL.QGLWidget): import OpenGL print OpenGL.__version__ -# def minimumSizeHint(self): -# return QtCore.QSize(512, 512) - -# def sizeHint(self): -# return QtCore.QSize(512, 512) + def sizeHint(self): + return QSize(*self.origImageSize) def paintGL(self): """you set self.levels to dict and call tkRedraw""" @@ -75,20 +71,23 @@ class Surface(QtOpenGL.QGLWidget): # drawing to glAccum might be good layerTimes = [] + layers = 0 for filename, mag in self.levels.items(): t = time.time() - self.drawWithAlpha(self.image[filename], - self.imageWidth, self.imageHeight, mag) + layers += self.drawWithAlpha(self.image[filename], + self.imageWidth, self.imageHeight, mag) layerTimes.append(time.time() - t) + dispatcher.send("status", key="visibleLayers", value=str(layers)) + dispatcher.send("status", key="redraw", value="%.1fms" % ((time.time() - start) * 1000)) def drawWithAlpha(self, imgString, w, h, alpha): - """without opengl extensions""" + """without opengl extensions. Returns number of layers drawn""" if alpha == 0: - return + return 0 t = time.time() ar = num.reshape(num.fromstring(imgString, dtype='uint8'), (w * h, 4)) @@ -109,6 +108,7 @@ class Surface(QtOpenGL.QGLWidget): glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, ar.tostring()) #print " draw", time.time() - t + return 1 def newLevels(self, event=None, levels=None): if levels != self.levels: