more stable frame rate
This commit is contained in:
parent
dac236ca12
commit
720b7c00a9
|
@ -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,26 +290,35 @@ 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
|
||||||
|
|
||||||
img = window.render()
|
now = time.time()
|
||||||
buffer = QBuffer()
|
delta = now - last_frame
|
||||||
buffer.open(QIODevice.WriteOnly)
|
if delta > frame_length:
|
||||||
img.save(buffer, "JPG", 50)
|
print 1 / delta
|
||||||
img.save("/tmp/test.jpg", "JPG", 50)
|
last_frame = now
|
||||||
|
img = window.render()
|
||||||
|
buffer = QBuffer()
|
||||||
|
buffer.open(QIODevice.WriteOnly)
|
||||||
|
img.save(buffer, "JPG")
|
||||||
|
#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))
|
||||||
|
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue