mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Allow Plex playback using provided playqueue ID (#45580)
This commit is contained in:
parent
8065ece0bd
commit
d7e0391e03
@ -22,6 +22,7 @@ from homeassistant.components.media_player.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.const import STATE_IDLE, STATE_PAUSED, STATE_PLAYING
|
from homeassistant.const import STATE_IDLE, STATE_PAUSED, STATE_PLAYING
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.dispatcher import (
|
from homeassistant.helpers.dispatcher import (
|
||||||
async_dispatcher_connect,
|
async_dispatcher_connect,
|
||||||
async_dispatcher_send,
|
async_dispatcher_send,
|
||||||
@ -495,16 +496,26 @@ class PlexMediaPlayer(MediaPlayerEntity):
|
|||||||
if isinstance(src, int):
|
if isinstance(src, int):
|
||||||
src = {"plex_key": src}
|
src = {"plex_key": src}
|
||||||
|
|
||||||
shuffle = src.pop("shuffle", 0)
|
playqueue_id = src.pop("playqueue_id", None)
|
||||||
media = self.plex_server.lookup_media(media_type, **src)
|
|
||||||
|
|
||||||
if media is None:
|
if playqueue_id:
|
||||||
_LOGGER.error("Media could not be found: %s", media_id)
|
try:
|
||||||
return
|
playqueue = self.plex_server.get_playqueue(playqueue_id)
|
||||||
|
except plexapi.exceptions.NotFound as err:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"PlayQueue '{playqueue_id}' could not be found"
|
||||||
|
) from err
|
||||||
|
else:
|
||||||
|
shuffle = src.pop("shuffle", 0)
|
||||||
|
media = self.plex_server.lookup_media(media_type, **src)
|
||||||
|
|
||||||
_LOGGER.debug("Attempting to play %s on %s", media, self.name)
|
if media is None:
|
||||||
|
_LOGGER.error("Media could not be found: %s", media_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
_LOGGER.debug("Attempting to play %s on %s", media, self.name)
|
||||||
|
playqueue = self.plex_server.create_playqueue(media, shuffle=shuffle)
|
||||||
|
|
||||||
playqueue = self.plex_server.create_playqueue(media, shuffle=shuffle)
|
|
||||||
try:
|
try:
|
||||||
self.device.playMedia(playqueue)
|
self.device.playMedia(playqueue)
|
||||||
except requests.exceptions.ConnectTimeout:
|
except requests.exceptions.ConnectTimeout:
|
||||||
|
@ -593,6 +593,10 @@ class PlexServer:
|
|||||||
"""Create playqueue on Plex server."""
|
"""Create playqueue on Plex server."""
|
||||||
return plexapi.playqueue.PlayQueue.create(self._plex_server, media, **kwargs)
|
return plexapi.playqueue.PlayQueue.create(self._plex_server, media, **kwargs)
|
||||||
|
|
||||||
|
def get_playqueue(self, playqueue_id):
|
||||||
|
"""Retrieve existing playqueue from Plex server."""
|
||||||
|
return plexapi.playqueue.PlayQueue.get(self._plex_server, playqueue_id)
|
||||||
|
|
||||||
def fetch_item(self, item):
|
def fetch_item(self, item):
|
||||||
"""Fetch item from Plex server."""
|
"""Fetch item from Plex server."""
|
||||||
return self._plex_server.fetchItem(item)
|
return self._plex_server.fetchItem(item)
|
||||||
|
@ -105,15 +105,25 @@ def lookup_plex_media(hass, content_type, content_id):
|
|||||||
content_type = DOMAIN
|
content_type = DOMAIN
|
||||||
|
|
||||||
plex_server_name = content.pop("plex_server", None)
|
plex_server_name = content.pop("plex_server", None)
|
||||||
shuffle = content.pop("shuffle", 0)
|
|
||||||
|
|
||||||
plex_server = get_plex_server(hass, plex_server_name)
|
plex_server = get_plex_server(hass, plex_server_name)
|
||||||
|
|
||||||
media = plex_server.lookup_media(content_type, **content)
|
playqueue_id = content.pop("playqueue_id", None)
|
||||||
if media is None:
|
if playqueue_id:
|
||||||
raise HomeAssistantError(f"Plex media not found using payload: '{content_id}'")
|
try:
|
||||||
|
playqueue = plex_server.get_playqueue(playqueue_id)
|
||||||
|
except NotFound as err:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"PlayQueue '{playqueue_id}' could not be found"
|
||||||
|
) from err
|
||||||
|
else:
|
||||||
|
shuffle = content.pop("shuffle", 0)
|
||||||
|
media = plex_server.lookup_media(content_type, **content)
|
||||||
|
if media is None:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Plex media not found using payload: '{content_id}'"
|
||||||
|
)
|
||||||
|
playqueue = plex_server.create_playqueue(media, shuffle=shuffle)
|
||||||
|
|
||||||
playqueue = plex_server.create_playqueue(media, shuffle=shuffle)
|
|
||||||
return (playqueue, plex_server)
|
return (playqueue, plex_server)
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,6 +168,12 @@ def playqueue_created_fixture():
|
|||||||
return load_fixture("plex/playqueue_created.xml")
|
return load_fixture("plex/playqueue_created.xml")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="playqueue_1234", scope="session")
|
||||||
|
def playqueue_1234_fixture():
|
||||||
|
"""Load payload for playqueue 1234 and return it."""
|
||||||
|
return load_fixture("plex/playqueue_1234.xml")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="plex_server_accounts", scope="session")
|
@pytest.fixture(name="plex_server_accounts", scope="session")
|
||||||
def plex_server_accounts_fixture():
|
def plex_server_accounts_fixture():
|
||||||
"""Load payload accounts on the Plex server and return it."""
|
"""Load payload accounts on the Plex server and return it."""
|
||||||
|
@ -113,6 +113,7 @@ async def test_sonos_play_media(
|
|||||||
setup_plex_server,
|
setup_plex_server,
|
||||||
requests_mock,
|
requests_mock,
|
||||||
empty_payload,
|
empty_payload,
|
||||||
|
playqueue_1234,
|
||||||
playqueue_created,
|
playqueue_created,
|
||||||
plextv_account,
|
plextv_account,
|
||||||
sonos_resources,
|
sonos_resources,
|
||||||
@ -178,3 +179,19 @@ async def test_sonos_play_media(
|
|||||||
play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_bad_media, sonos_speaker_name)
|
play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_bad_media, sonos_speaker_name)
|
||||||
assert "Plex media not found" in str(excinfo.value)
|
assert "Plex media not found" in str(excinfo.value)
|
||||||
assert playback_mock.call_count == 3
|
assert playback_mock.call_count == 3
|
||||||
|
|
||||||
|
# Test with speakers available and playqueue
|
||||||
|
requests_mock.get("https://1.2.3.4:32400/playQueues/1234", text=playqueue_1234)
|
||||||
|
content_id_with_playqueue = '{"playqueue_id": 1234}'
|
||||||
|
play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_with_playqueue, sonos_speaker_name)
|
||||||
|
assert playback_mock.call_count == 4
|
||||||
|
|
||||||
|
# Test with speakers available and invalid playqueue
|
||||||
|
requests_mock.get("https://1.2.3.4:32400/playQueues/1235", status_code=404)
|
||||||
|
content_id_with_playqueue = '{"playqueue_id": 1235}'
|
||||||
|
with pytest.raises(HomeAssistantError) as excinfo:
|
||||||
|
play_on_sonos(
|
||||||
|
hass, MEDIA_TYPE_MUSIC, content_id_with_playqueue, sonos_speaker_name
|
||||||
|
)
|
||||||
|
assert "PlayQueue '1235' could not be found" in str(excinfo.value)
|
||||||
|
assert playback_mock.call_count == 4
|
||||||
|
8
tests/fixtures/plex/media_100.xml
vendored
8
tests/fixtures/plex/media_100.xml
vendored
@ -1 +1,7 @@
|
|||||||
<MediaContainer allowSync="1" identifier="com.plexapp.plugins.library" librarySectionID="3" librarySectionTitle="Music" librarySectionUUID="005308ec-5019-43d4-a449-75d2b9e42f93" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1603922053" size="1"><Track addedAt="1600999261" art="/library/metadata/300/art/1605462131" duration="250000" grandparentArt="/library/metadata/300/art/1605462131" grandparentGuid="plex://artist/12345" grandparentKey="/library/metadata/300" grandparentRatingKey="300" grandparentThumb="/library/metadata/300/thumb/1605462131" grandparentTitle="Arist Name" guid="plex://track/12345" index="1" key="/library/metadata/100" lastViewedAt="1603309346" librarySectionID="3" librarySectionKey="/library/sections/3" librarySectionTitle="Music" parentGuid="plex://album/12345" parentIndex="1" parentKey="/library/metadata/200" parentRatingKey="200" parentThumb="/library/metadata/200/thumb/1605462119" parentTitle="Album Title" ratingKey="100" summary="" thumb="/library/metadata/200/thumb/1605462119" title="Track 1" type="track" updatedAt="1605462119" viewCount="1"><Media audioChannels="2" audioCodec="mp3" bitrate="256" container="mp3" duration="250000" id="381515" /><Part container="mp3" duration="250000" file="/storage/music/Artist Name/Album Name/Track Name.mp3" id="381939" key="/library/parts/381939/1602996958/file.mp3" size="5000000" /><Stream albumGain="-10.34" albumPeak="1.000000" albumRange="8.429853" audioChannelLayout="stereo" bitrate="256" channels="2" codec="mp3" displayTitle="Unknown (MP3 Stereo)" extendedDisplayTitle="Unknown (MP3 Stereo)" gain="-10.34" id="766687" index="0" loudness="-11.38" lra="7.80" peak="0.870300" samplingRate="44100" selected="1" streamType="2" /></Track></MediaContainer>
|
<MediaContainer allowSync="1" identifier="com.plexapp.plugins.library" librarySectionID="3" librarySectionTitle="Music" librarySectionUUID="005308ec-5019-43d4-a449-75d2b9e42f93" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1603922053" size="1">
|
||||||
|
<Track addedAt="1600999261" art="/library/metadata/300/art/1605462131" duration="250000" grandparentArt="/library/metadata/300/art/1605462131" grandparentGuid="plex://artist/12345" grandparentKey="/library/metadata/300" grandparentRatingKey="300" grandparentThumb="/library/metadata/300/thumb/1605462131" grandparentTitle="Artist Name" guid="plex://track/12345" index="1" key="/library/metadata/100" lastViewedAt="1603309346" librarySectionID="3" librarySectionKey="/library/sections/3" librarySectionTitle="Music" parentGuid="plex://album/12345" parentIndex="1" parentKey="/library/metadata/200" parentRatingKey="200" parentThumb="/library/metadata/200/thumb/1605462119" parentTitle="Album Title" ratingKey="100" summary="" thumb="/library/metadata/200/thumb/1605462119" title="Track 1" type="track" updatedAt="1605462119" viewCount="1">
|
||||||
|
<Media audioChannels="2" audioCodec="mp3" bitrate="256" container="mp3" duration="250000" id="381515" />
|
||||||
|
<Part container="mp3" duration="250000" file="/storage/music/Artist Name/Album Name/Track Name.mp3" id="381939" key="/library/parts/381939/1602996958/file.mp3" size="5000000" />
|
||||||
|
<Stream albumGain="-10.34" albumPeak="1.000000" albumRange="8.429853" audioChannelLayout="stereo" bitrate="256" channels="2" codec="mp3" displayTitle="Unknown (MP3 Stereo)" extendedDisplayTitle="Unknown (MP3 Stereo)" gain="-10.34" id="766687" index="0" loudness="-11.38" lra="7.80" peak="0.870300" samplingRate="44100" selected="1" streamType="2" />
|
||||||
|
</Track>
|
||||||
|
</MediaContainer>
|
||||||
|
7
tests/fixtures/plex/playqueue_1234.xml
vendored
Normal file
7
tests/fixtures/plex/playqueue_1234.xml
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<MediaContainer size="1" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1608235013" playQueueID="1234" playQueueSelectedItemID="10234" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="100" playQueueShuffled="0" playQueueSourceURI="library://005308ec-5019-43d4-a449-75d2b9e42f93/item//library/metadata/100" playQueueTotalCount="1" playQueueVersion="1">
|
||||||
|
<Track addedAt="1600999261" art="/library/metadata/300/art/1605462131" duration="250000" grandparentArt="/library/metadata/300/art/1605462131" grandparentGuid="plex://artist/12345" grandparentKey="/library/metadata/300" grandparentRatingKey="300" grandparentThumb="/library/metadata/300/thumb/1605462131" grandparentTitle="Artist Name" guid="plex://track/12345" index="1" key="/library/metadata/100" lastViewedAt="1603309346" librarySectionID="3" librarySectionKey="/library/sections/3" librarySectionTitle="Music" parentGuid="plex://album/12345" parentIndex="1" parentKey="/library/metadata/200" parentRatingKey="200" parentThumb="/library/metadata/200/thumb/1605462119" parentTitle="Album Title" ratingKey="100" summary="" thumb="/library/metadata/200/thumb/1605462119" title="Track 1" type="track" updatedAt="1605462119" viewCount="1">
|
||||||
|
<Media audioChannels="2" audioCodec="mp3" bitrate="256" container="mp3" duration="250000" id="381515" />
|
||||||
|
<Part container="mp3" duration="250000" file="/storage/music/Artist Name/Album Name/Track Name.mp3" id="381939" key="/library/parts/381939/1602996958/file.mp3" size="5000000" />
|
||||||
|
<Stream albumGain="-10.34" albumPeak="1.000000" albumRange="8.429853" audioChannelLayout="stereo" bitrate="256" channels="2" codec="mp3" displayTitle="Unknown (MP3 Stereo)" extendedDisplayTitle="Unknown (MP3 Stereo)" gain="-10.34" id="766687" index="0" loudness="-11.38" lra="7.80" peak="0.870300" samplingRate="44100" selected="1" streamType="2" />
|
||||||
|
</Track>
|
||||||
|
</MediaContainer>
|
Loading…
x
Reference in New Issue
Block a user