Merge pull request #2 from CodePanter/master

Improved performance by replacing the 'threading', 'socket' and 'Queu…
This commit is contained in:
JanKlopper 2016-03-15 19:30:26 +01:00
commit aca73688c0

View file

@ -5,36 +5,38 @@ Inspired by the PixelFlut beamer on eth0:winter 2016 and
code from https://github.com/defnull/pixelflut/ code from https://github.com/defnull/pixelflut/
""" """
__version__ = 0.1 __version__ = 0.2
__author__ = "Jan Klopper <jan@underdark.nl>" __author__ = "Jan Klopper <jan@underdark.nl>"
import pygame import pygame
import socket
import struct import struct
import Queue
import threading
import time import time
from gevent import spawn, socket, monkey
from gevent.server import DatagramServer
from gevent.queue import Queue
monkey.patch_all()
UDP_IP = "127.0.0.1"
UDP_PORT= 5005
def main(): def main():
"""Runs a pixelvloed server""" """Runs a pixelvloed server"""
PixelVloed() PixelVloed(':%d' %(UDP_PORT)).serve_forever()
class PixelVloed(object): class Canvas(object):
"""PixelVloed server class""" """PixelVloed server class"""
def __init__(self, udp_ip="127.0.0.1", udp_port=5005, debug=False): def __init__(self, queue, debug=False):
"""Init the pixelVloed server""" """Init the pixelVloed server"""
self.debug = debug self.debug = debug
self.pixeloffset = 2 self.pixeloffset = 2
self.fps = 30 self.fps = 30
self.screen = None self.screen = None
self.udp_ip = UDP_IP
self.udp_port = UDP_PORT
self.canvas() self.canvas()
self.set_title() self.set_title()
self.queue = Queue.Queue() self.queue = queue
self.receivethread = threading.Thread(target=self.Socket, args=(udp_ip, udp_port), name="ReceiveThread")
self.drawthread = threading.Thread(target=self.CanvasUpdate, name="DrawThread")
self.receivethread.start()
self.drawthread.start()
@staticmethod @staticmethod
def set_title(text=None): def set_title(text=None):
@ -44,7 +46,7 @@ class PixelVloed(object):
title += ' ' + text title += ' ' + text
pygame.display.set_caption(title) pygame.display.set_caption(title)
def canvas(self, width=768, height=1366): def canvas(self, width=1366, height=768):
"""Init the pygame canvas""" """Init the pygame canvas"""
pygame.init() pygame.init()
self.screen = pygame.display.set_mode((width, height)) self.screen = pygame.display.set_mode((width, height))
@ -57,17 +59,8 @@ class PixelVloed(object):
"""Print a pixel to the screen""" """Print a pixel to the screen"""
self.screen.set_at((x, y), (r, g, b, a)) self.screen.set_at((x, y), (r, g, b, a))
def Socket(self, ipaddress, port):
"""Sets up a udp listening socket and handles the incoming binary data"""
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((ipaddress, port))
while True:
self.queue.put(sock.recvfrom(1024))
self.queue.join()
def CanvasUpdate(self): def CanvasUpdate(self):
"""Updates the screen according to self.fps"""
lasttime = time.time() lasttime = time.time()
while True: while True:
currenttime = time.time() currenttime = time.time()
@ -77,26 +70,38 @@ class PixelVloed(object):
lasttime = time.time() lasttime = time.time()
def Draw(self): def Draw(self):
data, addr = self.queue.get() """Draws pixels specified in the received packages in the queue"""
self.queue.task_done() try:
preamble = struct.unpack_from("<?", data)[0] data = self.queue.get()
protocol = struct.unpack_from("<B", data, 1)[0] except:
pixellength = 7 #xx,yy,r,g,b raise
if preamble: else:
preamble = struct.unpack_from("<?", data)[0]
protocol = struct.unpack_from("<B", data, 1)[0]
pixellength = 7 #xx,yy,r,g,b
if preamble:
pixellength = 8 #xx,yy,r,g,b,a
pixelcount = (len(data)-1) / pixellength
if self.debug: if self.debug:
print 'rgba mode for %s:%d' % (addr[0], addr[1]) print '%d pixels received, protocol V %d ' % (pixelcount, protocol)
pixellength = 8 #xx,yy,r,g,b,a for i in xrange(0, pixelcount):
pixelcount = (len(data)-1) / pixellength pixel = struct.unpack_from(
if self.debug: ("<2H4B" if preamble else "<2H3B"),
print '%d pixels received, protocol V %d ' % (pixelcount, protocol) data,
for i in xrange(0, pixelcount): self.pixeloffset + (i*pixellength))
pixel = struct.unpack_from( if self.debug:
("<2H4B" if preamble else "<2H3B"), print pixel
data, self.Pixel(*pixel)
self.pixeloffset + (i*pixellength))
if self.debug: class PixelVloed(DatagramServer):
print pixel """PixelVloed server class"""
self.Pixel(*pixel) queue = Queue()
pixelcanvas = Canvas(queue)
__request_processing_greenlet = spawn(pixelcanvas.CanvasUpdate)
def handle(self, data, address):
"""Is called by the DataGramServer whenever a package is received"""
self.queue.put(data)
if __name__ == '__main__': if __name__ == '__main__':
main() main()