intermediate commit

This commit is contained in:
Stefan Kögl 2014-05-25 15:52:40 +02:00
parent b123160470
commit f3477757c2
20 changed files with 1377 additions and 1226 deletions

View File

@ -15,17 +15,17 @@ set -g terminal-overrides 'xterm*:smcup@:rmcup@'
new-session -s 'csession' new-session -s 'csession'
attach-session -t 'csession' attach-session -t 'csession'
new-window -n 'socat-ekg-merle' -t 'csession:3' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-merle-out,b115200,user=stefan' new-window -n 'socat-ekg-merle' -t 'csession:3' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-merle-out,b115200,user=sarah'
new-window -n 'socat-ekg-uwe' -t 'csession:4' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-out,b115200,user=stefan' new-window -n 'socat-ekg-uwe' -t 'csession:4' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-out,b115200,user=sarah'
new-window -n 'socat-ekg-bjoern' -t 'csession:2' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-out,b115200,user=stefan' new-window -n 'socat-ekg-bjoern' -t 'csession:2' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-out,b115200,user=sarah'
new-window -n 'socat-pulse-merle' -t 'csession:6' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-merle-out,b115200,user=stefan' new-window -n 'socat-pulse-merle' -t 'csession:6' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-merle-out,b115200,user=sarah'
new-window -n 'socat-pulse-uwe' -t 'csession:7' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-out,b115200,user=stefan' new-window -n 'socat-pulse-uwe' -t 'csession:7' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-out,b115200,user=sarah'
new-window -n 'socat-pulse-bjoern' -t 'csession:5' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-out,b115200,user=stefan' new-window -n 'socat-pulse-bjoern' -t 'csession:5' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-out,b115200,user=sarah'
new-window -n 'socat-ehealth-merle' -t 'csession:9' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-out,b115200,user=stefan' new-window -n 'socat-ehealth-merle' -t 'csession:9' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-out,b115200,user=sarah'
new-window -n 'socat-ehealth-uwe' -t 'csession:10' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-out,b115200,user=stefan' new-window -n 'socat-ehealth-uwe' -t 'csession:10' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-out,b115200,user=sarah'
new-window -n 'socat-ehealth-bjoern' -t 'csession:8' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-out,b115200,user=stefan' new-window -n 'socat-ehealth-bjoern' -t 'csession:8' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-out,b115200,user=sarah'
new-window -n 'ekg2osc-merle' -t 'csession:11' 'ekgmerle -D /tmp/ekg2osc-merle-out' new-window -n 'ekg2osc-merle' -t 'csession:11' 'ekgmerle -D /tmp/ekg2osc-merle-out'
new-window -n 'ekg2osc-uwe' -t 'csession:12' 'ekguwe -D /tmp/ekg2osc-uwe-out' new-window -n 'ekg2osc-uwe' -t 'csession:12' 'ekguwe -D /tmp/ekg2osc-uwe-out'
@ -39,17 +39,17 @@ new-window -n 'ehealth2osc-merle' -t 'csession:17' 'sleep 1 && ehealthmerle -
new-window -n 'ehealth2osc-uwe' -t 'csession:18' 'sleep 1 && ehealthuwe -D /tmp/ehealth2osc-uwe-out' new-window -n 'ehealth2osc-uwe' -t 'csession:18' 'sleep 1 && ehealthuwe -D /tmp/ehealth2osc-uwe-out'
new-window -n 'ehealth2osc-bjoern' -t 'csession:19' 'sleep 1 && ehealthbjoern -D /tmp/ehealth2osc-bjoern-out' new-window -n 'ehealth2osc-bjoern' -t 'csession:19' 'sleep 1 && ehealthbjoern -D /tmp/ehealth2osc-bjoern-out'
new-window -n 'test-ekg-merle' -t 'csession:21' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-merle-in' new-window -n 'test-ekg-merle' -t 'csession:21' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-merle-in'
new-window -n 'test-ekg-uwe' -t 'csession:22' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-uwe-in' new-window -n 'test-ekg-uwe' -t 'csession:22' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-uwe-in'
new-window -n 'test-ekg-bjoern' -t 'csession:20' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-bjoern-in' new-window -n 'test-ekg-bjoern' -t 'csession:20' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-bjoern-in'
new-window -n 'test-pulse-merle' -t 'csession:24' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-merle-in' new-window -n 'test-pulse-merle' -t 'csession:24' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-merle-in'
new-window -n 'test-pulse-uwe' -t 'csession:25' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-uwe-in' new-window -n 'test-pulse-uwe' -t 'csession:25' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-uwe-in'
new-window -n 'test-pulse-bjoern' -t 'csession:23' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-bjoern-in' new-window -n 'test-pulse-bjoern' -t 'csession:23' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-bjoern-in'
new-window -n 'test-ehealth-merle' -t 'csession:27' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-merle-in' new-window -n 'test-ehealth-merle' -t 'csession:27' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-merle-in'
new-window -n 'test-ehealth-uwe' -t 'csession:28' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-uwe-in' new-window -n 'test-ehealth-uwe' -t 'csession:28' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-uwe-in'
new-window -n 'test-ehealth-bjoern' -t 'csession:26' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-bjoern-in' new-window -n 'test-ehealth-bjoern' -t 'csession:26' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-bjoern-in'
select-window -t 'csession:2' select-window -t 'csession:2'

View File

@ -10,6 +10,28 @@
<height>606</height> <height>606</height>
</rect> </rect>
</property> </property>
<property name="font">
<font>
<family>Monospace</family>
<pointsize>14</pointsize>
<italic>true</italic>
</font>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGraphicsView" name="graphics_view">
<property name="minimumSize">
<size>
<width>785</width>
<height>580</height>
</size>
</property>
<property name="palette"> <property name="palette">
<palette> <palette>
<active> <active>
@ -425,61 +447,13 @@
</disabled> </disabled>
</palette> </palette>
</property> </property>
<property name="font">
<font>
<family>Monospace</family>
<pointsize>14</pointsize>
<italic>true</italic>
</font>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGraphicsView" name="graphics_view">
<property name="minimumSize">
<size>
<width>785</width>
<height>580</height>
</size>
</property>
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>true</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</item> </item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>4</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'dump_grabber.ui' # Form implementation generated from reading ui file 'dump_grabber.ui'
# #
# Created: Wed Apr 16 22:18:59 2014 # Created: Tue May 13 06:55:09 2014
# by: PyQt4 UI code generator 4.10.3 # by: PyQt4 UI code generator 4.10.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -27,6 +27,19 @@ class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow")) MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(811, 606) MainWindow.resize(811, 606)
font = QtGui.QFont()
font.setFamily(_fromUtf8("Monospace"))
font.setPointSize(14)
font.setItalic(True)
MainWindow.setFont(font)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.graphics_view = QtGui.QGraphicsView(self.centralwidget)
self.graphics_view.setMinimumSize(QtCore.QSize(785, 580))
palette = QtGui.QPalette() palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)
@ -163,23 +176,11 @@ class Ui_MainWindow(object):
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
MainWindow.setPalette(palette) self.graphics_view.setPalette(palette)
self.centralwidget = QtGui.QWidget(MainWindow) self.graphics_view.setAutoFillBackground(False)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.graphics_view = QtGui.QGraphicsView(self.centralwidget)
self.graphics_view.setMinimumSize(QtCore.QSize(785, 580))
self.graphics_view.setAutoFillBackground(True)
self.graphics_view.setObjectName(_fromUtf8("graphics_view")) self.graphics_view.setObjectName(_fromUtf8("graphics_view"))
self.horizontalLayout.addWidget(self.graphics_view) self.horizontalLayout.addWidget(self.graphics_view)
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout.addLayout(self.horizontalLayout)
spacerItem1 = QtGui.QSpacerItem(20, 4, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem1)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)

View File

@ -1,7 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of chaosc and psychosis # This file is part of chaosc and psychosis
# #
# chaosc is free software: you can redistribute it and/or modify # chaosc is free software: you can redistribute it and/or modify
@ -21,24 +20,20 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging
import os import os
import os.path import os.path
import Queue
import re import re
import select
import socket
import sys import sys
import threading
import time
from datetime import datetime from datetime import datetime
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
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 PyQt4.QtNetwork import QTcpServer, QTcpSocket, QUdpSocket, QHostAddress
from dump_grabber.dump_grabber_ui import Ui_MainWindow from dump_grabber.dump_grabber_ui import Ui_MainWindow
from psylib.mjpeg_streaming_server import MjpegStreamingServer
try: try:
from chaosc.c_osc_lib import OSCMessage, decode_osc from chaosc.c_osc_lib import OSCMessage, decode_osc
@ -68,7 +63,7 @@ class ColumnTextStorage(TextStorage):
self.column_width = column_width self.column_width = column_width
self.line_height = line_height self.line_height = line_height
self.graphics_scene = scene self.graphics_scene = scene
self.num_lines, self.offset = divmod(775, self.line_height) self.num_lines, self.offset = divmod(768, self.line_height)
def init_columns(self): def init_columns(self):
for x in range(self.column_count): for x in range(self.column_count):
@ -102,7 +97,7 @@ class ExclusiveTextStorage(TextStorage):
self.column_width = column_width self.column_width = column_width
self.line_height = line_height self.line_height = line_height
self.graphics_scene = scene self.graphics_scene = scene
self.num_lines, self.offset = divmod(775, self.line_height) self.num_lines, self.offset = divmod(576, self.line_height)
def init_columns(self): def init_columns(self):
color = self.colors[0] color = self.colors[0]
@ -125,10 +120,17 @@ class ExclusiveTextStorage(TextStorage):
text_item.setY(iy * self.line_height) text_item.setY(iy * self.line_height)
class MainWindow(QtGui.QMainWindow, Ui_MainWindow): class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None, columns=3, column_exclusive=False): def __init__(self, args, parent=None, columns=3, column_exclusive=False):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
self.args = args
self.setupUi(self) self.setupUi(self)
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
self.http_server.listen(port=args.http_port)
self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.graphics_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.graphics_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True) self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True)
@ -140,178 +142,78 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
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.graphics_scene.setFont(self.default_font) 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.column_width = 775 / columns self.column_width = 775 / columns
self.text_storage = ExclusiveTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene) self.text_storage = ExclusiveTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
#self.text_storage = ColumnTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
self.text_storage.init_columns() self.text_storage.init_columns()
self.osc_sock = QUdpSocket(self)
logger.info("osc bind localhost %d", args.client_port)
self.osc_sock.bind(QHostAddress("127.0.0.1"), args.client_port)
self.osc_sock.readyRead.connect(self.got_message)
self.osc_sock.error.connect(self.handle_osc_error)
msg = OSCMessage("/subscribe")
msg.appendTypedArg("localhost", "s")
msg.appendTypedArg(args.client_port, "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.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
#self.add_text(0, "foo bar")
self.regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
def closeEvent(self, event):
msg = OSCMessage("/unsubscribe")
msg.appendTypedArg("localhost", "s")
msg.appendTypedArg(self.args.client_port, "i")
msg.appendTypedArg(self.args.authenticate, "s")
self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
def handle_osc_error(self, error):
logger.info("osc socket error %d", error)
def add_text(self, column, text): def add_text(self, column, text):
self.text_storage.add_text(column, text) self.text_storage.add_text(column, text)
def render(self): def render_image(self):
image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32_Premultiplied) 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.setRenderHints(QtGui.QPainter.RenderHint(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing), True) 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() painter.end()
return image buf = QBuffer()
buf.open(QIODevice.WriteOnly)
image.save(buf, "JPG", 80)
image_data = buf.data()
return image_data
def got_message(self):
class OSCThread(threading.Thread): while self.osc_sock.hasPendingDatagrams():
def __init__(self, args): data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
super(OSCThread, self).__init__() try:
self.args = args osc_address, typetags, args = decode_osc(data, 0, len(data))
self.running = True except Exception:
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)
logger.info("starting up osc receiver on '%s:%d'", self.client_address[0], self.client_address[1])
self.subscribe_me()
def subscribe_me(self):
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.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 return
logger.info("unsubscribing from '%s:%d'", 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: try:
reads, writes, errs = select.select([self.osc_sock], [], [], 0.01) actor, text = self.regex.match(osc_address).groups()
except Exception, 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))
queue.put_nowait((osc_address, messages))
except Exception, e:
pass
else:
pass
self.unsubscribe_me()
logger.info("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.hide()
self.send_response(200)
self.send_header("Content-Type", "multipart/x-mixed-replace; boundary=--aaboundary")
self.end_headers()
event_loop = QtCore.QEventLoop()
last_frame = time.time() - 1.
frame_rate = 16.0
frame_length = 1. / frame_rate
regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
while 1:
event_loop.processEvents()
app.sendPostedEvents(None, 0)
while 1:
try:
osc_address, args = queue.get_nowait()
print osc_address
except Queue.Empty:
break
else:
try:
actor, text = regex.match(osc_address).groups()
if actor == "merle":
window.add_text(0, "%s = %s" % (text, ", ".join([str(i) for i in args])))
if actor == "uwe":
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: except AttributeError:
pass pass
now = time.time()
delta = now - last_frame
if delta > frame_length:
last_frame = now
img = window.render()
buffer = QBuffer()
buffer.open(QIODevice.WriteOnly)
img.save(buffer, "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
time.sleep(0.01)
return
except (KeyboardInterrupt, SystemError):
if hasattr(self, "thread") and self.thread is not None:
self.thread.running = False
self.thread.join()
self.thread = None
except IOError, 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: else:
pass if actor == "merle":
self.add_text(0, "%s = %s" % (text, ", ".join([str(i) for i in args])))
elif actor == "uwe":
class JustAHTTPServer(HTTPServer): self.add_text(1, "%s = %s" % (text, ", ".join([str(i) for i in args])))
pass elif actor == "bjoern":
self.add_text(2, "%s = %s" % (text, ", ".join([str(i) for i in args])))
return True
def main(): def main():
@ -327,13 +229,10 @@ def main():
args = arg_parser.finalize() args = arg_parser.finalize()
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)
window = MainWindow(args)
#window.show()
app.exec_()
server = JustAHTTPServer((http_host, http_port), MyHandler)
server.address_family = args.address_family
server.args = args
logger.info("starting up http server on '%s:%d'", http_host, http_port)
server.serve_forever()
if ( __name__ == '__main__' ): if ( __name__ == '__main__' ):
main() main()

View File

@ -0,0 +1,312 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# This file is part of sensors2osc package
#
# sensors2osc is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# sensors2osc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with sensors2osc. If not, see <http://www.gnu.org/licenses/>.
#
# found the mjpeg part here, thanks for the nice code :)
# http://hardsoftlucid.wordpress.com/2013/04/11/mjpeg-server-for-webcam-in-python-with-opencv/
# the osc integration stuff is implemented by me
#
# Copyright (C) 2014 Stefan Kögl
from __future__ import absolute_import
from chaosc.argparser_groups import *
from chaosc.lib import logger, resolve_host
from datetime import datetime
from operator import attrgetter
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
from PyQt4.QtNetwork import QTcpServer, QTcpSocket, QUdpSocket, QHostAddress
from PyQt4.QtGui import QPixmap
import logging
import numpy as np
import os.path
import pyqtgraph as pg
from pyqtgraph.widgets.PlotWidget import PlotWidget
import Queue
import re
import select
import socket
import threading
import time
from psylib.mjpeg_streaming_server import MjpegStreamingServer
try:
from chaosc.c_osc_lib import OSCMessage, decode_osc
except ImportError as e:
logging.exception(e)
from chaosc.osc_lib import OSCMessage, decode_osc
def get_steps(pulse_rate, rate):
beat_length = 60. / pulse_rate
steps_pre = int(beat_length / rate) + 1
used_sleep_time = beat_length / steps_pre
steps = int(beat_length / used_sleep_time)
return steps, used_sleep_time
class Generator(object):
def __init__(self, pulse=92, delta=0.08):
self.count = 0
self.pulse = 92
self.delta = delta
self.steps = get_steps(self.pulse, delta / 2)
def __call__(self):
while 1:
value = random.randint(0, steps)
if self.count < int(steps / 100. * 20):
value = random.randint(0,20)
elif self.count < int(steps / 100. * 30):
value = random.randint(20, 30)
elif self.count < int(steps / 100. * 40):
value = random.randint(30,100)
elif self.count < int(steps / 2.):
value = random.randint(100,200)
elif self.count == int(steps / 2.):
value = 255
elif self.count < int(steps / 100. * 60):
value = random.randint(100, 200)
elif self.count < int(steps / 100. * 70):
value = random.randint(50, 100)
elif self.count < int(steps / 100. * 80):
value = random.randint(20, 50)
elif self.count <= steps:
value = random.randint(0,20)
elif self.count >= steps:
self.count = 0
self.count += 1
yield value
def retrigger(self):
self.count = self.steps / 2
class Actor(object):
def __init__(self, name, num_data, color, ix, max_actors, actor_height):
self.name = name
self.num_data = num_data
self.color = color
self.ix = ix
self.max_actors = max_actors
self.actor_height = actor_height
self.updated = 0
self.offset = ix * actor_height
self.data = np.array([self.offset] * num_data)
self.head = 0
self.pre_head = 0
self.plotItem = pg.PlotCurveItem(pen=pg.mkPen(color, width=3), name=name)
self.plotPoint = pg.ScatterPlotItem(pen=pg.mkPen("w", width=5), brush=pg.mkBrush(color), size=5)
def __str__(self):
return "<Actor name:%r, active=%r, position=%r>" % (self.name, self.active, self.head)
__repr__ = __str__
def add_value(self, value):
dp = self.head
self.data[dp] = value / self.max_actors + self.offset
self.pre_head = dp
self.head = (dp + 1) % self.num_data
self.updated += 1
def fill_missing(self, count):
dp = self.head
for i in range(count):
self.data[dp] = self.offset
dp = (dp + 1) % self.num_data
self.updated += 1
self.pre_head = (dp - 1) % self.num_data
self.head = dp
def render(self):
self.plotItem.setData(y=self.data, clear=True)
self.plotPoint.setData(x=[self.pre_head], y = [self.data[self.pre_head]])
class EkgPlotWidget(PlotWidget):
def __init__(self, args, parent=None):
super(EkgPlotWidget, self).__init__(parent)
self.args = args
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
self.http_server.listen(port=args.http_port)
self.osc_sock = QUdpSocket(self)
logger.info("osc bind localhost %d", args.client_port)
self.osc_sock.bind(QHostAddress("127.0.0.1"), args.client_port)
self.osc_sock.readyRead.connect(self.got_message)
self.osc_sock.error.connect(self.handle_osc_error)
msg = OSCMessage("/subscribe")
msg.appendTypedArg("localhost", "s")
msg.appendTypedArg(args.client_port, "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.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
self.num_data = 100
self.hide()
self.showGrid(False, False)
self.setYRange(0, 255)
self.setXRange(0, self.num_data)
self.resize(768, 576)
colors = ["r", "g", "b"]
ba = self.getAxis("bottom")
bl = self.getAxis("left")
ba.setTicks([])
bl.setTicks([])
ba.hide()
bl.hide()
self.active_actors = list()
self.actors = dict()
self.lengths1 = [0]
self.max_value = 255
actor_names = ["merle", "uwe", "bjoern" ]
self.max_actors = len(actor_names)
self.actor_height = self.max_value / self.max_actors
for ix, (actor_name, color) in enumerate(zip(actor_names, colors)):
self.add_actor(actor_name, self.num_data, color, ix, self.max_actors, self.actor_height)
self.set_positions()
self.ekg_regex = re.compile("^/(.*?)/ekg$")
self.ctl_regex = re.compile("^/plot/(.*?)$")
self.updated_actors = set()
self.new_round()
def add_actor(self, actor_name, num_data, color, ix, max_actors, actor_height):
actor_obj = Actor(actor_name, num_data, color, ix, max_actors, actor_height)
self.actors[actor_name] = actor_obj
self.addItem(actor_obj.plotItem)
self.addItem(actor_obj.plotPoint)
self.active_actors.append(actor_obj)
def set_positions(self):
for ix, actor_obj in enumerate(self.active_actors):
actor_obj.plotItem.setPos(0, ix * 2)
actor_obj.plotPoint.setPos(0, ix * 2)
def active_actor_count(self):
return self.max_actors
def new_round(self):
for ix, actor in enumerate(self.active_actors):
actor.updated = 0
def update_missing_actors(self):
liste = sorted(self.active_actors, key=attrgetter("updated"))
max_values = liste[-1].updated
if max_values == 0:
# handling no signal
for actor in self.active_actors:
actor.add_value(0)
return
for ix, actor in enumerate(self.active_actors):
diff = max_values - actor.updated
if diff > 0:
for i in range(diff):
actor.add_value(0)
def update(self, osc_address, value):
res = self.ekg_regex.match(osc_address)
if res:
actor_name = res.group(1)
actor_obj = self.actors[actor_name]
actor_obj.add_value(value)
def render(self):
for ix, actor in enumerate(self.active_actors):
actor.render()
def closeEvent(self, event):
msg = OSCMessage("/unsubscribe")
msg.appendTypedArg("localhost", "s")
msg.appendTypedArg(self.args.client_port, "i")
msg.appendTypedArg(self.args.authenticate, "s")
self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
def handle_osc_error(self, error):
logger.info("osc socket error %d", error)
def render_image(self):
self.update_missing_actors()
self.render()
exporter = pg.exporters.ImageExporter.ImageExporter(self.plotItem)
exporter.parameters()['width'] = 768
img = exporter.export(toBytes=True)
buf = QBuffer()
buf.open(QIODevice.WriteOnly)
img.save(buf, "JPG", 75)
JpegData = buf.data()
self.new_round()
return JpegData
def got_message(self):
while self.osc_sock.hasPendingDatagrams():
data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
try:
osc_address, typetags, args = decode_osc(data, 0, len(data))
except Exception, e:
logger.exception(e)
return
else:
self.update(osc_address, args[0])
return True
def main():
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()
args.http_host, args.http_port = resolve_host(args.http_host, args.http_port, args.address_family)
qtapp = QtGui.QApplication([])
widget = EkgPlotWidget(args)
qtapp.exec_()
if __name__ == '__main__':
main()

View File

@ -30,7 +30,7 @@ setup(
# predefined extension points, e.g. for plugins # predefined extension points, e.g. for plugins
entry_points = """ entry_points = """
[console_scripts] [console_scripts]
ekgplotter = ekgplotter.main:main ekgplotter = ekgplotter.main_qt:main
""", """,
# pypi metadata # pypi metadata
author = "Stefan Kögl", author = "Stefan Kögl",

View File

@ -28,6 +28,7 @@ import time
import sys import sys
from chaosc.argparser_groups import ArgParser from chaosc.argparser_groups import ArgParser
from chaosc.lib import logger
try: try:
@ -47,8 +48,8 @@ class Platform(object):
def connect(self): def connect(self):
print "connect serial" logger.info("connect serial")
print "waiting for the device %r to come up" % self.args.device logger.info("waiting for the device %r to come up", self.args.device)
self.serial_sock = serial.Serial() self.serial_sock = serial.Serial()
self.serial_sock.port = self.args.device self.serial_sock.port = self.args.device
self.serial_sock.baudrate = 115200 self.serial_sock.baudrate = 115200
@ -57,7 +58,7 @@ class Platform(object):
try: try:
self.serial_sock.open() self.serial_sock.open()
except (serial.serialutil.SerialException, os.error), e: except (serial.serialutil.SerialException, os.error), e:
print "serial error", e logger.exception(e)
time.sleep(0.5) time.sleep(0.5)
pass pass
else: else:
@ -66,12 +67,12 @@ class Platform(object):
def close(self): def close(self):
if self.serial_sock is not None: if self.serial_sock is not None:
print "close serial" logger.info("close serial")
self.serial_sock.close() self.serial_sock.close()
def reconnect(self): def reconnect(self):
print "reconnect serial" logger.info("reconnect serial")
self.close() self.close()
self.connect() self.connect()

View File

@ -39,20 +39,19 @@ def main():
#print repr(data) #print repr(data)
except (socket.error, serial.serialutil.SerialException), msg: except (socket.error, serial.serialutil.SerialException), msg:
# got disconnected? # got disconnected?
print "serial socket error!!!", msg logger.exception(msg)
platform.reconnect() platform.reconnect()
print "data", repr(data)
try: try:
airFlow, emg, temp = data.split(";") airFlow, emg, temp = data.split(";")
except ValueError, e: except ValueError, msg:
print e logger.exception(msg)
continue continue
try: try:
airFlow = int(airFlow) airFlow = int(airFlow)
except ValueError, e: except ValueError, msg:
print e logger.exception(msg)
continue continue
try: try:
@ -60,14 +59,14 @@ def main():
osc_message.appendTypedArg(airFlow, "i") osc_message.appendTypedArg(airFlow, "i")
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote) platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
except socket.error, msg: except socket.error, msg:
print "cannot connect to chaosc", msg logger.exception(msg)
continue continue
try: try:
emg = int(emg) emg = int(emg)
except ValueError, e: except ValueError, msg:
print e logger.exception(msg)
continue continue
try: try:
@ -75,14 +74,14 @@ def main():
osc_message.appendTypedArg(emg, "i") osc_message.appendTypedArg(emg, "i")
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote) platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
except socket.error, msg: except socket.error, msg:
print "cannot connect to chaosc", msg logger.exception(msg)
continue continue
try: try:
temp = int(temp) temp = int(temp)
except ValueError, e: except ValueError, msg:
print e logger.exception(msg)
continue continue
try: try:
@ -90,7 +89,7 @@ def main():
osc_message.appendTypedArg(temp, "i") osc_message.appendTypedArg(temp, "i")
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote) platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
except socket.error, msg: except socket.error, msg:
print "cannot connect to chaosc", msg logger.exception(msg)
continue continue

View File

@ -51,11 +51,11 @@ def main():
except TypeError, e: except TypeError, e:
continue continue
if msg_count >= 20: #if msg_count >= 20:
logger.info("value = %d", t) # logger.info("value = %d", t)
msg_count = 0 # msg_count = 0
else: #else:
msg_count += 1 # msg_count += 1
try: try:
osc_message = OSCMessage("/%s/ekg" % actor) osc_message = OSCMessage("/%s/ekg" % actor)

View File

@ -29,7 +29,6 @@ import datetime
try: try:
from chaosc.c_osc_lib import OSCMessage from chaosc.c_osc_lib import OSCMessage
except ImportError as e: except ImportError as e:
print(e)
from chaosc.osc_lib import OSCMessage from chaosc.osc_lib import OSCMessage
@ -48,7 +47,7 @@ class Forwarder(object):
def close(self): def close(self):
"""Close all resources and unpublish service""" """Close all resources and unpublish service"""
print "%s: closing..." % (self.device, ) logger.info("%s: closing...", self.device)
self.serial.close() self.serial.close()
@ -58,7 +57,6 @@ class EHealth2OSC(Forwarder):
def handle_read(self, osc_sock): def handle_read(self, osc_sock):
data = self.serial.readline()[:-2] data = self.serial.readline()[:-2]
print repr(data)
try: try:
airFlow, emg, temp = data.split(";") airFlow, emg, temp = data.split(";")
except ValueError: except ValueError:
@ -106,7 +104,7 @@ class RingBuffer(object):
self.head = (self.head + 1) % self.length self.head = (self.head + 1) % self.length
def getData(self): def getData(self):
print "getData", self.ring_buf, self.head #print "getData", self.ring_buf, self.head
data = list() data = list()
for i in range(7, 1, -1): for i in range(7, 1, -1):
value = self.ring_buf[(self.head - i) % self.length] value = self.ring_buf[(self.head - i) % self.length]
@ -146,7 +144,7 @@ class Pulse2OSC(Forwarder):
osc_message.appendTypedArg(heart_rate, "i") osc_message.appendTypedArg(heart_rate, "i")
osc_message.appendTypedArg(o2, "i") osc_message.appendTypedArg(o2, "i")
osc_sock.sendall(osc_message.encode_osc()) osc_sock.sendall(osc_message.encode_osc())
print "heartbeat", datetime.datetime.now(), heart_signal #print "heartbeat", datetime.datetime.now(), heart_signal
self.heartbeat_on = True self.heartbeat_on = True
elif pulse == 1 and self.heartbeat_on: elif pulse == 1 and self.heartbeat_on:
#print "off heartbeat", datetime.datetime.now(), heart_signal #print "off heartbeat", datetime.datetime.now(), heart_signal

View File

@ -41,7 +41,7 @@ class RingBuffer(object):
self.head = (self.head + 1) % self.length self.head = (self.head + 1) % self.length
def getData(self): def getData(self):
print "getData", self.ring_buf, self.head #print "getData", self.ring_buf, self.head
data = list() data = list()
for i in range(self.length + 1, 1, -1): for i in range(self.length + 1, 1, -1):
value = self.ring_buf[(self.head - i) % self.length] value = self.ring_buf[(self.head - i) % self.length]
@ -52,7 +52,7 @@ class RingBuffer(object):
raise ValueError("not complete - reset ringbuffer") raise ValueError("not complete - reset ringbuffer")
data.append(value) data.append(value)
if data[0] != 0x0 or data[1] != 0xff: if data[0] != 0x0 or data[1] != 0xff:
print "issue", data #print "issue", data
self.reset() self.reset()
self.ring_buf[0] = 0 self.ring_buf[0] = 0
self.head = 1 self.head = 1
@ -77,7 +77,7 @@ def main():
continue continue
except (socket.error, serial.serialutil.SerialException), msg: except (socket.error, serial.serialutil.SerialException), msg:
# got disconnected? # got disconnected?
print "serial socket error!!!", msg logger.exception(msg)
platform.reconnect() platform.reconnect()
try: try:
@ -91,8 +91,8 @@ def main():
if t == 0: if t == 0:
try: try:
heart_signal, heart_rate, o2, pulse = buf.getData() heart_signal, heart_rate, o2, pulse = buf.getData()
except ValueError, e: except ValueError, msg:
print e logger.exception(msg)
continue continue
if pulse == 245 and not heartbeat_on: if pulse == 245 and not heartbeat_on:
@ -103,12 +103,12 @@ def main():
osc_message.appendTypedArg(heart_rate, "i") osc_message.appendTypedArg(heart_rate, "i")
osc_message.appendTypedArg(o2, "i") osc_message.appendTypedArg(o2, "i")
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote) platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
print "on heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse #print "on heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
except socket.error, msg: except socket.error, msg:
print "cannot connect to chaosc" logger.exception(msg)
continue continue
elif pulse == 1 and heartbeat_on: elif pulse == 1 and heartbeat_on:
print "off heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse #print "off heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
heartbeat_on = False heartbeat_on = False
try: try:
osc_message = OSCMessage("/%s/heartbeat" % actor) osc_message = OSCMessage("/%s/heartbeat" % actor)
@ -117,7 +117,7 @@ def main():
osc_message.appendTypedArg(o2, "i") osc_message.appendTypedArg(o2, "i")
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote) platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
except socket.error, msg: except socket.error, msg:
print "cannot connect to chaosc" logger.exception(msg)
continue continue

Binary file not shown.

View File

@ -15,61 +15,18 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QSplitter" name="splitter"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="minimumSize"> <item>
<size> <widget class="QTableView" name="text_list"/>
<width>768</width> </item>
<height>576</height> <item>
</size> <widget class="QTextEdit" name="text_preview">
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>576</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListView" name="text_list">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>576</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>576</height>
</size>
</property>
</widget>
<widget class="KRichTextWidget" name="text_preview">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>100</horstretch> <horstretch>100</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>576</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>768</width>
<height>576</height>
</size>
</property>
<property name="palette"> <property name="palette">
<palette> <palette>
<active> <active>
@ -485,11 +442,18 @@
</disabled> </disabled>
</palette> </palette>
</property> </property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
</property>
</widget> </widget>
</widget> </item>
</layout>
</item> </item>
<item> <item>
<widget class="KButtonGroup" name="kbuttongroup"> <widget class="KButtonGroup" name="kbuttongroup">
@ -526,11 +490,6 @@
<extends>QPushButton</extends> <extends>QPushButton</extends>
<header>karrowbutton.h</header> <header>karrowbutton.h</header>
</customwidget> </customwidget>
<customwidget>
<class>KRichTextEdit</class>
<extends>KTextEdit</extends>
<header>krichtextedit.h</header>
</customwidget>
<customwidget> <customwidget>
<class>KButtonGroup</class> <class>KButtonGroup</class>
<extends>QGroupBox</extends> <extends>QGroupBox</extends>
@ -542,16 +501,6 @@
<extends>QPushButton</extends> <extends>QPushButton</extends>
<header>kpushbutton.h</header> <header>kpushbutton.h</header>
</customwidget> </customwidget>
<customwidget>
<class>KTextEdit</class>
<extends>QTextEdit</extends>
<header>ktextedit.h</header>
</customwidget>
<customwidget>
<class>KRichTextWidget</class>
<extends>KRichTextEdit</extends>
<header>krichtextwidget.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'texter4.ui' # Form implementation generated from reading ui file 'edit_dialog.ui'
# #
# Created: Mon Apr 28 21:58:51 2014 # Created: Sat May 17 16:15:38 2014
# by: PyQt4 UI code generator 4.10.3 # by: PyQt4 UI code generator 4.10.3
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -23,32 +23,23 @@ except AttributeError:
def _translate(context, text, disambig): def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig) return QtGui.QApplication.translate(context, text, disambig)
class Ui_TextSorterDialog(object): class Ui_EditDialog(object):
def setupUi(self, TextSorterDialog): def setupUi(self, EditDialog):
TextSorterDialog.setObjectName(_fromUtf8("TextSorterDialog")) EditDialog.setObjectName(_fromUtf8("EditDialog"))
TextSorterDialog.resize(1084, 633) EditDialog.resize(1084, 633)
self.verticalLayout = QtGui.QVBoxLayout(TextSorterDialog) self.verticalLayout = QtGui.QVBoxLayout(EditDialog)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.splitter = QtGui.QSplitter(TextSorterDialog) self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.splitter.setOrientation(QtCore.Qt.Horizontal) self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
self.splitter.setObjectName(_fromUtf8("splitter")) self.text_list = QtGui.QTableView(EditDialog)
self.text_list = QtGui.QListView(self.splitter)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.text_list.sizePolicy().hasHeightForWidth())
self.text_list.setSizePolicy(sizePolicy)
self.text_list.setMinimumSize(QtCore.QSize(200, 576))
self.text_list.setMaximumSize(QtCore.QSize(16777215, 576))
self.text_list.setObjectName(_fromUtf8("text_list")) self.text_list.setObjectName(_fromUtf8("text_list"))
self.text_preview = KRichTextWidget(self.splitter) self.horizontalLayout_2.addWidget(self.text_list)
self.text_preview = QtGui.QTextEdit(EditDialog)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(100) sizePolicy.setHorizontalStretch(100)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.text_preview.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.text_preview.sizePolicy().hasHeightForWidth())
self.text_preview.setSizePolicy(sizePolicy) self.text_preview.setSizePolicy(sizePolicy)
self.text_preview.setMinimumSize(QtCore.QSize(0, 576))
self.text_preview.setMaximumSize(QtCore.QSize(768, 576))
palette = QtGui.QPalette() palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)
@ -186,10 +177,13 @@ class Ui_TextSorterDialog(object):
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush) palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
self.text_preview.setPalette(palette) self.text_preview.setPalette(palette)
self.text_preview.setUndoRedoEnabled(False)
self.text_preview.setReadOnly(True) self.text_preview.setReadOnly(True)
self.text_preview.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
self.text_preview.setObjectName(_fromUtf8("text_preview")) self.text_preview.setObjectName(_fromUtf8("text_preview"))
self.verticalLayout.addWidget(self.splitter) self.horizontalLayout_2.addWidget(self.text_preview)
self.kbuttongroup = KButtonGroup(TextSorterDialog) self.verticalLayout.addLayout(self.horizontalLayout_2)
self.kbuttongroup = KButtonGroup(EditDialog)
self.kbuttongroup.setObjectName(_fromUtf8("kbuttongroup")) self.kbuttongroup.setObjectName(_fromUtf8("kbuttongroup"))
self.horizontalLayout = QtGui.QHBoxLayout(self.kbuttongroup) self.horizontalLayout = QtGui.QHBoxLayout(self.kbuttongroup)
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
@ -206,14 +200,12 @@ class Ui_TextSorterDialog(object):
self.remove_button.setObjectName(_fromUtf8("remove_button")) self.remove_button.setObjectName(_fromUtf8("remove_button"))
self.horizontalLayout.addWidget(self.remove_button) self.horizontalLayout.addWidget(self.remove_button)
self.verticalLayout.addWidget(self.kbuttongroup) self.verticalLayout.addWidget(self.kbuttongroup)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.retranslateUi(TextSorterDialog) self.retranslateUi(EditDialog)
QtCore.QMetaObject.connectSlotsByName(TextSorterDialog) QtCore.QMetaObject.connectSlotsByName(EditDialog)
def retranslateUi(self, TextSorterDialog): def retranslateUi(self, EditDialog):
TextSorterDialog.setWindowTitle(_translate("TextSorterDialog", "Form", None)) EditDialog.setWindowTitle(_translate("EditDialog", "Form", None))
self.remove_button.setText(_translate("TextSorterDialog", "Remove", None)) self.remove_button.setText(_translate("EditDialog", "Remove", None))
from PyKDE4.kdeui import KButtonGroup, KArrowButton, KPushButton, KRichTextWidget from PyKDE4.kdeui import KButtonGroup, KArrowButton, KPushButton

BIN
texter/texter/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@ -0,0 +1,5 @@
P6
# CREATOR: GIMP PNM Filter Version 1.1
16 16
255
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>哪尿蝌<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>èň揪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E7A78D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><14><><EFBFBD>晻暢吵yyy挝<79><E68C9D><EFBFBD><EFBFBD>eee悙愔种<E68494><E7A78D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>tttQQQ<51><51><EFBFBD>种謑llbbb篌蟥è厖區^^ⅱ<><E285B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ppp鞍<70>666鬃讞棗<E8AE9E>畘~~破歧珑览纀bb┅<62><E29485><EFBFBD><EFBFBD>行协<E8A18C><E58D8F><EFBFBD><EFBFBD>圹勖妹666噜鄅hh适蕯敂牋<E69582><E7898B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>佑羽痧<E7BEBD><E797A7><EFBFBD>滗湫行<E6B9AB><E8A18C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E68FAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>悙悽ⅱ<E682BD><E285B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -60,7 +60,8 @@ class MjpegStreamingServer(QTcpServer):
super(MjpegStreamingServer, self).__init__(parent) super(MjpegStreamingServer, self).__init__(parent)
self.server_address = server_address self.server_address = server_address
self.newConnection.connect(self.start_streaming) self.newConnection.connect(self.start_streaming)
self.widget = parent self.widget = parent.live_text
self.win_id = self.widget.winId()
self.sockets = list() self.sockets = list()
self.img_data = None self.img_data = None
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
@ -72,6 +73,7 @@ class MjpegStreamingServer(QTcpServer):
self.coords = parent.live_text_rect() self.coords = parent.live_text_rect()
def handle_request(self): def handle_request(self):
print "foo"
sock = self.sender() sock = self.sender()
logger.info("handle_request: %s %d", sock.peerAddress(), sock.peerPort()) logger.info("handle_request: %s %d", sock.peerAddress(), sock.peerPort())
sock_id = id(sock) sock_id = id(sock)
@ -89,7 +91,7 @@ class MjpegStreamingServer(QTcpServer):
resource, ext, http_version = self.regex.match(line).groups() resource, ext, http_version = self.regex.match(line).groups()
logger.info("resource=%r, ext=%r, http_version=%r", resource, ext, http_version) logger.info("resource=%r, ext=%r, http_version=%r", resource, ext, http_version)
except AttributeError: except AttributeError:
loggging.info("no matching request - sending 404 not found") logger.info("no matching request - sending 404 not found")
sock.write("HTTP/1.1 404 Not Found\r\n") sock.write("HTTP/1.1 404 Not Found\r\n")
else: else:
if ext == "ico": if ext == "ico":
@ -159,10 +161,11 @@ class MjpegStreamingServer(QTcpServer):
if not self.stream_clients: if not self.stream_clients:
return return
pixmap = QPixmap.grabWidget(self.widget.live_text, *self.coords) #pixmap = QPixmap.grabWidget(self.widget, QtCore.QRect(10, 10, 768, 576))
pixmap = QPixmap.grabWindow(self.win_id, 5, 5, 768, 576)
buf = QBuffer() buf = QBuffer()
buf.open(QIODevice.WriteOnly) buf.open(QIODevice.WriteOnly)
pixmap.save(buf, "JPG", 25) pixmap.save(buf, "JPG", 30)
self.img_data = buf.data() self.img_data = buf.data()
len_data = len(self.img_data) len_data = len(self.img_data)
array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, self.img_data)) array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, self.img_data))
@ -368,7 +371,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
self.args = args self.args = args
self.is_streaming = False self.is_streaming = False
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
self.live_center_action = None self.live_center_action = None
self.preview_center_action = None self.preview_center_action = None
self.live_size_action = None self.live_size_action = None
@ -392,6 +395,10 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.is_auto_publish = False self.is_auto_publish = False
self.setupUi(self) self.setupUi(self)
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
self.live_text.setLineWrapMode(QtGui.QTextEdit.LineWrapMode(QtGui.QTextEdit.FixedPixelWidth))
self.live_text.setLineWrapColumnOrWidth(768)
self.font = QtGui.QFont("monospace", self.default_size) self.font = QtGui.QFont("monospace", self.default_size)
self.font.setStyleHint(QtGui.QFont.TypeWriter) self.font.setStyleHint(QtGui.QFont.TypeWriter)
@ -431,6 +438,12 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.show() self.show()
def getPreviewCoords(self):
public_rect = self.preview_text.geometry()
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
return global_rect.x(), global_rect.y()
def filter_editor_actions(self): def filter_editor_actions(self):
disabled_action_names = [ disabled_action_names = [
"action_to_plain_text", "action_to_plain_text",
@ -620,14 +633,14 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.dialog.exec_() self.dialog.exec_()
def live_text_rect(self): def live_text_rect(self):
return 3, 3, 768, 576 return 5, 5, 768, 576
def stop_streaming(self): def stop_streaming(self):
self.is_streaming = False self.is_streaming = False
self.http_server.stop() self.http_server.stop()
def start_streaming(self): def start_streaming(self):
self.http_server.listen(port=9009) self.http_server.listen(port=self.args.http_port)
self.is_streaming = True self.is_streaming = True
def focusChanged(self, old, new): def focusChanged(self, old, new):
@ -814,6 +827,8 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.dialog.setButtons(KDialog.Close) self.dialog.setButtons(KDialog.Close)
self.dialog_widget = EditDialog(self.dialog) self.dialog_widget = EditDialog(self.dialog)
self.dialog.setMainWidget(self.dialog_widget) self.dialog.setMainWidget(self.dialog_widget)
pos_x, pos_y = self.getPreviewCoords()
self.dialog.move(pos_x, self.pos().y())
self.dialog.exec_() self.dialog.exec_()
self.fill_combo_box() self.fill_combo_box()

View File

@ -16,7 +16,7 @@ class TextModel(QtCore.QAbstractTableModel):
return len(self.text_db) return len(self.text_db)
def columnCount(self, parent=QtCore.QModelIndex()): def columnCount(self, parent=QtCore.QModelIndex()):
return 2 return 1
def data(self, index, role): def data(self, index, role):
if not index.isValid() or \ if not index.isValid() or \
@ -26,12 +26,9 @@ class TextModel(QtCore.QAbstractTableModel):
row = index.row() row = index.row()
column = index.column() column = index.column()
if role == QtCore.Qt.DisplayRole: if role == QtCore.Qt.DisplayRole:
return self.text_db[row][column] print "data", row, column, row
return QtCore.QVariant(self.text_db[row][column])
#return "foo bar" #return "foo bar"
elif role == QtCore.Qt.ForegroundRole:
return QtGui.QBrush(QtCore.Qt.black)
elif role == QtCore.Qt.BackgroundRole:
return QtGui.QBrush(QtCore.Qt.white)
return QtCore.QVariant() return QtCore.QVariant()
@ -45,6 +42,12 @@ class TextModel(QtCore.QAbstractTableModel):
return QtCore.QVariant() return QtCore.QVariant()
def setData(self, index, value, role): def setData(self, index, value, role):
if (not index.isValid() or
not 0 <= index.row() < self.rowCount()):
print "setData index not valid"
return False
print "setData", index.row(), index.column(), value, role
if role == QtCore.Qt.EditRole: if role == QtCore.Qt.EditRole:
text = value.toString() text = value.toString()
@ -52,14 +55,16 @@ class TextModel(QtCore.QAbstractTableModel):
return False return False
else: else:
self.text_db[index.row()][index.column()] = text self.text_db[index.row()][index.column()] = text
return True return True
else:
return False
def flags(self, index): def flags(self, index):
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled if index.column() == 0:
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled
else:
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
def supportedDropActions(self):
return QtCore.Qt.MoveAction
def insertRows(self, row, count, parent=QtCore.QModelIndex()): def insertRows(self, row, count, parent=QtCore.QModelIndex()):
self.beginInsertRows(parent, row, row+count+1) self.beginInsertRows(parent, row, row+count+1)

1
texter/texter/texter.html Symbolic link
View File

@ -0,0 +1 @@
index.html

View File

@ -62,8 +62,8 @@ class Ui_MainWindow(object):
self.horizontalLayout = QtGui.QHBoxLayout() self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.live_text = KRichTextWidget(self.centralwidget) self.live_text = KRichTextWidget(self.centralwidget)
self.live_text.setMinimumSize(QtCore.QSize(775, 582)) self.live_text.setMinimumSize(QtCore.QSize(778, 586))
self.live_text.setMaximumSize(QtCore.QSize(775, 582)) self.live_text.setMaximumSize(QtCore.QSize(778, 586))
palette = QtGui.QPalette() palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)
@ -116,8 +116,8 @@ class Ui_MainWindow(object):
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.preview_text.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.preview_text.sizePolicy().hasHeightForWidth())
self.preview_text.setSizePolicy(sizePolicy) self.preview_text.setSizePolicy(sizePolicy)
self.preview_text.setMinimumSize(QtCore.QSize(300, 582)) self.preview_text.setMinimumSize(QtCore.QSize(300, 586))
self.preview_text.setMaximumSize(QtCore.QSize(775, 582)) self.preview_text.setMaximumSize(QtCore.QSize(778, 586))
palette = QtGui.QPalette() palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern) brush.setStyle(QtCore.Qt.SolidPattern)