dezmob
dezmob

Reputation: 13

How to start and stop a process using multiprocessing?

I'm trying to code a simple script that will help me to start and stop video playback on multiple Raspberry Pi using mqtt.

This is the first time I'm trying to start and stop subprocess from a python script and I'm having trouble understanding the correct order of operation

there is my code

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

def player(video):
    print("Playing " + video)
    os.system("omxplayer-sync " + video)

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):    
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        p = multiprocessing.Process(target=player, args=[str(msg.payload.decode())])
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("localhost", 1883, 60)

client.loop_forever()

I can successfully start the video but I can't stop it. I'm pretty sure this is due to the fact that the p object is destroyed at the end of the on_message callback but I don't see where I can create my Process elsewhere.


Edit

this is a naive approach using the global keyword

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

videoFile = ""

class GracefulExit:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

    def exit_gracefully(self,signum, frame):
        self.kill_now = True

def player():
    global videoFile
    print("Playing " + videoFile)
    os.system("omxplayer-sync " + videoFile)

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):
    global videoFile
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        videoFile = str(msg.payload.decode())
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

def main():
    app_killer = GracefulExit()
    while not app_killer.kill_now:
        try:
            time.sleep(0.5)
        except BaseException:
            print("Encountered an exeption.")
            break
    print ("End of the program.")

if __name__ == '__main__':
    print("Starting the program")
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("localhost", 1883, 60)
    client.loop_start()
    p = multiprocessing.Process(target=player)
    main()

but I can play the video just once and calling terminate doesn't stop the playback


Edit 2

Now I'm declaring p as a global as suggested, but I can't figure how to start playing a filename that I'm receiving from MQTT subscription

import paho.mqtt.client as mqtt
import multiprocessing, time, signal
import os

def player():
    print("Playing " + "synctest.mp4")
    os.system("omxplayer-sync " + "synctest.mp4")

p = multiprocessing.Process(target=player)

class GracefulExit:
    kill_now = False
    def __init__(self):
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

    def exit_gracefully(self,signum, frame):
        self.kill_now = True

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("player/#")

def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    if msg.topic == "player/PLAY":
        print("p.args= " + p.name)
        videoFile = str(msg.payload.decode())
        #how to put the videoFile into the args given to p ?
        p.start()
    if msg.topic == "player/STOP":
        print("Stopping video")
        print(p, p.is_alive())
        print("Terminating video")
        p.terminate()
        print(p, p.is_alive())

def main():
    app_killer = GracefulExit()
    while not app_killer.kill_now:
        try:
            time.sleep(0.5)
        except BaseException:
            print("Encountered an exeption.")
            break
    print ("End of the program.")

if __name__ == '__main__':
    print("Starting the program")
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect("localhost", 1883, 60)
    client.loop_start()
    main()

Upvotes: 0

Views: 575

Answers (0)

Related Questions