Skip to content

Instantly share code, notes, and snippets.

@bikubi
Last active March 26, 2021 12:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bikubi/21a1fa9553d96fadbb98e51741ae6e21 to your computer and use it in GitHub Desktop.
Save bikubi/21a1fa9553d96fadbb98e51741ae6e21 to your computer and use it in GitHub Desktop.
Control a web radio stream on a Raspi with GPIO, a button and an LED.
#!/usr/bin/env python
import subprocess as sp
import RPi.GPIO as g
import time
import os
# see http://cyfta.com/?p=8480
# & listen to WFMU! http://wfmu.org
# "constants", change these.
# raspi pinout
pin_button = 4
pin_led = 17
# seconds before we accept another input
# (give mplayer time to terminate)
input_delay = 5
# run 'id' to see these
user_name = 'pi'
user_id = 1000
user_gid = 1000
user_home_dir = '/home/pi'
# do not change the URL.
player_cmd = ["mplayer", "-quiet", "http://stream0.wfmu.org/freeform-high.aac"]
print "setting up pins..."
g.setmode(g.BCM)
g.setup(pin_button, g.IN)
g.setup(pin_led, g.OUT)
# run subprocess as different, non-root user
# https://stackoverflow.com/a/6037494
def demote ():
def result ():
global user_name, user_id, user_gid
#os.setgid(1001)
# we need initgroups to set all groups, including 'audio'
os.initgroups(user_name, user_gid)
os.setuid(user_id)
print 'demoted %d %d' % (os.getgid(), os.getuid())
return result
env = os.environ.copy()
env[ 'HOME' ] = user_home_dir
env[ 'LOGNAME' ] = user_name
env[ 'PWD' ] = user_home_dir
env[ 'USER' ] = user_name
p = None
blink = False
wait = 0
def play ():
global p, blink, player_cmd, user_home_dir
if p is not None and p.poll() is None:
print "seems to be playing. terminating!"
p.terminate()
if p is None or p.poll() is not None:
print "play!"
p = sp.Popen(
player_cmd,
preexec_fn = demote(),
cwd = user_home_dir,
env = env
)
def stop ():
global p
print "terminating!"
p.terminate()
# let the led flutter!
def flutter (length, delay):
for x in range(0, length):
g.output(pin_led, g.LOW if x % 2 == 0 else g.HIGH)
time.sleep(delay)
flutter(6, 0.05) # hi!
print "starting polling..."
while True:
poll = p.poll() if p is not None else -1
# we could do this using events...
if g.input(pin_button) == g.HIGH:
# if we are not blocked by a previous input...
if wait == 0:
flutter(6, 0.05)
wait = input_delay
if poll is None:
stop()
else:
play()
else:
# if we're blocked, give visual feedback
flutter(50, 0.02)
blink = not blink if poll is None else False
g.output(pin_led, g.LOW if blink else g.HIGH)
wait = wait - 1 if wait > 0 else 0
time.sleep(1) # adjust this to poll for input faster
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment