def removeItem(self, item): request = plexrequest.PlexRequest( self.server, "/playQueues/" + str(self.id) + "/items/" + item.get("playQueueItemID", "-1"), "DELETE") self.addRequestOptions(request) context = request.createRequestContext( "delete", callback.Callable(self.onResponse)) util.APP.startRequest(request, context)
def sendTimelineToServer(self, timelineType, timeline, time): if not hasattr(timeline.item, 'getServer') or not timeline.item.getServer(): return serverTimeline = self.getServerTimeline(timelineType) # Only send timeline if it's the first, item changes, playstate changes or timer pops itemsEqual = timeline.item and serverTimeline.item and timeline.item.ratingKey == serverTimeline.item.ratingKey if itemsEqual and timeline.state == serverTimeline.state and not serverTimeline.isExpired( ): return serverTimeline.reset() serverTimeline.item = timeline.item serverTimeline.state = timeline.state # Ignore sending timelines for multi part media with no duration obj = timeline.choice if obj and obj.part and obj.part.duration.asInt( ) == 0 and obj.media.parts and len(obj.media.parts) > 1: util.WARN_LOG( "Timeline not supported: the current part doesn't have a valid duration" ) return # It's possible with timers and in player seeking for the time to be greater than the # duration, which causes a 400, so in that case we'll set the time to the duration. duration = timeline.item.duration.asInt() or timeline.duration if time > duration: time = duration params = util.AttributeDict() params["time"] = time params["duration"] = duration params["state"] = timeline.state params["guid"] = timeline.item.guid params["ratingKey"] = timeline.item.ratingKey params["url"] = timeline.item.url params["key"] = timeline.item.key params["containerKey"] = timeline.item.container.address if timeline.playQueue: params["playQueueItemID"] = timeline.playQueue.selectedId path = "/:/timeline" for paramKey in params: if params[paramKey]: path = http.addUrlParam( path, paramKey + "=" + six.moves.urllib.parse.quote(str(params[paramKey]))) request = plexrequest.PlexRequest(timeline.item.getServer(), path) context = request.createRequestContext( "timelineUpdate", callback.Callable(self.onTimelineResponse)) context.playQueue = timeline.playQueue util.APP.startRequest(request, context)
def addItem(self, item, addNext=False, excludeSeedItem=False): request = plexrequest.PlexRequest(self.server, "/playQueues/" + str(self.id), "PUT") request.addParam("uri", item.getItemUri()) request.addParam("next", addNext and "1" or "0") request.addParam("excludeSeedItem", excludeSeedItem and "1" or "0") self.addRequestOptions(request) context = request.createRequestContext( "add", callback.Callable(self.onResponse)) util.APP.startRequest(request, context)
def refreshResources(self, force=False): if force: plexapp.SERVERMANAGER.resetLastTest() request = myplexrequest.MyPlexRequest("/pms/resources") context = request.createRequestContext( "resources", callback.Callable(self.onResourcesResponse)) if plexapp.ACCOUNT.isSecure: request.addParam("includeHttps", "1") util.APP.startRequest(request, context)
def createPlayQueueForId(id, server=None, contentType=None): obj = PlayQueue(server, contentType) obj.id = id request = plexrequest.PlexRequest(server, "/playQueues/" + str(id)) request.addParam("own", "1") obj.addRequestOptions(request) context = request.createRequestContext("own", callback.Callable(obj.onResponse)) util.APP.startRequest(request, context) return obj
def moveItem(self, item, after): if after: query = "?after=" + after.get("playQueueItemID", "-1") else: query = "" request = plexrequest.PlexRequest( self.server, "/playQueues/" + str(self.id) + "/items/" + item.get("playQueueItemID", "-1") + "/move" + query, "PUT") self.addRequestOptions(request) context = request.createRequestContext( "move", callback.Callable(self.onResponse)) util.APP.startRequest(request, context)
def publish(self): util.LOG('MyPlexManager().publish() - NOT IMPLEMENTED') return # TODO: ----------------------------------------------------------------------------------------------------------------------------- IMPLEMENT? request = myplexrequest.MyPlexRequest( "/devices/" + util.INTERFACE.getGlobal("clientIdentifier")) context = request.createRequestContext("publish") addrs = util.INTERFACE.getGlobal("roDeviceInfo").getIPAddrs() for iface in addrs: request.addParam(six.moves.urllib.parse.quote("Connection[][uri]"), "http://{0):8324".format(addrs[iface])) util.APP.startRequest(request, context, "_method=PUT")
def setShuffle(self, shuffle=None): if shuffle is None: shuffle = not self.isShuffled if self.isShuffled == shuffle: return if shuffle: command = "/shuffle" else: command = "/unshuffle" # Don't change self.isShuffled, it'll be set in OnResponse if all goes well request = plexrequest.PlexRequest( self.server, "/playQueues/" + str(self.id) + command, "PUT") self.addRequestOptions(request) context = request.createRequestContext( "shuffle", callback.Callable(self.onResponse)) util.APP.startRequest(request, context)
def refresh(self, force=True, delay=False, wait=False): # Ignore refreshing local PQs if self.isLocal(): return if wait: self.responded = False self.initialized = False # We refresh our play queue if the caller insists or if we only have a # portion of our play queue loaded. In particular, this means that we don't # refresh the play queue if we're asked to refresh because a new track is # being played but we have the entire album loaded already. if force or self.isWindowed(): if delay: # We occasionally want to refresh the PQ in response to moving to a # new item and starting playback, but if we refresh immediately: # we probably end up refreshing before PMS realizes we've moved on. # There's no great solution, but delaying our refresh by just a few # seconds makes us much more likely to get an accurate window (and # accurate selected IDs) from PMS. if not self.refreshTimer: self.refreshTimer = plexapp.createTimer( 5000, self.onRefreshTimer) util.APP.addTimer(self.refreshTimer) else: request = plexrequest.PlexRequest( self.server, "/playQueues/" + str(self.id)) self.addRequestOptions(request) context = request.createRequestContext( "refresh", callback.Callable(self.onResponse)) util.APP.startRequest(request, context) if wait: return self.waitForInitialization()
def createRemotePlayQueue(item, contentType, options, args): util.DEBUG_LOG('Creating remote playQueue request...') obj = PlayQueue(item.getServer(), contentType, options) # The item's URI is made up of the library section UUID, a descriptor of # the item type (item or directory), and the item's path, URL-encoded. uri = "library://" + item.getLibrarySectionUuid() + "/" itemType = item.isDirectory() and "directory" or "item" path = None if not options.key: # if item.onDeck and len(item.onDeck) > 0: # options.key = item.onDeck[0].getAbsolutePath("key") # el if not item.isDirectory(): options.key = item.get("key") # If we're asked to play unwatched, ignore the option unless we are unwatched. options.unwatched = options.unwatched and item.isUnwatched() # TODO(schuyler): Until we build postplay, we're not allowed to queue containers for episodes. if item.type == "episode": options.context = options.CONTEXT_SELF elif item.type == "movie": if not options.extrasPrefixCount and not options.resume: options.extrasPrefixCount = util.INTERFACE.getPreference( "cinema_trailers", 0) # How exactly to construct the item URI depends on the metadata type, though # whenever possible we simply use /library/metadata/:id. if item.isLibraryItem() and not item.isLibraryPQ: path = "/library/metadata/" + item.ratingKey else: path = item.getAbsolutePath("key") if options.context == options.CONTEXT_SELF: # If the context is specifically for just this item,: just use the # item's key and get out. pass elif item.type == "playlist": path = None uri = item.get("ratingKey") options.isPlaylist = True elif item.type == "track": # TODO(rob): Is there ever a time the container address is wrong? If we # expect to play a single track,: use options.CONTEXT_SELF. path = item.container.address or "/library/metadata/" + item.get( "parentRatingKey", "") itemType = "directory" elif item.isPhotoOrDirectoryItem(): if item.type == "photoalbum" or item.parentKey: path = item.getParentPath(item.type == "photoalbum" and "key" or "parentKey") itemType = "item" elif item.isDirectory(): path = item.getAbsolutePath("key") else: path = item.container.address itemType = "directory" options.key = item.getAbsolutePath("key") elif item.type == "episode": path = "/library/metadata/" + item.get("grandparentRatingKey", "") itemType = "directory" options.key = item.getAbsolutePath("key") # elif item.type == "show": # path = "/library/metadata/" + item.get("ratingKey", "") if path: if args: path += util.joinArgs(args) util.DEBUG_LOG("playQueue path: " + str(path)) if "/search" not in path: # Convert a few params to the PQ spec convert = {'type': "sourceType", 'unwatchedLeaves': "unwatched"} for key in convert: regex = re.compile("(?i)([?&])" + key + "=") path = regex.sub("\1" + convert[key] + "=", path) util.DEBUG_LOG("playQueue path: " + str(path)) uri = uri + itemType + "/" + six.moves.urllib.parse.quote_plus(path) util.DEBUG_LOG("playQueue uri: " + str(uri)) # Create the PQ request request = plexrequest.PlexRequest(obj.server, "/playQueues") request.addParam(not options.isPlaylist and "uri" or "playlistID", uri) request.addParam("type", contentType) # request.addParam('X-Plex-Client-Identifier', util.INTERFACE.getGlobal('clientIdentifier')) # Add options we pass once during PQ creation if options.shuffle: request.addParam("shuffle", "1") options.key = None else: request.addParam("shuffle", "0") if options.key: request.addParam("key", options.key) # Add options we pass every time querying PQs obj.addRequestOptions(request) util.DEBUG_LOG('Initial playQueue request started...') context = request.createRequestContext("create", callback.Callable(obj.onResponse)) util.APP.startRequest(request, context, body='') return obj