Using Python API to trigger events in script with DMX Values

590 views
Skip to first unread message

tim massey

unread,
Aug 13, 2014, 2:00:32 PM8/13/14
to open-l...@googlegroups.com
I am by no means an expert programmer so all help would be gratefully appreciated, thank you in advanced.

Also just to note all my code will be freely available under the GNU General Public License

So I have this script which works perfectly, but I would like to replace the key presses with DMX values, video 1 DMX value 001 video 2 002 and so on

I looked at the ola_recv_dmx.py script but unfortunately it didn't really help me to understand how I might use it in my script.

#!/usr/bin/env python

SCREEN_SIZE
= (1366, 768)
video1
= 'c:\\video\\newtest1.mpg'
video2
= 'c:\\video\\newtest2.mpg'
still1
= 'c:\\video\\red.tga'
still2
= 'c:\\video\\blue.tga'

import pygame
from pygame.locals import *
from sys import exit

pygame
.init()
screen
= pygame.display.set_mode((SCREEN_SIZE), FULLSCREEN, 32)
surface
= pygame.display.set_mode((SCREEN_SIZE), FULLSCREEN, 32)

while True:
       
   
for event in pygame.event.get():
       
if event.type == QUIT:
           
exit()
   
   
if event.type == KEYDOWN:
       
if event.key == K_LEFT:
            movie
= pygame.movie.Movie(video1)
            movie
.play()
            pygame
.display.update()
       
elif event.key == K_RIGHT:
            movie
= pygame.movie.Movie(video2)
            movie
.play()
            pygame
.display.update()
       
elif event.key == K_UP:
            surface
= pygame.image.load(still1).convert()
            screen
.blit(surface, (10, 10))
            pygame
.display.flip()
       
elif event.key == K_DOWN:
            surface
= pygame.image.load(still2).convert()
            screen
.blit(surface, (10, 10))
            pygame
.display.flip()

 

I am guessing that I will have to import something  from the example it says from ola.ClientWrapper import ClientWrapper which I assume is from ClientWrapper.py?  Do I need any other files to communicate with OLA?

I guess will find something to replace event.type == KEYDOWN and event.key == K_LEFT with the relevant code to listen for DMX values but I just not sure what to look for.

Thanks again in advanced any help will be greatly appreciated.

Tim

Simon Newton

unread,
Aug 14, 2014, 11:13:35 AM8/14/14
to open-lighting
On Wed, Aug 13, 2014 at 11:00 AM, tim massey <timm...@gmail.com> wrote:
> I am by no means an expert programmer so all help would be gratefully
> appreciated, thank you in advanced.
>
> Also just to note all my code will be freely available under the GNU General
> Public License
>
> So I have this script which works perfectly, but I would like to replace the
> key presses with DMX values, video 1 DMX value 001 video 2 002 and so on
>
> I looked at the ola_recv_dmx.py script but unfortunately it didn't really
> help me to understand how I might use it in my script.

Take a look at http://docs.openlighting.org/doc/latest/event_driven.html
which I wrote yesterday.

You'll need to figure out how to integrate a socket with pygame's
event framework.

Simon
> --
> The Open Lighting Group: open-l...@googlegroups.com, #openlighting
> (irc.freenode.org)
> To unsubscribe from this group, send email to
> open-lightin...@googlegroups.com
> For more options, visit https://groups.google.com/groups/opt_out?hl=en

tim massey

unread,
Aug 14, 2014, 4:40:59 PM8/14/14
to open-l...@googlegroups.com
Simon

Thank you for you speedy reply I know that you are busy.

So here is importing socket
import socket

clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 9090))
I think I am correct in saying that its Address Family : AF_INET (this is IP version 4 or IPv4) & Type : SOCK_STREAM (this means connection oriented TCP protocol)?? and I guess that I should be listening to port 9090. I am guessing that this socket will have to integrate with the code below some how? but that is unfortunately defiantly beyond my skills.

This I kind of understand
from ola.ClientWrapper import ClientWrapper

wrapper = ClientWrapper()
wrapper.Run()  # event loop is running
but what I don't understand is where I would put the DMX value and address etc I want to listen for?

So to put it all together I think it would look something along there lines?? This is by no means a working script more an outline which hopefully someone can help me fill in the blanks
SCREEN_SIZE = (1366, 768)
video1 = 'c:\\video\\newtest1.mpg'
video2 = 'c:\\video\\newtest2.mpg'
still1 = 'c:\\video\\red.tga'
still2 = 'c:\\video\\blue.tga'

import pygame
from pygame.locals import *
from sys import exit
import socket
from ola.ClientWrapper import ClientWrapper

### DON'T UNDERSTAND HOW THESE INTEGRATE WITH THE OLA CODE
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 9090))

### DON'T UNDERSTAND HOW TO USE THESE SORRY.
wrapper = ClientWrapper()

wrapper.Run()


pygame.init()
screen = pygame.display.set_mode((SCREEN_SIZE), FULLSCREEN, 32)
surface = pygame.display.set_mode((SCREEN_SIZE), FULLSCREEN, 32)

while True:

        if DMX VALUE == 1: ### This is where I need some OLA listerning code but I just don't know what
            movie = pygame.movie.Movie(video1)
            movie.play()
            pygame.display.update()
        elif DMX VALUE == 2:
            movie = pygame.movie.Movie(video2)
            movie.play()
            pygame.display.update()

So where my confusion comes is how I use the wrapper = ClientWrapper()and the wrapper.Run()I don't understand where and or how to look at a value of a DMX channel?

Thank you again any tips or help would be great-fully appreciated and hopefully we can have some working code to put on the events driven page webpage soon.

Tim


On Wednesday, 13 August 2014 19:00:32 UTC+1, tim massey wrote:

tim massey

unread,
Aug 14, 2014, 5:38:40 PM8/14/14
to open-l...@googlegroups.com
So just had a thought and will look at implementing it over the coming few days use ola trigger to write the Dmx value to a file and then read the value from file.

It some thing I understand and think I should be able too do quite easily.

While I figure out the more elegant option of using the python api.

But any help would be greatly appreciated.

Thank you

Tim

Jesse Anderson

unread,
Aug 15, 2014, 12:02:02 AM8/15/14
to open-l...@googlegroups.com
Hey Tim,

I don't know much about Pygame, and I don't think I can help you with the socket-based solution Simon mentioned.  However, I can try to explain an alternative that might be more straightforward. So the OLA client is event-based, so when you call ClientWrapper.Run(), it starts a select server loop to listen for any events that are sent its way.  Your main problem is going to be that your Pygame system is also event-based, and also has a loop running listening for events. These two loops will not be able to run simultaneously in the same thread.  So, what I did when working on a user interface for Python OLA was create an alternative ola client wrapper that inherits from the python thread module.  Here's my code:

https://github.com/jesseanderson/ola-rpiui/blob/master/olalistener.py

First, let's talk about what's happening with OLA in the above code.  I make OLAClient and SelectServer objects, these are the important parts of talking to OLA.  The run() method could be as simple as selectserver.Run().  Mine is more complex to handle cases where the OLA server is not running; if you don't need this functionality, don't worry about it; your program will just throw an exception if it is started while the OLA server is not running. The rest of the methods in this class things I wanted for handling complex OLA calls; you may not need anything like these, I'll go into details in a bit.  The last thing to know is that the main problem with thread safety occurs if you need to retrieve information from OLA and send it back to the UI thread.  If I understand what you need to do, then you might not need this, but if you do, look at the ui_queue and UIEvent in the above code or ask me more questions.

So, if you make something like this OLAListener class, it should be easy to make simple calls to OLA.  Instead of wrapper = ClientWrapper() and wrapper.run(), you'll want wrapper = (YourClientWrapper) and wrapper.run() at the top of your code.  To look at how to send DMX to OLA, I recommend you look at the send_dmx method in the code above--the important parts are: self.selectserver.Execute( lambda:self.client.SendDmx(universe, data, """callback""))--the rest is just to deal with the callback system and sending data back to the UI.  It might make sense to put this in your client wrapper, this way you can bind events from Pygame to simple calls to your clientwrapper without having to deal with the technicalities of the OLA Python API.

I probably didn't do a great job of explaining this, but please take a look at my code and feel free to ask me any questions about it or what I've said here.

Jesse

tim massey

unread,
Aug 15, 2014, 2:20:08 AM8/15/14
to open-l...@googlegroups.com
Jesse

Thank you for you reply I will have a look at this is the coming days. Much appreciated.

Excellent Project buy the way just waiting to get a screen then will be installing it.

Thank you

Tim

tim massey

unread,
Aug 15, 2014, 2:55:13 AM8/15/14
to open-l...@googlegroups.com
Jesse

If it possible when / if you have a moment could you right the most basic python script to print the DMX value for a given channel.

Just wanted to strip it down to the barebones and work up from there.

Thank you

Tim

g.schlmm

unread,
Aug 15, 2014, 7:06:07 AM8/15/14
to open-l...@googlegroups.com
Hi Tim,
here is a simple pygame example using OlaClient and select calls. it
receives dmx and send some random dmx every 3 seconds.

import sys
import select
import array
import random
import pygame
from ola import OlaClient

# let OlaClient create the socket itself
ola_client = OlaClient.OlaClient()
sock = ola_client.GetSocket()

# defining custom events for pygame
DMX_RECEIVE_EVENT = pygame.USEREVENT + 1
SEND_DMX_EVENT_TIMER = pygame.USEREVENT + 2

""" receive the dmx """
def on_dmx(dmx):
print "received!"
# create a pygame event with the dmx values attached
ev = pygame.event.Event(DMX_RECEIVE_EVENT, {'dmx': dmx})
# posting the event
pygame.event.post(ev)

UNIVERSE = 1
# listening for dmx frames
ola_client.RegisterUniverse(UNIVERSE, ola_client.REGISTER, on_dmx)

pygame.init()
size = width, height = 320, 200
speed = [2, 2]
# background color
background = (66, 66, 66)
screen = pygame.display.set_mode(size)

ball = pygame.Surface([10, 10])
ball.fill((255, 255, 255))
ballrect = ball.get_rect()

clock = pygame.time.Clock()

# set a timer to send dmx.
pygame.time.set_timer(SEND_DMX_EVENT_TIMER, 3000)
# dmx frame with 4 channels
DMX_FRAME = array.array('B', [0, 0, 0, 0])

moving = True

while True:
# check for pygame events
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == DMX_RECEIVE_EVENT:
# first channel
if event.dmx[0] > 128:
moving = False
else:
moving = True

# next 3 channel for the ball color
if len(event.dmx) > 3:
ball.fill((event.dmx[1], event.dmx[2], event.dmx[3]))

# send dmx timer reached
elif event.type == SEND_DMX_EVENT_TIMER:
if DMX_FRAME[0] == 0xff:
DMX_FRAME[0] = 0x00
else:
DMX_FRAME[0] = 0xff

# some random rgb value
DMX_FRAME[1] = random.randint(0, 255)
DMX_FRAME[2] = random.randint(0, 255)
DMX_FRAME[3] = random.randint(0, 255)

print "sending dmx", DMX_FRAME
ola_client.SendDmx(UNIVERSE, DMX_FRAME)

if moving:
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]

screen.fill(background)
screen.blit(ball, ballrect)
pygame.display.flip()

# 25 fps
clock.tick(25)

# check if there is something to do
readable, writable, exceptional = select.select([sock], [], [], 0)
if readable:
# tell it ola_client
ola_client.SocketReady()

tim massey

unread,
Aug 15, 2014, 7:11:09 AM8/15/14
to open-l...@googlegroups.com
schlmm

Thank you it much appreciated I will have a look at this as soon as I have a moment works gone a bit crazy.

Thanks again

Tim

tim massey

unread,
Sep 23, 2014, 10:38:04 AM9/23/14
to open-l...@googlegroups.com
schlmm

Thank you again for you help, I have finally had time to have a your script and its perfect so here is my final script.

Its a little rough and ready but its very functional I will be refining it as time goes

Thank you again

Tim

#!/usr/bin/env python

SCREEN_SIZE
= (1920, 1080)
black
= '/home/pi/media/HD_black.jpg'
video1
= '/home/pi/media/newtest1.mpg'
video2
= '/home/pi/media/newtest2.mpg'
still1
= '/home/pi/media/red.tga'
still2
= '/home/pi/media/blue.tga'


import sys
import select
import array
import random
import pygame
from ola import OlaClient

# let OlaClient create the socket itself
ola_client
= OlaClient.OlaClient()
sock
= ola_client.GetSocket()

# defining custom events for pygame
DMX_RECEIVE_EVENT
= pygame.USEREVENT + 1
SEND_DMX_EVENT_TIMER
= pygame.USEREVENT + 2

""" receive the dmx """
def on_dmx(dmx):

       
print ("received!")

       
# create a pygame event with the dmx values attached
        ev
= pygame.event.Event(DMX_RECEIVE_EVENT, {'dmx': dmx})
       
# posting the event
        pygame
.event.post(ev)

UNIVERSE
= 1
# listening for dmx frames
ola_client
.RegisterUniverse(UNIVERSE, ola_client.REGISTER, on_dmx)

pygame
.init()

screen
= pygame.display.set_mode((SCREEN_SIZE), 0, 32)
surface
= pygame.display.set_mode((SCREEN_SIZE), 0, 32)
# background color
background
= (0, 0, 0)



# dmx frame with 4 channels
DMX_FRAME
= array.array('B', [0, 0, 0, 0])

while True:
       
# check for pygame events
       
for event in pygame.event.get():
               
if event.type == pygame.QUIT:
                        sys
.exit()

               
elif event.type == DMX_RECEIVE_EVENT:
                       
# first channel

                       
if event.dmx[0] == 000:
                                pygame
.mouse.set_visible(0)
                                screen
= pygame.display.set_mode((SCREEN_SIZE), $
                                surface
= pygame.image.load(black).convert()
                                screen
.blit(surface, (10, 10))
                                pygame
.display.flip()
                       
elif event.dmx[0] == 001:

                                surface
= pygame.image.load(still1).convert()
                                screen
.blit(surface, (10, 10))
                                pygame
.display.flip()

                       
elif event.dmx[0] == 002:

                                surface
= pygame.image.load(still2).convert()
                                screen
.blit(surface, (10, 10))
                                pygame
.display.flip()



       
# check if there is something to do
Reply all
Reply to author
Forward
0 new messages