Show cast as playing when an app without media support is active (#59714)

This commit is contained in:
Erik Montnemery 2021-11-15 20:13:43 +01:00 committed by GitHub
parent eaaa53d8d5
commit e88ea2d48c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 26 deletions

View File

@ -79,11 +79,7 @@ _LOGGER = logging.getLogger(__name__)
CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png" CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png"
SUPPORT_CAST = ( SUPPORT_CAST = SUPPORT_PLAY_MEDIA | SUPPORT_TURN_OFF
SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_TURN_OFF
)
STATE_CASTING = "casting"
ENTITY_SCHEMA = vol.All( ENTITY_SCHEMA = vol.All(
vol.Schema( vol.Schema(
@ -567,7 +563,7 @@ class CastDevice(MediaPlayerEntity):
"""Return the state of the player.""" """Return the state of the player."""
# The lovelace app loops media to prevent timing out, don't show that # The lovelace app loops media to prevent timing out, don't show that
if self.app_id == CAST_APP_ID_HOMEASSISTANT_LOVELACE: if self.app_id == CAST_APP_ID_HOMEASSISTANT_LOVELACE:
return STATE_CASTING return STATE_PLAYING
if (media_status := self._media_status()[0]) is not None: if (media_status := self._media_status()[0]) is not None:
if media_status.player_is_playing: if media_status.player_is_playing:
return STATE_PLAYING return STATE_PLAYING
@ -576,7 +572,7 @@ class CastDevice(MediaPlayerEntity):
if media_status.player_is_idle: if media_status.player_is_idle:
return STATE_IDLE return STATE_IDLE
if self.app_id is not None and self.app_id != pychromecast.IDLE_APP_ID: if self.app_id is not None and self.app_id != pychromecast.IDLE_APP_ID:
return STATE_CASTING return STATE_PLAYING
if self._chromecast is not None and self._chromecast.is_idle: if self._chromecast is not None and self._chromecast.is_idle:
return STATE_OFF return STATE_OFF
return None return None
@ -701,7 +697,8 @@ class CastDevice(MediaPlayerEntity):
): ):
support |= SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET support |= SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET
if media_status: if media_status and self.app_id != CAST_APP_ID_HOMEASSISTANT_LOVELACE:
support |= SUPPORT_PAUSE | SUPPORT_PLAY | SUPPORT_STOP
if media_status.supports_queue_next: if media_status.supports_queue_next:
support |= SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK support |= SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK
if media_status.supports_seek: if media_status.supports_seek:

View File

@ -605,11 +605,9 @@ async def test_entity_cast_status(hass: HomeAssistant):
assert state.state == "off" assert state.state == "off"
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid) assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
# No media status, pause, play, stop not supported
assert state.attributes.get("supported_features") == ( assert state.attributes.get("supported_features") == (
SUPPORT_PAUSE SUPPORT_PLAY_MEDIA
| SUPPORT_PLAY
| SUPPORT_PLAY_MEDIA
| SUPPORT_STOP
| SUPPORT_TURN_OFF | SUPPORT_TURN_OFF
| SUPPORT_TURN_ON | SUPPORT_TURN_ON
| SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_MUTE
@ -652,17 +650,12 @@ async def test_entity_cast_status(hass: HomeAssistant):
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.attributes.get("supported_features") == ( assert state.attributes.get("supported_features") == (
SUPPORT_PAUSE SUPPORT_PLAY_MEDIA | SUPPORT_TURN_OFF | SUPPORT_TURN_ON
| SUPPORT_PLAY
| SUPPORT_PLAY_MEDIA
| SUPPORT_STOP
| SUPPORT_TURN_OFF
| SUPPORT_TURN_ON
) )
@pytest.mark.parametrize( @pytest.mark.parametrize(
"cast_type,supported_features", "cast_type,supported_features,supported_features_no_media",
[ [
( (
pychromecast.const.CAST_TYPE_AUDIO, pychromecast.const.CAST_TYPE_AUDIO,
@ -673,6 +666,10 @@ async def test_entity_cast_status(hass: HomeAssistant):
| SUPPORT_TURN_OFF | SUPPORT_TURN_OFF
| SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET, | SUPPORT_VOLUME_SET,
SUPPORT_PLAY_MEDIA
| SUPPORT_TURN_OFF
| SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET,
), ),
( (
pychromecast.const.CAST_TYPE_CHROMECAST, pychromecast.const.CAST_TYPE_CHROMECAST,
@ -684,6 +681,11 @@ async def test_entity_cast_status(hass: HomeAssistant):
| SUPPORT_TURN_ON | SUPPORT_TURN_ON
| SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET, | SUPPORT_VOLUME_SET,
SUPPORT_PLAY_MEDIA
| SUPPORT_TURN_OFF
| SUPPORT_TURN_ON
| SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET,
), ),
( (
pychromecast.const.CAST_TYPE_GROUP, pychromecast.const.CAST_TYPE_GROUP,
@ -694,10 +696,16 @@ async def test_entity_cast_status(hass: HomeAssistant):
| SUPPORT_TURN_OFF | SUPPORT_TURN_OFF
| SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET, | SUPPORT_VOLUME_SET,
SUPPORT_PLAY_MEDIA
| SUPPORT_TURN_OFF
| SUPPORT_VOLUME_MUTE
| SUPPORT_VOLUME_SET,
), ),
], ],
) )
async def test_supported_features(hass: HomeAssistant, cast_type, supported_features): async def test_supported_features(
hass: HomeAssistant, cast_type, supported_features, supported_features_no_media
):
"""Test supported features.""" """Test supported features."""
entity_id = "media_player.speaker" entity_id = "media_player.speaker"
@ -705,7 +713,7 @@ async def test_supported_features(hass: HomeAssistant, cast_type, supported_feat
chromecast, _ = await async_setup_media_player_cast(hass, info) chromecast, _ = await async_setup_media_player_cast(hass, info)
chromecast.cast_type = cast_type chromecast.cast_type = cast_type
_, conn_status_cb, _ = get_status_callbacks(chromecast) _, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
connection_status = MagicMock() connection_status = MagicMock()
connection_status.status = "CONNECTED" connection_status.status = "CONNECTED"
@ -716,7 +724,14 @@ async def test_supported_features(hass: HomeAssistant, cast_type, supported_feat
assert state is not None assert state is not None
assert state.name == "Speaker" assert state.name == "Speaker"
assert state.state == "off" assert state.state == "off"
assert state.attributes.get("supported_features") == supported_features_no_media
media_status = MagicMock(images=None)
media_status.supports_queue_next = False
media_status.supports_seek = False
media_status_cb(media_status)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.attributes.get("supported_features") == supported_features assert state.attributes.get("supported_features") == supported_features
@ -935,15 +950,23 @@ async def test_entity_control(hass: HomeAssistant):
chromecast.cast_type = pychromecast.const.CAST_TYPE_CHROMECAST chromecast.cast_type = pychromecast.const.CAST_TYPE_CHROMECAST
_, conn_status_cb, media_status_cb = get_status_callbacks(chromecast) _, conn_status_cb, media_status_cb = get_status_callbacks(chromecast)
# Fake connection status
connection_status = MagicMock() connection_status = MagicMock()
connection_status.status = "CONNECTED" connection_status.status = "CONNECTED"
conn_status_cb(connection_status) conn_status_cb(connection_status)
await hass.async_block_till_done() await hass.async_block_till_done()
# Fake media status
media_status = MagicMock(images=None)
media_status.supports_queue_next = False
media_status.supports_seek = False
media_status_cb(media_status)
await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state is not None assert state is not None
assert state.name == "Speaker" assert state.name == "Speaker"
assert state.state == "off" assert state.state == "playing"
assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid) assert entity_id == reg.async_get_entity_id("media_player", "cast", full_info.uuid)
assert state.attributes.get("supported_features") == ( assert state.attributes.get("supported_features") == (
@ -1119,28 +1142,31 @@ async def test_entity_media_states_lovelace_app(hass: HomeAssistant):
cast_status_cb(cast_status) cast_status_cb(cast_status)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "casting" assert state.state == "playing"
assert state.attributes.get("supported_features") == (
SUPPORT_PLAY_MEDIA | SUPPORT_TURN_OFF | SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET
)
media_status = MagicMock(images=None) media_status = MagicMock(images=None)
media_status.player_is_playing = True media_status.player_is_playing = True
media_status_cb(media_status) media_status_cb(media_status)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "casting" assert state.state == "playing"
media_status.player_is_playing = False media_status.player_is_playing = False
media_status.player_is_paused = True media_status.player_is_paused = True
media_status_cb(media_status) media_status_cb(media_status)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "casting" assert state.state == "playing"
media_status.player_is_paused = False media_status.player_is_paused = False
media_status.player_is_idle = True media_status.player_is_idle = True
media_status_cb(media_status) media_status_cb(media_status)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state.state == "casting" assert state.state == "playing"
chromecast.app_id = pychromecast.IDLE_APP_ID chromecast.app_id = pychromecast.IDLE_APP_ID
media_status.player_is_idle = False media_status.player_is_idle = False