diff --git a/plexapi/client.py b/plexapi/client.py index 4aa7d8755..2329cdec0 100644 --- a/plexapi/client.py +++ b/plexapi/client.py @@ -481,8 +481,38 @@ def setVideoStream(self, videoStreamID, mtype=DEFAULT_MTYPE): """ self.setStreams(videoStreamID=videoStreamID, mtype=mtype) + def createPlayQueue(self, server, items, offset=0, paused=False, **params): + """ Create a playqueue and start playback of the specified media item. + + Parameters: + server (:class:`~plexapi.server.PlexServer`): Server you are connected to. + items (:class:`~plexapi.base.PlexPartialObject`): + A media item or a list of media items. + offset (int, optional): Number of milliseconds at which to start playing with zero + representing the beginning (default 0). + paused (bool, optional): Set True to pause playback, + default False to start playback immediately. + **params (dict): Additional options to apply to the playqueue. + See :func:`~plexapi.playqueue.PlayQueue.create` for available parameters. + """ + protocol, address, port = server._baseurl.split(':') + args = PlayQueue._createArgs( + server=server, + items=items, + offset=offset, + paused=int(bool(paused)), + protocol=protocol, + address=address.strip('/'), + port=port, + machineIdentifier=server.machineIdentifier, + source=server.machineIdentifier, + **params) + self.sendCommand("playback/createPlayQueue", **args) + def playMedia(self, media, offset=0, **params): - """ Start playback of the specified media item. See also: + """ Start playback of the specified media item. + Note: This is a legacy command for older clients. + Use :func:`~plexapi.client.PlexClient.createPlayQueue` instead for modern clients. Parameters: media (:class:`~plexapi.media.Media`): Media item to be played back diff --git a/plexapi/playqueue.py b/plexapi/playqueue.py index ede8ccb0f..2d59bd92d 100644 --- a/plexapi/playqueue.py +++ b/plexapi/playqueue.py @@ -136,39 +136,25 @@ def get( c._server = server return c - @classmethod - def create( - cls, + @staticmethod + def _createArgs( server, items, startItem=None, - shuffle=0, - repeat=0, - includeChapters=1, - includeRelated=1, - continuous=0, + shuffle=False, + repeat=False, + includeChapters=True, + includeRelated=True, + continuous=False, + **kwargs ): - """Create and return a new :class:`~plexapi.playqueue.PlayQueue`. - - Parameters: - server (:class:`~plexapi.server.PlexServer`): Server you are connected to. - items (:class:`~plexapi.base.PlexPartialObject`): - A media item or a list of media items. - startItem (:class:`~plexapi.base.Playable`, optional): - Media item in the PlayQueue where playback should begin. - shuffle (int, optional): Start the playqueue shuffled. - repeat (int, optional): Start the playqueue shuffled. - includeChapters (int, optional): include Chapters. - includeRelated (int, optional): include Related. - continuous (int, optional): include additional items after the initial item. - For a show this would be the next episodes, for a movie it does nothing. - """ args = { - "includeChapters": includeChapters, - "includeRelated": includeRelated, - "repeat": repeat, - "shuffle": shuffle, - "continuous": continuous, + "includeChapters": int(bool(includeChapters)), + "includeRelated": int(bool(includeRelated)), + "repeat": int(bool(repeat)), + "shuffle": int(bool(shuffle)), + "continuous": int(bool(continuous)), + **kwargs } if isinstance(items, list): @@ -187,6 +173,48 @@ def create( if startItem: args["key"] = startItem.key + return args + + @classmethod + def create( + cls, + server, + items, + startItem=None, + shuffle=False, + repeat=False, + includeChapters=True, + includeRelated=True, + continuous=False, + **kwargs + ): + """Create and return a new :class:`~plexapi.playqueue.PlayQueue`. + + Parameters: + server (:class:`~plexapi.server.PlexServer`): Server you are connected to. + items (:class:`~plexapi.base.PlexPartialObject`): + A media item or a list of media items. + startItem (:class:`~plexapi.base.Playable`, optional): + Media item in the PlayQueue where playback should begin. + shuffle (bool, optional): Start the playqueue shuffled. + repeat (bool, optional): Start the playqueue shuffled. + includeChapters (bool, optional): include Chapters. + includeRelated (bool, optional): include Related. + continuous (bool, optional): include additional items after the initial item. + For a show this would be the next episodes, for a movie it does nothing. + **kwargs (dict): Additional options to apply to the playqueue. + """ + args = cls._createArgs( + server=server, + items=items, + startItem=startItem, + shuffle=shuffle, + repeat=repeat, + includeChapters=includeChapters, + includeRelated=includeRelated, + continuous=continuous, + **kwargs + ) path = f"/playQueues{utils.joinArgs(args)}" data = server.query(path, method=server._session.post) c = cls(server, data, initpath=path) diff --git a/tests/test_client.py b/tests/test_client.py index 21974530e..d9d8bb7c5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -139,3 +139,20 @@ def test_client_timeline(plex, client, movies, proxy): print("movie.markPlayed()") movie.markPlayed() time.sleep(2) + + +@pytest.mark.client +def test_client_createPlayQueue(client, plex, movie, mocker): + client.sendCommand = mocker.MagicMock(return_value=None) + + client.createPlayQueue(plex, movie, paused=True) + + client.sendCommand.assert_called_once() + args = client.sendCommand.call_args[0] + kwargs = client.sendCommand.call_args[1] + + assert args[0] == "playback/createPlayQueue" + assert kwargs["paused"] == 1 + assert kwargs["type"] == movie.listType + assert kwargs["uri"].startswith(f"server://{plex.machineIdentifier}/") + assert movie.key in kwargs["uri"]