Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Exiting from a file
#1
Hi,

The following code runs on a Raspberry and plays a song in a loop unless a button is pressed which stops the execution and exits file.

The button works as well the loop however, when the loop ends normally (without the use of the button), the line os._exit(1) is not executed causing the file to remain loaded into the memories.

How to I solve it? Also, how do I pass the variables (vol and file) from an external file?

TIA

import RPi.GPIO as GPIO
import time, signal, os
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
file = './sounds/bleep_01.wav'
vol = 5

def play():
    '''play music'''
    for x in range(3):    
        command = 'mplayer -softvol -volume %d %s 1>/dev/null 2>&1' % (vol, file)
        os.system(command)
    os._exit(1) 

def get_pid():
    '''gets mplayer's actual pid'''
    global m_pid
    m_pid = int(check_output(["pidof","-s","mplayer"]))

def kill_pid(pid):
    '''kills mplayer's pid'''
    os.kill(pid, signal.SIGKILL)

def button():
    '''checks if button is pressed'''
    while True:
        input_state = GPIO.input(buttonpin)
        if input_state == False:
            time.sleep(0.3) #debounce
            GPIO.cleanup() 
            kill_pid(m_pid)


if __name__ == '__main__':
  p1 = Process(target=play)
  p1.start()
  p2 = Process(target=get_pid)
  p2.start()
  p3 = Process(target=button)
  p3.start()
  p1.join()
  p2.join()
  p3.join()
Reply
#2
I refactored the code a little bit.
  • one global left
  • lesser imports
  • no multiprocessing
  • put some functions together
  • use of callback
  • use of debouncing
  • use of return value of the process

When you kill a process, the return value of the process is the negative number of the signal.
SIGKILL == 9
You can use edge detection and the return_value of the process.

import time
import os
from signal import SIGKILL
from subprocess import check_output, Popen
from shlex import split # needed for Popen

import RPi.GPIO as GPIO


MPL_COMMAND = 'mplayer -softvol -volume {vol} {file}'


def popen(file, vol)
    command = MPL_COMMAND.format(file=file, vol=vol)
    proc = Popen(split(command), stdout=None, stderr=None)
    return proc.wait()


def gpio_setup(buttonpin):
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(buttonpin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(buttonpin, GPIO.RISING, callback=kill_mplayer, bouncetime=300)
    # I'm not sure, maybe GPIO.RISING must be inverted to GPIO.FALLING
    # I guess you need FALLING, because of the inverted logic of PUD_UP, pull up resistor
    # kill_mplayer is called, when the button is pressed
    # If you want to have a delay of 3 seconds, change the bouncetime to 3000
    # if I remind correct, the callback is called after the bouncetime is over and the
    # button was pressed during this time
    # but I'm not complete sure about it, just try it


def teardown():
    GPIO.cleanup()


def kill_mplayer():
    '''kills mplayer'''
    pid = int(check_output(["pidof","-s","mplayer"]))
    os.kill(pid, SIGKILL)


def main(file, vol=5, buttonpin=23):
    gpio_setup(buttonpin)
    for _ in range(3):
        ret_val = popen(file, vol)
        if ret_val == -SIGKILL:
            break
        elif ret_val != 0:
            print('Some other signal was detected')
    teardown()


if __name__ == '__main__':
    file = './sounds/bleep_01.wav'
    main(file)
Code was not tested nor executed. Was edited in a plain text editor.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#3
@DeaD_EyE thanks for helping out. I'm new to this language so will take me a time to digest the changes you made Blush

The file is now exiting correctly once the loop ends but when the button is pressed, I get the error msg: TypeError: kill_mplayer() takes no arguments (1 given)

The line GPIO.add_event_detect(buttonpin, GPIO.RISING, callback=kill_mplayer, bouncetime=300) is not passing an argument so, I don't understand the error.
Reply
#4
Not sure if is the right way of doing it but added the word 'none' in def kill_mplayer(none):
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Return not exiting function?? rudihammad 3 5,276 Dec-01-2020, 07:11 PM
Last Post: bowlofred
  proc communicate not exiting on python subprocess timeout leoonardoo 0 3,783 Sep-13-2017, 09:54 AM
Last Post: leoonardoo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020