|
@@ -0,0 +1,105 @@
|
|
|
|
+#!./bin/python3
|
|
|
|
+
|
|
|
|
+import os
|
|
|
|
+import threading
|
|
|
|
+import time
|
|
|
|
+
|
|
|
|
+from handler import EVENT_LEFT
|
|
|
|
+from handler.listhandler import BaseListHandler
|
|
|
|
+from handler.lib.pymplb import MPlayer
|
|
|
|
+
|
|
|
|
+class M3UHandler(BaseListHandler):
|
|
|
|
+
|
|
|
|
+ def __init__(self, config, display):
|
|
|
|
+ super().__init__(config, display)
|
|
|
|
+ self._mplayer = None
|
|
|
|
+ self._mplayer_watcher = None
|
|
|
|
+ self.is_playing = False
|
|
|
|
+ self._last_event = time.time()
|
|
|
|
+
|
|
|
|
+ def setPlaylistItem(self, item):
|
|
|
|
+ '''
|
|
|
|
+ Called with the selected item.
|
|
|
|
+ '''
|
|
|
|
+ self.item = item
|
|
|
|
+
|
|
|
|
+ path = item["path"]
|
|
|
|
+ items = []
|
|
|
|
+
|
|
|
|
+ with open(path) as f:
|
|
|
|
+ for line in f:
|
|
|
|
+ item_path = str(line).strip()
|
|
|
|
+ if not item_path.startswith("#"):
|
|
|
|
+ items.append({
|
|
|
|
+ "name" : self.toDisplayName(os.path.basename(item_path)),
|
|
|
|
+ "path" : os.path.join(os.path.dirname(path), item_path)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ if self._mplayer is None:
|
|
|
|
+ self._mplayer = MPlayer()
|
|
|
|
+ self.setItems(items)
|
|
|
|
+ self._mplayer_watcher = threading.Thread(target=self._watch_mplayer, daemon=True)
|
|
|
|
+ self._mplayer_watcher.start()
|
|
|
|
+
|
|
|
|
+ self.is_playing = False
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def itemSelected(self, item):
|
|
|
|
+ self._mplayer.loadfile(item["path"])
|
|
|
|
+ self.is_playing = True
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def stop(self):
|
|
|
|
+ '''
|
|
|
|
+ Called when the handler should stop.
|
|
|
|
+ '''
|
|
|
|
+ if self._mplayer is not None:
|
|
|
|
+ self._mplayer.quit()
|
|
|
|
+ self._mplayer = None
|
|
|
|
+ self._mplayer_watcher = None
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def emitEvent(self, event):
|
|
|
|
+ '''
|
|
|
|
+ Called when an event has happened.
|
|
|
|
+ '''
|
|
|
|
+
|
|
|
|
+ # Clock the time so the thread can hold off if there
|
|
|
|
+ # was a recent user event
|
|
|
|
+
|
|
|
|
+ self._last_event = time.time()
|
|
|
|
+
|
|
|
|
+ if event == EVENT_LEFT and self.is_playing:
|
|
|
|
+ self._mplayer.stop()
|
|
|
|
+ self.is_playing = False
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ super().emitEvent(event)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def _watch_mplayer(self):
|
|
|
|
+ '''
|
|
|
|
+ Thread to watch mplayer and advance the playlist.
|
|
|
|
+ '''
|
|
|
|
+
|
|
|
|
+ while self._mplayer_watcher is not None:
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ time.sleep(0.5)
|
|
|
|
+
|
|
|
|
+ if self._mplayer:
|
|
|
|
+ playing_path = self._mplayer.p_path
|
|
|
|
+
|
|
|
|
+ # Only do something in the thread if the last user
|
|
|
|
+ # input is at least 3 seconds ago
|
|
|
|
+
|
|
|
|
+ if time.time() - self._last_event > 3:
|
|
|
|
+
|
|
|
|
+ # Advance to the next item if we are playing music
|
|
|
|
+
|
|
|
|
+ if self.is_playing and playing_path == "(null)":
|
|
|
|
+ self.nextItem()
|
|
|
|
+
|
|
|
|
+ except Exception as e:
|
|
|
|
+ print("Error watching player:", e)
|
|
|
|
+
|