问题
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
回答1:
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.
来源:https://stackoverflow.com/questions/26389648/how-to-open-and-close-omxplayer-python-raspberry-pi-while-playing-video