diff --git a/plex_mpv_shim/client.py b/plex_mpv_shim/client.py index caf9b87..5aea4d1 100644 --- a/plex_mpv_shim/client.py +++ b/plex_mpv_shim/client.py @@ -59,6 +59,7 @@ class HttpHandler(SimpleHTTPRequestHandler): "/player/application/sendKey",), "sendVKey"), (("/player/playback/bigStepForward", "/player/playback/bigStepBack",), "stepFunction"), + (("/player/playback/refreshPlayQueue",),"refreshPlayQueue"), #(("/player/mirror/details",), "mirror"), ) @@ -321,12 +322,16 @@ class HttpHandler(SimpleHTTPRequestHandler): key = arguments.get("key", None) offset = int(int(arguments.get("offset", 0))/1e3) url = urllib.parse.urljoin("%s://%s:%s" % (protocol, address, port), key) + playQueue = arguments.get("containerKey", None) token = arguments.get("token", None) if token: upd_token(address, token) - media = Media(url) + if settings.enable_play_queue and playQueue.startswith("/playQueue"): + media = Media(url, play_queue=playQueue) + else: + media = Media(url) log.debug("HttpHandler::playMedia %s" % media) @@ -373,6 +378,10 @@ class HttpHandler(SimpleHTTPRequestHandler): subtitleStreamID = arguments["subtitleStreamID"] playerManager.set_streams(audioStreamID, subtitleStreamID) + def refreshPlayQueue(self, path, arguments): + playerManager._video.parent.upd_play_queue() + timelineManager.SendTimelineToSubscribers() + def mirror(self, path, arguments): pass diff --git a/plex_mpv_shim/conf.py b/plex_mpv_shim/conf.py index f847949..d3e68d9 100644 --- a/plex_mpv_shim/conf.py +++ b/plex_mpv_shim/conf.py @@ -26,7 +26,8 @@ class Settings(object): "audio_dtspassthrough": False, "client_uuid": str(uuid.uuid4()), "display_sleep": 0, - "display_mode": "" + "display_mode": "", + "enable_play_queue": True } def __getattr__(self, name): diff --git a/plex_mpv_shim/gdm.py b/plex_mpv_shim/gdm.py index a415235..2cf19a5 100644 --- a/plex_mpv_shim/gdm.py +++ b/plex_mpv_shim/gdm.py @@ -31,6 +31,7 @@ import re import threading import time import urllib.request, urllib.error, urllib.parse +from .conf import settings class PlexGDM: @@ -61,6 +62,10 @@ class PlexGDM: print("PlexGDM: %s" % message) def clientDetails(self, c_id, c_name, c_port, c_product, c_version): + capabilities = b"timeline,playback,navigation" + if settings.enable_play_queue: + capabilities = b"timeline,playback,navigation,playqueues" + data = { b"Name": str(c_name).encode("utf-8"), b"Port": str(c_port).encode("utf-8"), @@ -68,7 +73,7 @@ class PlexGDM: b"Content-Type": b"plex/media-player", b"Protocol": b"plex", b"Protocol-Version": b"1", - b"Protocol-Capabilities": b"timeline,playback,navigation", + b"Protocol-Capabilities": capabilities, b"Version": str(c_version).encode("utf-8"), b"Resource-Identifier": str(c_id).encode("utf-8"), b"Device-Class": b"HTPC" diff --git a/plex_mpv_shim/media.py b/plex_mpv_shim/media.py index c82e68b..7981b24 100644 --- a/plex_mpv_shim/media.py +++ b/plex_mpv_shim/media.py @@ -292,15 +292,25 @@ class XMLCollection(object): return self.path.path class Media(XMLCollection): - def __init__(self, url, series=None, seq=None): + def __init__(self, url, series=None, seq=None, play_queue=None, play_queue_xml=None): XMLCollection.__init__(self, url) self.video = self.tree.find('./Video') self.is_tv = self.video.get("type") == "episode" self.seq = None self.has_next = False self.has_prev = False + self.play_queue = play_queue + self.play_queue_xml = play_queue_xml - if self.is_tv: + if self.play_queue: + if not series: + self.upd_play_queue() + else: + self.series = series + self.seq = seq + self.has_next = self.seq < len(self.series) + self.has_prev = self.seq > 0 + elif self.is_tv: if series: self.series = series self.seq = seq @@ -329,15 +339,41 @@ class Media(XMLCollection): self.has_next = self.seq < len(self.series) self.has_prev = self.seq > 0 + def upd_play_queue(self): + if self.play_queue: + self.play_queue_xml = XMLCollection(self.get_path(self.play_queue)) + videos = self.play_queue_xml.tree.findall('./Video') + self.series = [] + + key = self.video.get('key') + for i, video in enumerate(videos): + if video.get('key') == key: + self.seq = i + self.series.append(video) + + self.has_next = self.seq < len(self.series) + self.has_prev = self.seq > 0 + + def get_queue_info(self): + return { + "playQueueID": self.play_queue_xml.tree.find(".").get("playQueueID"), + "playQueueVersion": self.play_queue_xml.tree.find(".").get("playQueueVersion"), + "playQueueItemID": self.series[self.seq].get("playQueueItemID") + } + def get_next(self): if self.has_next: + if self.play_queue and self.seq+1 == len(self.series): + self.upd_play_queue() next_video = self.series[self.seq+1] - return Media(self.get_path(next_video.get('key')), self.series, self.seq+1) + return Media(self.get_path(next_video.get('key')), self.series, self.seq+1, self.play_queue, self.play_queue_xml) def get_prev(self): if self.has_prev: + if self.play_queue and self.seq-1 == 0: + self.upd_play_queue() prev_video = self.series[self.seq-1] - return Media(self.get_path(prev_video.get('key')), self.series, self.seq-1) + return Media(self.get_path(prev_video.get('key')), self.series, self.seq-1, self.play_queue, self.play_queue_xml) def get_video(self, index, media=0, part=0): if index == 0 and self.video: diff --git a/plex_mpv_shim/timeline.py b/plex_mpv_shim/timeline.py index b85bd96..03659bd 100644 --- a/plex_mpv_shim/timeline.py +++ b/plex_mpv_shim/timeline.py @@ -128,6 +128,9 @@ class TimelineManager(threading.Thread): options["machineIdentifier"] = media.get_machine_identifier() options["seekRange"] = "0-%s" % options["duration"] + if media.play_queue: + options.update(media.get_queue_info()) + controllable.append("playPause") controllable.append("stop") controllable.append("stepBack")