Last active
January 10, 2023 16:47
-
-
Save chew-z/b450199cf629943e134fcc4f25e8d4e0 to your computer and use it in GitHub Desktop.
Simplistic script for playing radio in terminal with mpv underneath
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"id": 0, | |
"station": { | |
"name": "Machine Geist", | |
"url": "http://178.209.52.163:7331/maschinengeist.org.128.aacp" | |
} | |
}, | |
{ | |
"id": 1, | |
"station": { | |
"name": "Freeform Radio the Way it Oughta Be", | |
"url": "http://stream0.wfmu.org/freeform-128k" | |
} | |
}, | |
{ | |
"id": 2, | |
"station": { | |
"name": "Jazz Radio New Orleans", | |
"url": "http://jazz-wr03.ice.infomaniak.ch/jazz-wr03-128.mp3" | |
} | |
}, | |
{ | |
"id": 3, | |
"station": { | |
"name": "Wereldmuziek", | |
"url": "http://streams.greenhost.nl:8080/wereldmuziek.m3u" | |
} | |
}, | |
{ | |
"id": 4, | |
"station": { | |
"name": "worldwidefm.net", | |
"url": "http://worldwidefm.out.airtime.pro:8000/worldwidefm_a" | |
} | |
}, | |
{ | |
"id": 5, | |
"station": { | |
"name": "Wassoulou", | |
"url": "http://listen.radionomy.com/radio-wassoulou-internationale.m3u" | |
} | |
}, | |
{ | |
"id": 6, | |
"station": { | |
"name": "Asian Star 101.6FM", | |
"url": "http://icecast.commedia.org.uk:8000/asianstar.mp3.m3u" | |
} | |
}, | |
{ | |
"id": 7, | |
"station": { | |
"name": "ZemaRadio (Ethiopian)", | |
"url": "http://listen.radionomy.com/zema-radio.m3u" | |
} | |
}, | |
{ | |
"id": 8, | |
"station": { | |
"name": "Bongo African Grooves", | |
"url": "http://www.bongoradio.com/african-grooves/listen128k.pls" | |
} | |
}, | |
{ | |
"id": 9, | |
"station": { | |
"name": "Bongo East African", | |
"url": "http://www.bongoradio.com/east-african/listen128k.pls" | |
} | |
}, | |
{ | |
"id": 10, | |
"station": { | |
"name": "Chilled Out", | |
"url": "http://relay.181.fm:8700" | |
} | |
}, | |
{ | |
"id": 11, | |
"station": { | |
"name": "Yerevan Nights", | |
"url": "http://www.yerevannights.com/Radio.pls" | |
} | |
}, | |
{ | |
"id": 12, | |
"station": { | |
"name": "Salsa LatiN 181fm", | |
"url": "http://relay.181.fm:8098" | |
} | |
}, | |
{ | |
"id": 13, | |
"station": { | |
"name": "Trance Jazz 181fm", | |
"url": "http://icyrelay.181.fm/181-trancejazz_128k.mp3" | |
} | |
}, | |
{ | |
"id": 14, | |
"station": { | |
"name": "Mantra (radiolla)", | |
"url": "http://air.radiolla.com/mantra192k" | |
} | |
}, | |
{ | |
"id": 15, | |
"station": { | |
"name": "Radio Mississipi Blues", | |
"url": "http://listen.radionomy.com:80/RadioMississipi-Blues" | |
} | |
}, | |
{ | |
"id": 16, | |
"station": { | |
"name": "BackPorch Bluegrass", | |
"url": "http://listen.radionomy.com:80/BackPorchBluegrass" | |
} | |
}, | |
{ | |
"id": 17, | |
"station": { | |
"name": "Antenne Bayern Chillout", | |
"url": "http://mp3channels.webradio.antenne.de/chillout" | |
} | |
}, | |
{ | |
"id": 18, | |
"station": { | |
"name": "A Jazz Dream", | |
"url": "http://streaming.radionomy.com/AJAZZDREAM-Classic-NewJazz24H" | |
} | |
}, | |
{ | |
"id": 19, | |
"station": { | |
"name": "Bombay Beats India Radio", | |
"url": "http://205.164.62.15:8017" | |
} | |
}, | |
{ | |
"id": 20, | |
"station": { | |
"name": "Motown Classics", | |
"url": "http://streaming.radionomy.com/motown-classics" | |
} | |
}, | |
{ | |
"id": 21, | |
"station": { | |
"name": "RnB Cream", | |
"url": "http://streaming.radionomy.com/_rb_cream" | |
} | |
} | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import argparse | |
import json | |
import logging | |
import os | |
import signal | |
import subprocess | |
def playStation(url='http://178.209.52.163:7331/maschinengeist.org.128.aacp'): | |
params = { | |
'player': '/usr/local/bin/mpv', | |
'profile': 'radio', | |
'url': url | |
} | |
command = "%(player)s --profile=\"%(profile)s\" \"%(url)s\"" % params | |
logging.info(command) | |
try: | |
# return commands.getoutput(command) | |
# return subprocess.getoutput(command) | |
# The os.setsid() is passed in the argument preexec_fn so | |
# it's run after the fork() and before exec() to run the shell. | |
return subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid) | |
except Exception as e: | |
logging.exception("Sending notification failed\n{}".format(e)) | |
raise | |
def displayCandidates(candidates, pageStart, nStations): | |
print("{:2} stations found. Please select from following:".format(nStations)) | |
fmtStr = "{:2}) {:20}" | |
for i, s in enumerate(candidates): | |
print(fmtStr.format(i + pageStart, s["station"]["name"])) | |
def selectStation(stations): | |
nStations = len(stations) | |
page = 0 | |
pageSize = 15 | |
msg = "\nEnter number to select (default=0), 's' to skip." | |
if nStations > pageSize: | |
msg += " 'n' to next page, 'p' to previous page.\n>>>_" | |
else: | |
msg += "\n>>>_" | |
while True: | |
start = page * pageSize | |
end = start + pageSize | |
# go to alternate screen | |
os.system("tput smcup") | |
print(chr(27) + "[2J") | |
displayCandidates(stations[start:end], start, nStations) | |
ans = input(msg) | |
logging.info("User ans = '{}'".format(ans)) | |
# go back to main screen | |
os.system("tput rmcup") | |
if ans.lower() == "s": | |
print("Skiping station {}, {}".format( | |
stations["id"], stations["station"]["name"])) | |
return None | |
elif ans.lower() == "n": | |
if page + 1 > int(nStations / pageSize): | |
pass | |
else: | |
page += 1 | |
elif ans.lower() == "p": | |
if page == 0: | |
pass | |
else: | |
page -= 1 | |
elif ans.isdigit(): | |
return stations[int(ans)] | |
else: | |
return stations[0] | |
def getArgs(argv=None): | |
parser = argparse.ArgumentParser(description='Play radiostations with mpv', | |
formatter_class=argparse.ArgumentDefaultsHelpFormatter) | |
parser.add_argument('-p', '--playlist', | |
default='radio.json', | |
help='List of radiostations') | |
return parser.parse_args(argv) | |
if __name__ == '__main__': | |
FORMAT = '%(asctime)s - %(levelname)s - %(message)s' | |
try: | |
os.remove('radio.log') | |
except BaseException: | |
pass | |
logging.basicConfig(filename='radio.log', level=logging.DEBUG, | |
format=FORMAT, datefmt='%a, %d %b %Y %H:%M:%S',) | |
logging.info('--- radio.py logging started ---.') | |
args = getArgs() | |
fpath = "./{}".format(args.playlist) | |
with open(fpath, 'r') as json_data: | |
st = json.load(json_data) | |
selected = selectStation(st) | |
logging.info(selected) | |
url = selected["station"]["url"] | |
print("Playing station {} from {}".format( | |
selected["station"]["name"], url)) | |
process = playStation(url) | |
logging.info(process) | |
# sleep(10) | |
input("Press Enter to stop playback...") | |
try: | |
# Send the signal to all the process groups | |
os.killpg(os.getpgid(process.pid), signal.SIGTERM) | |
except Exception as e: | |
logging.exception(e) | |
pass | |
logging.info('--- radio.py logging finished ---.') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment