Posts: 183
Threads: 71
Joined: Oct 2018
Oct-26-2018, 09:36 PM
(This post was last modified: Oct-28-2018, 01:14 PM by ebolisa.)
Hi,
I'm trying to stop a wav file from playing when a button is pressed but I just cannot get it right.
Any help is appeciated. This' my test code:
#!/usr/bin/python
import commands, os, signal, time
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
pushbutton = 23
buttonstate = True
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BCM) # Use physical pin numbering
GPIO.setup(pushbutton, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set pin 10 to be an input pin and set initial value to be pulled low (off)
p = os.getpid()
file = 'music.wav'
def song():
command = 'mplayer -softvol -volume 5 %s 1>/dev/null 2>&1' % file
os.system(command)
def kill():
buttonstate = GPIO.input(pushbutton)
if buttonstate == False:
print('Killing pid')
time.sleep(0.3)
os.kill(p, signal.SIGKILL)
if __name__ == '__main__':
song()
while True:
kill()
Posts: 536
Threads: 0
Joined: Feb 2018
Oct-26-2018, 10:17 PM
(This post was last modified: Oct-26-2018, 10:22 PM by woooee.)
Use psutil def killtree(pid, including_parent=True):
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
print "child", child
child.kill()
if including_parent:
parent.kill() ## this program
pid=os.getpid()
if some_condition:
killtree(pid)
Posts: 183
Threads: 71
Joined: Oct 2018
Thank you, your code worked as well but my main issue is that I want the song to stop playing when the push button is pressed. Now the song only stops when CTR-C and the push button are pressed. My intentions are to eliminate the KB from the loop. Here's the test code modified:
#!/usr/bin/python
import commands, os, psutil, signal, threading, time
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
pushbutton = 23 #GPIO23
buttonstate = True
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BCM) # Use GPIO numbering
GPIO.setup(pushbutton, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set line as input pin and set initial value to be pulled high (on)
file = 'music.wav'
def song():
command = 'mplayer -softvol -volume 4 %s 1>/dev/null 2>&1' % file
os.system(command)
def killtree(pid, including_parent = True):
parent = psutil.Process(pid)
for child in parent.children(recursive = True):
print "child", child
child.kill()
if including_parent:
parent.kill() ## this program
if __name__ == '__main__':
song()
while True:
buttonstate = GPIO.input(pushbutton)
pid = os.getpid()
if buttonstate == False:
print('Killing pid')
time.sleep(0.3) #debounce delay
killtree(pid)
Posts: 536
Threads: 0
Joined: Feb 2018
Oct-27-2018, 08:04 PM
(This post was last modified: Oct-27-2018, 08:05 PM by woooee.)
You continually overlay the variable pid under the while True. os.getpid returns the last pid started, and if some system or other program started later, then you are killing that program. Call os.getpid() once as the very first statement executed in the program.
I do not know if you can kill an os.system process (I don't use it). You can kill a subprocess process (see POpen kill at https://pymotw.com/3/subprocess/index.html ). I personally prefer multiprocessing (see Terminating Processes at https://pymotw.com/3/multiprocessing/bas...-processes ). """ this uses psutil
. It can also be used
"""
import multiprocessing
import os
import psutil
import time
def killtree(pid, including_parent=True):
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
print("child", child)
child.kill()
if including_parent:
parent.kill() ## this program
def print_numbers():
ctr = 0
for x in range(1000):
ctr +=1
print ctr
time.sleep(0.5)
pid=os.getpid()
## substitute mplayer here
mp = multiprocessing.Process(target=print_numbers)
mp.start()
p= psutil.Process(mp.pid)
print 'pid =', pid, p
print "status", mp.is_alive()
time.sleep(5)
if mp.is_alive():
print("terminate")
mp.terminate()
mp.join()
else:
print "already terminated"
print 'pid =', pid, p
print "status", mp.is_alive()
killtree(pid)
Posts: 183
Threads: 71
Joined: Oct 2018
Well, the wav file is hard to kill. It only dies with CTR-C which I cannot use.
Your code returns the python pid and not the mplayer's.
This' the modified code:
import multiprocessing
import os
import psutil
import time
from subprocess import check_output
file = 'music.wav'
def killtree(pid, including_parent=True):
parent = psutil.Process(pid)
for child in parent.children(recursive=True):
print("child", child)
child.kill()
if including_parent:
parent.kill() ## this program
def song():
command = 'mplayer -softvol -volume 1 %s 1>/dev/null 2>&1' % file
os.system(command)
pid=os.getpid() ##this sketch's pid!!
mp = multiprocessing.Process(target=song)
mp.start()
p= psutil.Process(mp.pid)
print 'pid =', pid, p
print "status", mp.is_alive()
time.sleep(0.5)
if mp.is_alive():
print("terminate")
mp.terminate()
mp.join()
else:
print "already terminated"
print 'pid =', pid, p
print "status", mp.is_alive()
killtree(pid)
Posts: 536
Threads: 0
Joined: Feb 2018
Can't help you further as you insist on using os.system, instead of subprocess of multiprocessing, which I know nothing about
Posts: 183
Threads: 71
Joined: Oct 2018
Oct-28-2018, 01:12 PM
(This post was last modified: Oct-28-2018, 01:13 PM by ebolisa.)
Thanks for introducing me to multiprossesing. I finally got it working. Not sure if it's the best way of doing it but here's my final code.
import RPi.GPIO as GPIO
import time, os, signal, playsong
from multiprocessing import Process
from subprocess import check_output
buttonpin = 23 #GPIO23
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(buttonpin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
m_pid = 0
def play():
'''play music from playsong.py '''
playsong.song()
def get_pid():
'''gets mplayer's actual pid'''
global m_pid
m_pid = int(check_output(["pidof","-s","mplayer"]))
print "mplayer's pid: ", m_pid
def kill_pid(pid):
'''used to kill mplayer's pid'''
os.kill(pid, signal.SIGKILL)
def button():
'''check if button is pressed'''
while True:
input_state = GPIO.input(buttonpin)
if input_state == False:
print 'on'
time.sleep(0.3) #debounce
kill_pid(m_pid)
if __name__ == '__main__':
p1 = Process(target=play)
p1.start()
p2 = Process(target=button)
p2.start()
p3 = Process(target=get_pid)
p3.start()
p1.join()
p2.join()
p3.join()
|