implemented dump_grabber

This commit is contained in:
Stefan Kögl 2014-04-23 16:31:19 +02:00
parent fce69b46ee
commit 2effe315a7
1 changed files with 261 additions and 12 deletions

View File

@ -6,12 +6,40 @@ import sys, os, random
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
from dump_grabber_ui import Ui_MainWindow
from PyKDE4.kdecore import ki18n, KCmdLineArgs, KAboutData
from PyKDE4.kdeui import KMainWindow, KApplication
from datetime import datetime
import threading
import Queue
import traceback
import numpy as np
import string
import time
import random
import socket
import os.path
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn, ForkingMixIn
import select
import re
from collections import deque
from chaosc.argparser_groups import *
from chaosc.lib import resolve_host
try:
from chaosc.c_osc_lib import OSCMessage, decode_osc
except ImportError as e:
print(e)
from chaosc.osc_lib import OSCMessage, decode_osc
appName = "dump_grabber"
catalog = "dump_grabber"
programName = ki18n("dump_grabber")
@ -23,7 +51,7 @@ KCmdLineArgs.init (sys.argv, aboutData)
app = KApplication()
class MainWindow(KMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
def __init__(self, parent=None, columns=3):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
@ -39,24 +67,245 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.font_metrics = QtGui.QFontMetrics(self.default_font)
self.line_height = self.font_metrics.height()
self.num_lines = 775/self.line_height
self.graphics_scene.setFont(self.default_font)
print "font", self.default_font.family(), self.default_font.pixelSize(), self.default_font.pointSize()
self.brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
self.brush.setStyle(QtCore.Qt.SolidPattern)
pos_y = 0
for i in range(self.num_lines):
text = self.graphics_scene.addSimpleText("osc address:/test/foo/bar arguments:[%d] types=[\"i\"]" % random.randint(0,255), self.default_font)
text.setBrush(self.brush)
text.setPos(0, i * self.line_height)
pos_y += self.line_height
self.column_count = columns
self.columns = [["" for j in range(self.num_lines)]
for i in range(columns)]
self.column_width = 775 / columns
self.column_heads = [self.num_lines - 1] * columns
self.graphics_view.show()
def add_text(self, column, text):
head = self.column_heads[column]
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
#text_item.setPen(QtCore.Qt.red)
if column == 0:
text_item.setBrush(QtCore.Qt.red)
elif column == 1:
text_item.setBrush(QtCore.Qt.green)
elif column == 2:
text_item.setBrush(QtCore.Qt.blue)
text_item.setPos(column * self.column_width, head * self.line_height)
print "head", column, head
self.columns[column][head] = text_item
self.column_heads[column] = (head - 1) % self.num_lines
def render(self):
image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32_Premultiplied)
image.fill(QtCore.Qt.black)
painter = QtGui.QPainter(image)
#painter.setPen(QtCore.Qt.white)
painter.setFont(self.default_font)
self.graphics_view.render(painter, target=QtCore.QRectF(0,0,768,576),source=QtCore.QRect(0,0,768,576))
return image
class OSCThread(threading.Thread):
def __init__(self, args):
super(OSCThread, self).__init__()
self.args = args
self.running = True
self.client_address = resolve_host(args.client_host, args.client_port, args.address_family)
self.chaosc_address = chaosc_host, chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
self.osc_sock = socket.socket(args.address_family, 2, 17)
self.osc_sock.bind(self.client_address)
self.osc_sock.setblocking(0)
print "%s: starting up osc receiver on '%s:%d'" % (
datetime.now().strftime("%x %X"), self.client_address[0], self.client_address[1])
self.subscribe_me()
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
"""
print "%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.appendTypedArg(self.client_address[0], "s")
msg.appendTypedArg(self.client_address[1], "i")
msg.appendTypedArg(self.args.authenticate, "s")
if self.args.subscriber_label is not None:
msg.appendTypedArg(self.args.subscriber_label, "s")
self.osc_sock.sendto(msg.encode_osc(), self.chaosc_address)
def unsubscribe_me(self):
if self.args.keep_subscribed:
return
print "%s: unsubscribing from '%s:%d'" % (datetime.now().strftime("%x %X"), self.chaosc_address[0], self.chaosc_address[1])
msg = OSCMessage("/unsubscribe")
msg.appendTypedArg(self.client_address[0], "s")
msg.appendTypedArg(self.client_address[1], "i")
msg.appendTypedArg(self.args.authenticate, "s")
self.osc_sock.sendto(msg.encode_osc(), self.chaosc_address)
def run(self):
while self.running:
try:
reads, writes, errs = select.select([self.osc_sock], [], [], 0.05)
except Exception, e:
print "select error", e
pass
else:
if reads:
try:
osc_input, address = self.osc_sock.recvfrom(8192)
osc_address, typetags, messages = decode_osc(osc_input, 0, len(osc_input))
print osc_address, typetags, messages
if osc_address.find("ekg") != -1 or osc_address.find("plot") != -1:
queue.put_nowait((osc_address, messages))
except Exception, e:
print "recvfrom error", e
else:
queue.put_nowait(("/bjoern/ekg", [0]))
queue.put_nowait(("/merle/ekg", [0]))
queue.put_nowait(("/uwe/ekg", [0]))
self.unsubscribe_me()
print "OSCThread is going down"
queue = Queue.Queue()
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
if self.path=="" or self.path==None or self.path[:1]==".":
self.send_error(403,'Forbidden')
if self.path.endswith(".html"):
directory = os.path.dirname(os.path.abspath(__file__))
data = open(os.path.join(directory, self.path), "rb").read()
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(data)
elif self.path.endswith(".mjpeg"):
self.thread = thread = OSCThread(self.server.args)
thread.daemon = True
thread.start()
window = MainWindow()
window.show()
self.send_response(200)
self.send_header("Content-Type", "multipart/x-mixed-replace; boundary=--aaboundary")
self.end_headers()
event_loop = QtCore.QEventLoop()
while 1:
event_loop.processEvents()
app.sendPostedEvents(None, 0)
while 1:
try:
osc_address, args = queue.get_nowait()
print osc_address, args
except Queue.Empty:
break
else:
if "merle" in osc_address:
window.add_text(0, "%s = %s" % (osc_address[7:], ", ".join([str(i) for i in args])))
elif "uwe" in osc_address:
window.add_text(1, "%s = %s" % (osc_address[5:], ", ".join([str(i) for i in args])))
elif "bjoern" in osc_address:
window.add_text(2, "%s = %s" % (osc_address[8:], ", ".join([str(i) for i in args])))
img = window.render()
buffer = QBuffer()
buffer.open(QIODevice.WriteOnly)
img.save(buffer, "JPG", 100)
img.save("/tmp/test.jpg", "JPG")
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))
JpegData = None
buffer = None
img = None
elif self.path.endswith(".jpeg"):
directory = os.path.dirname(os.path.abspath(__file__))
data = open(os.path.join(directory, self.path), "rb").read()
self.send_response(200)
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(data)
return
except (KeyboardInterrupt, SystemError):
print "queue size", queue.qsize()
if hasattr(self, "thread") and self.thread is not None:
self.thread.running = False
self.thread.join()
self.thread = None
except IOError, e:
print "ioerror", e, e[0]
print dir(e)
if e[0] in (32, 104):
if hasattr(self, "thread") and self.thread is not None:
self.thread.running = False
self.thread.join()
self.thread = None
else:
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):
pass
def main():
window = MainWindow()
window.show()
app.exec_()
arg_parser = ArgParser("ekgplotter")
arg_parser.add_global_group()
client_group = arg_parser.add_client_group()
arg_parser.add_argument(client_group, '-x', "--http_host", default="::",
help='my host, defaults to "::"')
arg_parser.add_argument(client_group, '-X', "--http_port", default=9000,
type=int, help='my port, defaults to 9000')
arg_parser.add_chaosc_group()
arg_parser.add_subscriber_group()
args = arg_parser.finalize()
http_host, http_port = resolve_host(args.http_host, args.http_port, args.address_family)
server = JustAHTTPServer((http_host, http_port), MyHandler)
server.address_family = args.address_family
server.args = args
print "%s: starting up http server on '%s:%d'" % (
datetime.now().strftime("%x %X"), http_host, http_port)
try:
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down server'
server.socket.close()
sys.exit(0)
if ( __name__ == '__main__' ):