Search code examples
raspberry-pigpioomxplayer

GPIO combine with OMX Player to play different videos when triggered


I have a simple project where I want to combine a motion sensor to play certain video files. So normally in an infinitive loop I want to play a flickering video and if the motion sensor is triggered I want to stop the flickering video and select a scary one. See the following code.

import RPi.GPIO as GPIO
import time
from omxplayer.player import OMXPlayer
from random import randint

#
def main():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17,GPIO.IN)

    flicks = ("/home/pi/halloween/flicks/tv_noise_1.mp4")
    scares = ("/home/pi/halloween/scares/tv_noise_kitten_zombie_2.mp4")

    omxc = OMXPlayer(flicks)
    state = 0 # set initial state as 0
    while True:
        i = GPIO.input(17)
        if(not omxc.is_playing()):
            omxc = OMXPlayer(flicks)
        if(state != i): # change in state detected
            omxc.quit()
            omxc = OMXPlayer(scares)
            time.sleep(35) # wait as long as this video lasts

        state = i

if __name__ == '__main__':
    main() 

However, I keep getting the error:

Traceback (most recent call last):
  File "scare_old.py", line 29, in <module>
    main()
  File "scare_old.py", line 20, in main
    if(not omxc.is_playing()):
  File "<decorator-gen-90>", line 2, in is_playing
  File "/home/pi/.local/lib/python2.7/site-packages/omxplayer/player.py", line 48, in wrapped
    raise OMXPlayerDeadError('Process is no longer alive, can\'t run command')
omxplayer.player.OMXPlayerDeadError: Process is no longer alive, can't run command

What exactly is the problem? I mean the process should run because I'm just starting it before?


Solution

  • import RPi.GPIO as GPIO
    import time
    from random import randint
    from subprocess import Popen, PIPE
    import os
    import logging
    
    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=open(os.devnull, 'r+b', 0), close_fds=True, bufsize=0)
        self.process.stdin.write("b") # start playing
    
    def stop(self):
        p = self.process
        if p is not None:
            try:
                p.stdin.write("q") # 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)
    
    def main():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17,GPIO.IN)
    
    first = ("/home/pi/halloween/flicks/tv_noise_no_sound_short_1.mp4")
    second = ("/home/pi/halloween/scares/tv_noise_the_ring_2.mp4")
    
    first_player = Player(movie=first)
    second_player = Player(movie=second)
    
    second_player.start()
    second_player.stop()
    
    first_player.start()
    print "start the first/standard clip"
    
    state = GPIO.input(17)  # get the initial state of PIR
    while True:
        i = GPIO.input(17)
        if((first_player.process.poll() is not None) and (second_player.process.poll() is not None)):
                print "restart flickering video"
                first_player.stop()
                second_player.stop()
                first_player.start()
        if(state != i): # change in state detected
            print "state has changed"
            print "scaring video played"
            if(second_player.process.poll() is not None):
                first_player.stop()
                second_player.start()
        state = i
    
    if __name__ == '__main__':
        main()