2

I have KY040 rotary switcher(encoder) as shown below picture.

enter image description here

It is the scenario that there are 5 radio stations(simple html url) in urls.txt which are read into stations list in radyoCS.py, at every switch(turn) station is changed. I'm using the rotary switch to do that. The radio player is MPlayer which can be run via terminal like mplayer -playlist <url>. playStation(numberOfStation) uses subprocess.Popen(....) to run MPlayer with the given station. It simply switches between the urls. The problem is after 2nd switch the application is stuck. The way is my solution. If you have any better idea, please let me know.

radyoCs.py

import os

import re
import subprocess


### READ RADIO STATIONS FROM FILE AT FIRST ###

playlist = ["m3u", "pls", "asx"]

f = open('urls.txt', 'r')
stations = [line for line in f.readlines()]
f.close()

print('\n'.join(str(p) for p in stations))

### FUNCTIONS ###
def playStation(i):
    os.system("killall mplayer")
    if any(x in stations[i] for x in playlist):
        radioName = 'mplayer ' + '-prefer-ipv4 ' + '-playlist ' + stations[i]
        p = subprocess.Popen(radioName.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    else:
        radioName = 'mplayer ' + '-prefer-ipv4 ' + stations[i]
        p = subprocess.Popen(radioName.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)


    ### the below part is to grap radio station name and track being played and print ###
    for line in p.stdout:
        if line.startswith(('ICY Info:'.encode(), 'Name'.encode())):
            if 'Name'.encode() in line:
                nameStr = str(line)
                searchRadioName = re.search(r'(?<=:\s).*?(?=\\n)', nameStr, re.M | re.I)
                if searchRadioName:
                    print(searchRadioName.group())

            if 'ICY Info:'.encode() in line:
                trackStr = str(line)
                searchTrackName = re.search(r'(?<=\=\').*?(?=\'\;)', trackStr, re.M | re.I)
                if searchTrackName:
                    print(searchTrackName.group())
    return p

main.py

import os
import signal
import time

import RPi.GPIO as GPIO
from time import sleep

import radyoCS


GPIO.setmode(GPIO.BCM)

### PINS ###
CLOCKPIN = 16
DATAPIN = 15
SWITCHPIN = 14

# setup pins
GPIO.setup(CLOCKPIN, GPIO.IN)
GPIO.setup(DATAPIN, GPIO.IN)
GPIO.setup(SWITCHPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)


MIN_LIMIT_CHANNEL = 0
MAX_LIMIT_CHANNEL = 5

# for testing purpose, it is actually 0
counter = 2


try:
    while True:

        pid = os.fork()

        if pid == 0:
            print("i'm child my pid => " + str(os.getpid()) + "my parent => " + str(os.getppid()))
            #radyoCS.playStation(t)
            print(counter)

            ### normally playStation does work, control is takeovered by '''mplayer''' !!!!
            time.sleep(100)
        else:
            ### wait until rotary switcher turns
            GPIO.wait_for_edge(CLOCKPIN, GPIO.FALLING)

            clock = GPIO.input(CLOCKPIN)
            data = GPIO.input(DATAPIN)

            ### stop current child to create new child
            ### stop currently playing radio station to change to new station
            os.kill(pid, signal.SIGKILL)

            print("i'm waiting, value t > " + str(t))

            ### We have 5 radio stations, if data==1 turned counter clokwise, otherwise clockwise
            if data == 1:
                if counter == MIN_LIMIT_CHANNEL:
                    counter = MAX_LIMIT_CHANNEL + 1
                counter -= 1
            else:
                if counter == MAX_LIMIT_CHANNEL:
                    counter = MIN_LIMIT_CHANNEL - 1
                counter += 1


        sleep(0.1)
finally:
    GPIO.cleanup()

urls.txt

http://rss-streaming.co.uk:8062/listen.pls?sid=1
http://142.4.206.137:26284/
http://dir.xiph.org/listen/922068/listen.m3u
http://retroserver.streamr.ru:8043/retro128.m3u
http://stream.funradio.sk:8000/80-90-128.mp3.m3u
http://www.guldkanalen.se/static/streamGK/WMA.asx

Minimal fork() part,

try:
    while True:

        pid = os.fork()

        if pid == 0:
            print("i'm child my pid => " + str(os.getpid()) + "my parent => " + str(os.getppid()))
            #radyoCS.playStation(t)
            print(counter)

            ### normally playStation does work, control is takeovered by '''mplayer''' !!!!
            time.sleep(100)
        else:
            ### wait until rotary switcher turns
            GPIO.wait_for_edge(CLOCKPIN, GPIO.FALLING)

            clock = GPIO.input(CLOCKPIN)
            data = GPIO.input(DATAPIN)

            ### stop current child to create new child
            ### stop currently playing radio station to change to new station
            os.kill(pid, signal.SIGKILL)

            print("i'm waiting, value t > " + str(counter))

            ### We have 5 radio stations, if data==1 turned counter clokwise, otherwise clockwise
        if data == 1:   # counter clokwise
            if counter == MIN_LIMIT_CHANNEL:
                counter = MAX_LIMIT_CHANNEL + 1
            counter -= 1
        else:           # clockwise
            if counter == MAX_LIMIT_CHANNEL:
                counter = MIN_LIMIT_CHANNEL - 1
            counter += 1


        sleep(0.1)
finally:
    GPIO.cleanup()

bumped to the homepage by Community yesterday

This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

0

I have killed the process, but a dead process doesn't disappear from the process table until its parent process performs a task called "reaping" (essentially calling wait(3) for that process to read its exit status). Dead processes that haven't been reaped are called "zombie processes."

When I call several times after some rotations ps --ppid <parent pid>, I see that,

pi@raspberrypi:~ $ ps --ppid 801
  PID TTY          TIME CMD
  815 pts/1    00:00:00 python3.5 <defunct>
  819 pts/1    00:00:00 python3.5 <defunct>
  830 pts/1    00:00:00 python3.5 <defunct>
  831 pts/1    00:00:00 python3.5 <defunct>
  850 pts/1    00:00:00 python3.5 <defunct>

Rule of thumb: Even though the child is killed via another signal or self-annihilation(os.exit(..)), eventually burial procedures must be done by its parent, that is, let the child go to the happy hunting grounds by calling os.wait(...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.