0

Using a Raspberry Pi and some push buttons I want to control video playback. When someone presses a button the corresponding video plays. The buttons work great. When you press a button the video plays, but when you press a different button or the same button it opens the video without closing the video that was currently playing. I've been searching a while to fix this. I'm pretty new to Python so please keep it as simple as possible. In the code below I'm trying to accomplish it using multithreading. I wasn't able to close the thread though when another thread starts. I am able to close the video after it plays for 10 seconds, but I can't move the quit command anywhere else to close other videos: playSippycup.stdin.write('q')

Here's are the errors I'm currently receiving:

Unhandled exception in thread started by <function shoppingcart at 0xb6c566f0>Playing Sippycup

Unhandled exception in thread started by <function dodgeballs at 0xb6c56670>
Traceback (most recent call last):
    File "./labmural2.py", line 53, in dodgeballs
    playDodgeballs.stdin.write('q')
NameError: global name 'playDodgeballs' is not defined
Traceback (most recent call last):
  File "./labmural2.py", line 71, in shoppingcart
    playShoppingcart.stdin.write('q')
NameError: global name 'playShoppingcart' is not defined

Thanks so much for any help you guys can offer!

#!/usr/bin/env python

import RPi.GPIO as GPIO
import subprocess
import time
import thread

GPIO.setmode (GPIO.BCM)
GPIO.setwarnings (False)

GPIO.setup(9, GPIO.IN)
GPIO.setup(10, GPIO.IN)
GPIO.setup(11, GPIO.IN)

GPIO.setup(17, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)

def sippycup( name ):

        global playSippycup

        while True:
                if GPIO.input(11) == True:
                        print name
                        time.sleep(1)
                        playSippycup=subprocess.Popen(['omxplayer','Desktop/videos/sippycup.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playSippycup.stdin.write('q')

                if GPIO.input(9) == True:
                        playSippycup.stdin.write('q')

                if GPIO.input(10) == True:
                        playSippycup.stdin.write('q')

def dodgeballs( name ):

        global playDodgeballs

        while True:
                if GPIO.input(9) == True:
                        print name
                        time.sleep(1)
                        playDodgeballs=subprocess.Popen(['omxplayer','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playDodgeballs.stdin.write('q')

                if GPIO.input(10) == True:
                        playDodgeballs.stdin.write('q')

                if GPIO.input(11) == True:
                        playDodgeballs.stdin.write('q')

def dodgeballs( name ):

        global playDodgeballs

        while True:
                if GPIO.input(9) == True:
                        print name
                        time.sleep(1)
                        playDodgeballs=subprocess.Popen(['omxplayer','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playDodgeballs.stdin.write('q')

                if GPIO.input(10) == True:
                        playDodgeballs.stdin.write('q')

                if GPIO.input(11) == True:
                        playDodgeballs.stdin.write('q')

def shoppingcart( name ):

        global playShoppingcart

         while True:
                if GPIO.input(10) == True:
                        print name
                        time.sleep(1)
                        playShoppingcart=subprocess.Popen(['omxplayer','Desktop/videos/shoppingcart.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                        time.sleep(10)
                        playShoppingcart.stdin.write('q')

            if GPIO.input(9) == True:
                        playShoppingcart.stdin.write('q')

            if GPIO.input(11) == True:
                        playShoppingcart.stdin.write('q')

thread.start_new_thread( sippycup, ("Playing Sippycup",) )
thread.start_new_thread( dodgeballs, ("Playing Dodgeballs",) )
thread.start_new_thread( shoppingcart, ("Playing Shoppingcart",) )

while True:
            pass

GPIO.cleanup()

NEW EDIT:

#!/usr/bin/python

from time import sleep
import RPi.GPIO as GPIO
import subprocess
import time
import thread

GPIO.setmode (GPIO.BCM)
GPIO.setwarnings (False)

GPIO.setup(9, GPIO.IN)
GPIO.setup(10, GPIO.IN)
GPIO.setup(11, GPIO.IN)

GPIO.setup(17, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)

def welcome_loop():
    while True:
            global playProcess
            x = 1
            print "LOOPING"
            time.sleep(.5)
            playProcess=subprocess.Popen(['omxplayer','-b','Desktop/videos/loop/loop.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
            time.sleep(10)
            playProcess.stdin.write('q')
            x += 1

def videos():
    while True:
            if GPIO.input(9):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Sippycup"
                    sippycup_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/sippycup.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    sippycup_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

            if GPIO.input(10):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Dodgeballs"
                    dodgeballs_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/dodgeballs.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    dodgeballs_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

            if GPIO.input(11):
                    print "STOP LOOP"
                    time.sleep(.5)
                    playProcess.stdin.write('q')
                    time.sleep(.5)
                    print "Play Shoppingcart"
                    shoppingcart_video=subprocess.Popen(['omxplayer','-b','Desktop/videos/shoppingcart.mp4'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, close_fds=True)
                    time.sleep(10)
                    shoppingcart_video.stdin.write('q')
                    time.sleep(.5)
                    welcome_loop()

thread.start_new_thread( videos, () )
thread.start_new_thread( welcome_loop, () )

while True:
    pass

GPIO.cleanup()

ERROR:

Unhandled exception in thread started by Traceback (most recent call last): File "./labmural2.py", line 28, in welcome_loop playProcess.stdin.write('q') IOError: [Errno 32] Broken pipe

jmcclaire
  • 175
  • 3
  • 4
  • 16

1 Answers1

2

NameError: global name 'playDodgeballs' is not defined means that you are trying to use playDodgeballs before it is defined playDodgeballs = ...

I would simplify your code by removing all globals and threads. subprocess.Popen runs a separate process; it doesn't block your main thread:

names = 'sippycup', 'dodgeballs', 'shoppingcart'
movies = ['Desktop/videos/{name}.mp4'.format(name=name) for name in names]
players = [Player(movie=movie) for movie in movies]
player = players[0]

setup_io() # GPIO setup
while True:
    for key in get_key_events(): # get GPIO input
        if key == '0':
           player = players[0]
        elif key == 'space':
           player.toggle() # pause/unpause
        elif key == 'enter':
           player.start()
        ...

where Player is a simple wrapper around omxplayer subprocess:

import logging
from subprocess import Popen, PIPE, DEVNULL

logger = logging.getLogger(__name__)

class Player:
    def __init__(self, movie):
       self.movie = movie
       self.process = None

    def start(self):
        self.stop()
        self.process = Popen(['omxplayer', self.movie], stdin=PIPE,
                             stdout=DEVNULL, close_fds=True, bufsize=0)
        self.process.stdin.write(start_command) # start playing

    def stop(self):
        p = self.process
        if p is not None:
           try:
               p.stdin.write(quit_command) # send quit command
               p.terminate()
               p.wait() # -> move into background thread if necessary
           except EnvironmentError as e:
               logger.error("can't stop %s: %s", self.movie, e)
           else:
               self.process = None

    def toggle(self):
        p = self.process
        if p is not None:
           try:
               p.stdin.write(toggle_command) # pause/unpause
           except EnvironmentError as e:
               logger.warning("can't toggle %s: %s", self.movie, e)

Specify appropriate start_command, quit_command, toggle_command. You could define different methods depending on what commands omxplayer understands and what commands you need.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • I understand what is going on, but don't know how to implement it with the code I have. Thanks for trying to help though. – jmcclaire Oct 17 '14 at 17:43
  • @jmcclaire: If it is overwhelming; don't try to implement all at once. Implement, test one function/method at a time. For example, `setup_io()` is just the code before `def sippycup()` in your question. Do you understand how to implement `get_key_events()`: get input and interpret it as `space` or `enter` keys are released (you could expand it to detect when a key is pressed, multiple keys at once, `Ctrl`, etc if necessary). What is not clear about `Player.stop` method? Does `omxplayer` accept a `quit_command` command e.g., `q` or something? – jfs Oct 17 '14 at 19:31
  • No I've never done get_key_events(). I'm pretty new to Python. Most of my experience is with Arduino. setup_io() needs to be defined. How do I define it? omxplayer accepts 'q' as a quit. I am able to quit the video in the format my original code is above, but can't use the command elsewhere because it says it wasn't defined yet. :/ – jmcclaire Oct 21 '14 at 21:08
  • How do I import DEVNULL? – jmcclaire Oct 21 '14 at 21:18
  • On Python 2 you might need to emulate it [`DEVNULL = open(os.devnull, 'r+b', 0)`](http://stackoverflow.com/a/11270665/4279). btw, you could've searched `subprocess devnull` in google to get similar code in the first link. – jfs Oct 22 '14 at 01:57
  • Thanks. Trust me, I Googled for a while. I don't like being that lazy person that just asks for the answer. – jmcclaire Oct 22 '14 at 13:33
  • It still doesn't work for me. Do I need DEVNULL? I tried searching for what it does and didn't understand it's purpose. Sooo frustrating...hitting wall after wall... – jmcclaire Oct 22 '14 at 13:43
  • I added an edit below my original code above where I tried to implement the code you wrote. Does that look at all close? – jmcclaire Oct 22 '14 at 13:43
  • @jmcclaire: Have you tried to follow the link from my previous comment? `DEVNULL` is the answer to "How to hide output of subprocess in Python 2.7" question. You need it if you want to hide/discard output from a subprocess. If you don't mind seeing output from omxplayer process in terminal then you don't need it. – jfs Oct 22 '14 at 15:30
  • @jmcclaire: no, it doesn't look close. My code suggests only one event loop (only one loop that has `get_key_event()` -- the function that *you* should implement using whatever means necessary to get what keys are currently pressed/released). – jfs Oct 22 '14 at 15:34
  • I changed the last edit to my newest code. I'm VERY close to what I want it to do. The only problem is I'm getting the broken pipe error. If I can fix that I'm done! Thanks for the help! – jmcclaire Oct 22 '14 at 18:44