view bin/lightsim @ 1447:8a9a9b58a4e2

live page now knows that collector needs all settings on each request Ignore-this: 79ad8d1e001b98b6fce6d14f75f92745
author drewp@bigasterisk.com
date Sat, 11 Jun 2016 21:40:37 +0000
parents b5efddd80dad
children 7772cc48e016
line wrap: on
line source

#!bin/python

from __future__ import division
import run_local
import sys, logging

sys.path.append("lib")
import qt4reactor
qt4reactor.install()

from twisted.internet import reactor
from twisted.internet.task import LoopingCall
from twisted.web.xmlrpc import Proxy
from louie import dispatcher
from PyQt4.QtGui import QWidget, QLabel, QVBoxLayout, QHBoxLayout, QMainWindow
from OpenGL.GL import *
from OpenGL.GLU import *

from light9 import networking, Patch, showconfig, dmxclient, updatefreq, prof
from light9.namespaces import L9
from lightsim.openglsim import Surface

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:
                continue

            try:
                chan = Patch.get_channel_uri(Patch.get_channel_name(i + 1))
            except KeyError:
                continue

            for imgPath in filenamesForChan(graph, chan):
                level[str(imgPath)] = lev

        oglSurface.newLevels(levels=level)
    d.addCallback(received)
    return d

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")
        
    def status(self, key, value):
        if key not in self.row:
            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:
            lab = self.row[key]
            lab.setText(value)

class Window(QMainWindow):
    def __init__(self, filenames):
        QMainWindow.__init__(self, None)
        self.setWindowTitle(dmxclient._id)

        w = QWidget()
        self.setCentralWidget(w)
        mainLayout = QVBoxLayout()
        w.setLayout(mainLayout)
        
        self.glWidget = Surface(self, filenames, imgRescaleTo=128*2)

        mainLayout.addWidget(self.glWidget)

        status = StatusKeys(mainLayout)
        mainLayout.addWidget(status)      

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()

    window = Window(requiredImages(graph))
    window.show()

    serv = Proxy(networking.dmxServer.url)
    pollFreq = updatefreq.Updatefreq()
    LoopingCall(poll, graph, serv, pollFreq, window.glWidget).start(.05)

    reactor.run()