|
@@ -0,0 +1,127 @@
|
|
|
|
+#!/usr/bin/python3
|
|
|
|
+
|
|
|
|
+from subprocess import Popen, PIPE, call
|
|
|
|
+from threading import Thread
|
|
|
|
+import time
|
|
|
|
+
|
|
|
|
+# Declarations
|
|
|
|
+# ============
|
|
|
|
+
|
|
|
|
+# Default configuration for mplayer control thread
|
|
|
|
+default_config = {
|
|
|
|
+ "streaming_url" : "http://localhost:9092",
|
|
|
|
+ "per_artist_path" : "/artist",
|
|
|
|
+ "default_url" : "",
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Queue for player commands
|
|
|
|
+cmd_queue = []
|
|
|
|
+
|
|
|
|
+# Command object
|
|
|
|
+class Cmd(object):
|
|
|
|
+ def __init__(self, name, param={}):
|
|
|
|
+ self.name = name
|
|
|
|
+ self.param = param
|
|
|
|
+
|
|
|
|
+# Command names for the queue
|
|
|
|
+
|
|
|
|
+# Stream per artist
|
|
|
|
+# Expected parameter: name - Name of the artist
|
|
|
|
+CMD_NEW_ARTIST_STREAM = "New Artist Stream"
|
|
|
|
+
|
|
|
|
+# Stop current stream
|
|
|
|
+CMD_STOP_STREAM = "Stop Stream"
|
|
|
|
+
|
|
|
|
+# Internal
|
|
|
|
+# ========
|
|
|
|
+
|
|
|
|
+# Internal reference to mplayer process
|
|
|
|
+_player_instance = None
|
|
|
|
+
|
|
|
|
+# Internal mplayer control table
|
|
|
|
+_mplayer_control = {
|
|
|
|
+ "step-backward" : "\x1B[B",
|
|
|
|
+ "backward" : "\x1B[D",
|
|
|
|
+ "forward" : "\x1B[C",
|
|
|
|
+ "step-forward" : "\x1B[A",
|
|
|
|
+ "volume-down" : "9",
|
|
|
|
+ "volume-off" : "m",
|
|
|
|
+ "volume-up" : "0",
|
|
|
|
+ "stop" : "q",
|
|
|
|
+ "pause" : " ",
|
|
|
|
+ "play" : " ",
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+# Internal config
|
|
|
|
+_config = None
|
|
|
|
+
|
|
|
|
+def run():
|
|
|
|
+ global _player_instance, _config, _mplayer_control
|
|
|
|
+
|
|
|
|
+ while True:
|
|
|
|
+ try:
|
|
|
|
+
|
|
|
|
+ # Read the next command
|
|
|
|
+
|
|
|
|
+ cmd = cmd_queue.pop()
|
|
|
|
+
|
|
|
|
+ except IndexError:
|
|
|
|
+
|
|
|
|
+ # If nothing is in the queue wait for a second and try again
|
|
|
|
+
|
|
|
|
+ time.sleep(1)
|
|
|
|
+
|
|
|
|
+ else:
|
|
|
|
+ if cmd.name == CMD_STOP_STREAM:
|
|
|
|
+
|
|
|
|
+ # Stop the current stream
|
|
|
|
+
|
|
|
|
+ _stopPlayer()
|
|
|
|
+
|
|
|
|
+ if cmd.name == CMD_NEW_ARTIST_STREAM:
|
|
|
|
+
|
|
|
|
+ # Stop any current stream
|
|
|
|
+
|
|
|
|
+ _stopPlayer()
|
|
|
|
+
|
|
|
|
+ # Start a new player with the given artist playlist
|
|
|
|
+
|
|
|
|
+ _player_instance = Popen(["mplayer", "-slave", _config["streaming_url"] +
|
|
|
|
+ _config["per_artist_path"] + "/" + cmd.param["name"]], stdin=PIPE)
|
|
|
|
+
|
|
|
|
+def _stopPlayer():
|
|
|
|
+ '''
|
|
|
|
+ Stop A running player instance.
|
|
|
|
+ '''
|
|
|
|
+ global _player_instance, _mplayer_control
|
|
|
|
+
|
|
|
|
+ if _player_instance is not None:
|
|
|
|
+ _player_instance.stdin.write(bytes(_mplayer_control["stop"], "UTF-8"))
|
|
|
|
+ _player_instance.stdin.flush()
|
|
|
|
+ _player_instance.terminate()
|
|
|
|
+ _player_instance = None
|
|
|
|
+
|
|
|
|
+# Main API
|
|
|
|
+# ========
|
|
|
|
+
|
|
|
|
+def start(config=None):
|
|
|
|
+ '''
|
|
|
|
+ Start the new mplayer control thread.
|
|
|
|
+ '''
|
|
|
|
+ global _config, _player_instance
|
|
|
|
+
|
|
|
|
+ c = default_config.copy()
|
|
|
|
+ if config is not None:
|
|
|
|
+ c.update(config)
|
|
|
|
+
|
|
|
|
+ _config = c
|
|
|
|
+
|
|
|
|
+ playerThread = Thread(target=run, args=())
|
|
|
|
+ playerThread.daemon = True
|
|
|
|
+ playerThread.start()
|
|
|
|
+
|
|
|
|
+ # Start default playlist if defined
|
|
|
|
+
|
|
|
|
+ d = config["default_url"]
|
|
|
|
+ if d != "":
|
|
|
|
+ _player_instance = Popen(["mplayer", "-slave", d], stdin=PIPE)
|