You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.9 KiB
Python

import kode256
import requests
import vlc
from bureau import Bureau, add_command, add_webview
class Audio(Bureau):
"""
The Audio Services department provides for playback and recording
of sound within the office environment.
"""
name = "Audio Services Dept."
prefix = "AU"
version = 0
def __init__(self):
Bureau.__init__(self)
self.urldb = self.open_db("urldb")
self.player = vlc.MediaListPlayer()
@add_command("p", "Play an album, track or a live stream.")
def play(self, data):
"""
Initiates playback of a media reference. This could be a song or album
stored on the local office or remote URLs for live playback. Currently,
only supports line-out signals on the default DAC.
"""
shortcode, _ = data.split(".")
self.log.debug("looking up shortcode " + shortcode)
url = self.urldb.get(shortcode)
self.log.debug(" playing url " + url)
playlist = vlc.MediaList()
playlist.add_media(url)
self.player.set_media_list(playlist)
self.player.play()
@add_command("stop", "Halt audio playback.")
def stop(self):
"""
Stops all audio currently playing audio output.
"""
self.player.pause()
@add_command("resu", "Resume playback.")
def resume(self):
"""
Resume playback of paused audio.
"""
self.player.play()
@add_command("next", "Play the next song.")
def play_next(self):
"""
Skip to the next song in the playlist or album.
"""
#subprocess.call(["mocp", "-f"])
# TODO
pass
@add_command("prev", "Play the previous song.")
def play_prev(self):
"""
Skip to the previous song in the playlist or album.
"""
#subprocess.call(["mocp", "-r"])
# TODO
pass
@add_command("nowp", "Now Playing")
def now_playing(self):
"""
Prints the currently playing song or stream on the small printer.
"""
media = self.player.get_media_player().get_media()
out = "Now Playing: "
out += media.get_meta(vlc.Meta.Title) + "\n"
nowplaying = media.get_meta(vlc.Meta.NowPlaying)
if nowplaying == "":
out += "by " + media.get_meta(vlc.Meta.Artist) + "\n"
out += "from the album '" + media.get_meta(vlc.Meta.Album) \
+ "'\n"
else:
out += nowplaying + "\n"
self.log.debug("info output:" + out)
self.print_small(out)
@add_webview("radio", "radio")
def radio_webview(self, data=None):
"""
Edit internet radio stations.
"""
#TODO: allow deletes
#TODO: print out any new station
#TODO: use some kind of nicer templates?
ret = """
<html><head><title>screenless office - internet radio admin</title></head>
<body>
<h1>Audio Department</h1>
"""
if data:
if data["addurl"]:
self.save_url(data["addurl"])
ret += "<div>New station " + data["addurl"] + " saved!</div>\n"
ret += "<h2>Radio Stations<h2>\n <ul>\n"
with self.urldb.env.begin(db=self.urldb.db) as txn:
for sh_code, url in txn.cursor():
ret += "<li>" + url.decode("utf-8") + "</li>\n"
ret += "</ul>\n"
ret += """
<form action='/AU/radio' method='POST'>
<ul>
<li>
<label for="addurl">Add Radio Station URL:</label>
<input type="text" id="addurl" name="addurl" />
</li>
<li class="button">
<button type="submit">Save</button>
</li>
</ul>
</form>
</body></html>"""
return ret
def save_url(self, url):
"""
saves an url for a local file or network audio stream.
"""
# TODO: might be nice to save some station info: title, perhaps a logo, etc.
code = self.urldb.store_and_get_shortcode(url)
self.print_url(code)
print("saved url with shortcode: ", code)
def print_url(self, shortcode):
url = self.urldb.get(shortcode)
# download the url
headers = {'User-Agent': 'Mozilla/5.0'}
try:
resp = requests.get(url, timeout=20.0, headers=headers)
except requests.ReadTimeout:
self.log.warning("Timeout reading url %s", url)
self.print_small("Error: timed out reading " + url)
return
except requests.ConnectionError as e:
self.log.warning("Error reading url %s", url)
self.print_small("Error: connect error on " + url)
return
# TODO: support #EXTINF: extended attributes - logo or #EXTIMG or #PLAYLIST
# TODO: support XSPF?? does anyone use this?
# TODO: what to do with unwrapped links - raw mp3 or whateva - use vlc info?
# if line startswith #EXTINF: title = first comma to EOL
# if line startswith Title then title = first '=' to EOL
title = ""
for line in resp.text.splitlines():
if line.startswith("#EXTINF:"):
# this is m3u playlist - title is from first comma to EOL
title = line[(line.find(',') + 1):].strip()
elif line.startswith("Title"):
# this looks like a pls playlist - title is from first '=' to EOL
title = line[(line.find('=') + 1):].strip()
# TODO: create barcode
# small print title, url, barcode
prn = self._get_small_printer()
prn.textln("RADIO STATION:")
prn.textln(title)
prn.textln(url)
prn.soft_barcode("code128", "AUp." + shortcode)
prn.print_and_feed()
#TODO: cut
prn.close()
def main():
au = Audio()
au.run()
if __name__ == "__main__":
main()