more stable frame rate

This commit is contained in:
Stefan Kögl 2014-04-27 15:45:00 +02:00
parent dac236ca12
commit 720b7c00a9
1 changed files with 133 additions and 87 deletions

View File

@ -22,8 +22,6 @@
from __future__ import absolute_import from __future__ import absolute_import
import os
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from chaosc.argparser_groups import * from chaosc.argparser_groups import *
from chaosc.lib import logger, resolve_host from chaosc.lib import logger, resolve_host
@ -31,15 +29,13 @@ from collections import deque
from datetime import datetime from datetime import datetime
from dump_grabber.dump_grabber_ui import Ui_MainWindow from dump_grabber.dump_grabber_ui import Ui_MainWindow
from os import curdir, sep from os import curdir, sep
from PyKDE4.kdecore import ki18n, KCmdLineArgs, KAboutData
from PyKDE4.kdeui import KMainWindow, KApplication
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
from SocketServer import ThreadingMixIn, ForkingMixIn from SocketServer import ThreadingMixIn, ForkingMixIn
import logging import logging
import numpy as np import numpy as np
import os
import os.path import os.path
import Queue import Queue
import random import random
@ -57,25 +53,102 @@ try:
except ImportError as e: except ImportError as e:
from chaosc.osc_lib import OSCMessage, decode_osc from chaosc.osc_lib import OSCMessage, decode_osc
#appName = "dump_grabber"
#catalog = "dump_grabber"
#programName = ki18n("dump_grabber")
#version = "0.1"
#aboutData = KAboutData(appName, catalog, programName, version)
appName = "dump_grabber" #KCmdLineArgs.init(sys.argv, aboutData)
catalog = "dump_grabber"
programName = ki18n("dump_grabber")
version = "0.1"
aboutData = KAboutData(appName, catalog, programName, version) app = QtGui.QApplication([])
KCmdLineArgs.init (sys.argv, aboutData)
app = KApplication()
fh = logging.FileHandler(os.path.expanduser("~/.chaosc/dump_grabber.log")) fh = logging.FileHandler(os.path.expanduser("~/.chaosc/dump_grabber.log"))
fh.setLevel(logging.DEBUG) fh.setLevel(logging.DEBUG)
logger.addHandler(fh) logger.addHandler(fh)
class MainWindow(KMainWindow, Ui_MainWindow): class TextStorage(object):
def __init__(self, parent=None, columns=3): def __init__(self, columns):
super(TextStorage, self).__init__()
self.column_count = columns
self.colors = (QtCore.Qt.red, QtCore.Qt.green, QtGui.QColor(46, 100, 254))
def init_columns(self):
raise NotImplementedError()
def add_text(self, column, text):
raise NotImplementedError()
class ColumnTextStorage(TextStorage):
def __init__(self, columns, default_font, column_width, line_height, scene):
super(ColumnTextStorage, self).__init__(columns)
self.columns = list()
self.default_font = default_font
self.column_width = column_width
self.line_height = line_height
self.graphics_scene = scene
self.num_lines, self.offset = divmod(775, self.line_height)
def init_columns(self):
for x in range(self.column_count):
column = list()
color = self.colors[x]
for y in range(self.num_lines):
text_item = self.graphics_scene.addSimpleText("%d:%d" % (x, y), self.default_font)
text_item.setBrush(color)
text_item.setPos(x * self.column_width, y * self.line_height)
column.append(text_item)
self.columns.append(column)
def add_text(self, column, text):
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
color = self.colors[column]
text_item.setBrush(color)
old_item = self.columns[column].pop(0)
self.graphics_scene.removeItem(old_item)
self.columns[column].append(text_item)
for iy, text_item in enumerate(self.columns[column]):
text_item.setPos(column * self.column_width, iy * self.line_height)
class ExclusiveTextStorage(TextStorage):
def __init__(self, columns, default_font, column_width, line_height, scene):
super(ExclusiveTextStorage, self).__init__(columns)
self.column_count = columns
self.lines = list()
self.default_font = default_font
self.column_width = column_width
self.line_height = line_height
self.graphics_scene = scene
self.num_lines, self.offset = divmod(775, self.line_height)
def init_columns(self):
color = self.colors[0]
for y in range(self.num_lines):
text_item = self.graphics_scene.addSimpleText("", self.default_font)
text_item.setBrush(color)
text_item.setPos(0, y * self.line_height)
self.lines.append(text_item)
def add_text(self, column, text):
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
text_item.setX(column * self.column_width)
color = self.colors[column]
text_item.setBrush(color)
old_item = self.lines.pop(0)
self.graphics_scene.removeItem(old_item)
self.lines.append(text_item)
for iy, text_item in enumerate(self.lines):
text_item.setY(iy * self.line_height)
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None, columns=3, column_exclusive=False):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
self.setupUi(self) self.setupUi(self)
self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
@ -88,55 +161,27 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.default_font = QtGui.QFont("Monospace", 14) self.default_font = QtGui.QFont("Monospace", 14)
self.default_font.setStyleHint(QtGui.QFont.Monospace) self.default_font.setStyleHint(QtGui.QFont.Monospace)
self.default_font.setBold(True) self.default_font.setBold(True)
self.blue_color = QtGui.QColor(47,147,235) self.graphics_scene.setFont(self.default_font)
self.font_metrics = QtGui.QFontMetrics(self.default_font) self.font_metrics = QtGui.QFontMetrics(self.default_font)
self.line_height = self.font_metrics.height() self.line_height = self.font_metrics.height()
self.num_lines = 775/self.line_height
self.graphics_scene.setFont(self.default_font)
self.brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
self.brush.setStyle(QtCore.Qt.SolidPattern)
self.column_width = 775 / columns self.column_width = 775 / columns
self.column_count = columns self.text_storage = ExclusiveTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
self.columns = list() #self.text_storage = ColumnTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
for i in range(columns): self.text_storage.init_columns()
column = list()
for j in range(self.num_lines):
text_item = self.graphics_scene.addSimpleText("", self.default_font)
if column == 0:
text_item.setBrush(QtCore.Qt.red)
elif column == 1:
text_item.setBrush(QtCore.Qt.green)
elif column == 2:
text_item.setBrush(self.blue_color)
text_item.setPos(j * self.line_height, i * self.column_width)
column.append(text_item)
self.columns.append(column)
self.graphics_view.show()
def add_text(self, column, text): def add_text(self, column, text):
text_item = self.graphics_scene.addSimpleText(text, self.default_font) self.text_storage.add_text(column, text)
if column == 0:
text_item.setBrush(QtCore.Qt.red)
elif column == 1:
text_item.setBrush(QtCore.Qt.green)
elif column == 2:
text_item.setBrush(self.blue_color)
old_item = self.columns[column].pop(0)
self.graphics_scene.removeItem(old_item)
self.columns[column].append(text_item)
for ix, text_item in enumerate(self.columns[column]):
text_item.setPos(column * self.column_width, ix * self.line_height)
def render(self): def render(self):
image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32) image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32_Premultiplied)
image.fill(QtCore.Qt.black) image.fill(QtCore.Qt.black)
painter = QtGui.QPainter(image) painter = QtGui.QPainter(image)
#painter.setPen(QtCore.Qt.white) painter.setRenderHints(QtGui.QPainter.RenderHint(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing), True)
painter.setFont(self.default_font) painter.setFont(self.default_font)
self.graphics_view.render(painter, target=QtCore.QRectF(0,0,768,576),source=QtCore.QRect(0,0,768,576)) self.graphics_view.render(painter, target=QtCore.QRectF(0,0,768,576),source=QtCore.QRect(0,0,768,576))
painter.end()
return image return image
@ -159,17 +204,6 @@ class OSCThread(threading.Thread):
self.subscribe_me() self.subscribe_me()
def subscribe_me(self): def subscribe_me(self):
"""Use this procedure for a quick'n dirty subscription to your chaosc instance.
:param chaosc_address: (chaosc_host, chaosc_port)
:type chaosc_address: tuple
:param receiver_address: (host, port)
:type receiver_address: tuple
:param token: token to get authorized for subscription
:type token: str
"""
logger.info("%s: subscribing to '%s:%d' with label %r", datetime.now().strftime("%x %X"), self.chaosc_address[0], self.chaosc_address[1], self.args.subscriber_label) logger.info("%s: subscribing to '%s:%d' with label %r", datetime.now().strftime("%x %X"), self.chaosc_address[0], self.chaosc_address[1], self.args.subscriber_label)
msg = OSCMessage("/subscribe") msg = OSCMessage("/subscribe")
msg.appendTypedArg(self.client_address[0], "s") msg.appendTypedArg(self.client_address[0], "s")
@ -224,7 +258,6 @@ class MyHandler(BaseHTTPRequestHandler):
if self.path=="" or self.path==None or self.path[:1]==".": if self.path=="" or self.path==None or self.path[:1]==".":
self.send_error(403,'Forbidden') self.send_error(403,'Forbidden')
if self.path.endswith(".html"): if self.path.endswith(".html"):
directory = os.path.dirname(os.path.abspath(__file__)) directory = os.path.dirname(os.path.abspath(__file__))
data = open(os.path.join(directory, self.path), "rb").read() data = open(os.path.join(directory, self.path), "rb").read()
@ -244,6 +277,10 @@ class MyHandler(BaseHTTPRequestHandler):
self.end_headers() self.end_headers()
event_loop = QtCore.QEventLoop() event_loop = QtCore.QEventLoop()
last_frame = time.time() - 1.
frame_rate = 16.0
frame_length = 1. / frame_rate
regrex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
while 1: while 1:
event_loop.processEvents() event_loop.processEvents()
app.sendPostedEvents(None, 0) app.sendPostedEvents(None, 0)
@ -253,18 +290,27 @@ class MyHandler(BaseHTTPRequestHandler):
except Queue.Empty: except Queue.Empty:
break break
else: else:
if "merle" in osc_address: try:
window.add_text(0, "%s = %s" % (osc_address[7:], ", ".join([str(i) for i in args]))) actor, text = regex.match(osc_address).groups()
elif "uwe" in osc_address: if actor == "merle":
window.add_text(1, "%s = %s" % (osc_address[5:], ", ".join([str(i) for i in args]))) window.add_text(0, "%s = %s" % (text, ", ".join([str(i) for i in args])))
elif "bjoern" in osc_address: if actor == "uwe":
window.add_text(2, "%s = %s" % (osc_address[8:], ", ".join([str(i) for i in args]))) window.add_text(1, "%s = %s" % (text, ", ".join([str(i) for i in args])))
if actor == "bjoern":
window.add_text(2, "%s = %s" % (text, ", ".join([str(i) for i in args])))
except AttributeError:
pass
now = time.time()
delta = now - last_frame
if delta > frame_length:
print 1 / delta
last_frame = now
img = window.render() img = window.render()
buffer = QBuffer() buffer = QBuffer()
buffer.open(QIODevice.WriteOnly) buffer.open(QIODevice.WriteOnly)
img.save(buffer, "JPG", 50) img.save(buffer, "JPG")
img.save("/tmp/test.jpg", "JPG", 50) #img.save(os.path.expanduser("~/.chaosc/dump_grabber.jpg"), "JPG")
JpegData = buffer.data() JpegData = buffer.data()
self.wfile.write("--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(JpegData), JpegData)) self.wfile.write("--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(JpegData), JpegData))
@ -272,7 +318,7 @@ class MyHandler(BaseHTTPRequestHandler):
JpegData = None JpegData = None
buffer = None buffer = None
img = None img = None
time.sleep(0.06) time.sleep(0.01)
elif self.path.endswith(".jpeg"): elif self.path.endswith(".jpeg"):
directory = os.path.dirname(os.path.abspath(__file__)) directory = os.path.dirname(os.path.abspath(__file__))
@ -298,11 +344,6 @@ class MyHandler(BaseHTTPRequestHandler):
self.thread = None self.thread = None
else: else:
pass pass
#print '-'*40
#print 'Exception happened during processing of request from'
#traceback.print_exc() # XXX But this goes to stderr!
#print '-'*40
#self.send_error(404,'File Not Found: %s' % self.path)
class JustAHTTPServer(HTTPServer): class JustAHTTPServer(HTTPServer):
@ -321,6 +362,11 @@ def main():
arg_parser.add_subscriber_group() arg_parser.add_subscriber_group()
args = arg_parser.finalize() args = arg_parser.finalize()
if not args.background:
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)
http_host, http_port = resolve_host(args.http_host, args.http_port, args.address_family) http_host, http_port = resolve_host(args.http_host, args.http_port, args.address_family)
server = JustAHTTPServer((http_host, http_port), MyHandler) server = JustAHTTPServer((http_host, http_port), MyHandler)