Add new features to Apple TV media player (#45828)

This commit is contained in:
Pierre Ståhl 2021-02-06 21:29:48 +01:00 committed by GitHub
parent 60e3fce7dc
commit cefde8721d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 24 deletions

View File

@ -180,20 +180,23 @@ class AppleTVManager:
This is a callback function from pyatv.interface.DeviceListener. This is a callback function from pyatv.interface.DeviceListener.
""" """
_LOGGER.warning('Connection lost to Apple TV "%s"', self.atv.name) _LOGGER.warning(
if self.atv: 'Connection lost to Apple TV "%s"', self.config_entry.data.get(CONF_NAME)
self.atv.close() )
self.atv = None
self._connection_was_lost = True self._connection_was_lost = True
self._dispatch_send(SIGNAL_DISCONNECTED) self._handle_disconnect()
self._start_connect_loop()
def connection_closed(self): def connection_closed(self):
"""Device connection was (intentionally) closed. """Device connection was (intentionally) closed.
This is a callback function from pyatv.interface.DeviceListener. This is a callback function from pyatv.interface.DeviceListener.
""" """
self._handle_disconnect()
def _handle_disconnect(self):
"""Handle that the device disconnected and restart connect loop."""
if self.atv: if self.atv:
self.atv.listener = None
self.atv.close() self.atv.close()
self.atv = None self.atv = None
self._dispatch_send(SIGNAL_DISCONNECTED) self._dispatch_send(SIGNAL_DISCONNECTED)

View File

@ -1,22 +1,35 @@
"""Support for Apple TV media player.""" """Support for Apple TV media player."""
import logging import logging
from pyatv.const import DeviceState, FeatureName, FeatureState, MediaType from pyatv.const import (
DeviceState,
FeatureName,
FeatureState,
MediaType,
RepeatState,
ShuffleState,
)
from homeassistant.components.media_player import MediaPlayerEntity from homeassistant.components.media_player import MediaPlayerEntity
from homeassistant.components.media_player.const import ( from homeassistant.components.media_player.const import (
MEDIA_TYPE_MUSIC, MEDIA_TYPE_MUSIC,
MEDIA_TYPE_TVSHOW, MEDIA_TYPE_TVSHOW,
MEDIA_TYPE_VIDEO, MEDIA_TYPE_VIDEO,
REPEAT_MODE_ALL,
REPEAT_MODE_OFF,
REPEAT_MODE_ONE,
SUPPORT_NEXT_TRACK, SUPPORT_NEXT_TRACK,
SUPPORT_PAUSE, SUPPORT_PAUSE,
SUPPORT_PLAY, SUPPORT_PLAY,
SUPPORT_PLAY_MEDIA, SUPPORT_PLAY_MEDIA,
SUPPORT_PREVIOUS_TRACK, SUPPORT_PREVIOUS_TRACK,
SUPPORT_REPEAT_SET,
SUPPORT_SEEK, SUPPORT_SEEK,
SUPPORT_SHUFFLE_SET,
SUPPORT_STOP, SUPPORT_STOP,
SUPPORT_TURN_OFF, SUPPORT_TURN_OFF,
SUPPORT_TURN_ON, SUPPORT_TURN_ON,
SUPPORT_VOLUME_STEP,
) )
from homeassistant.const import ( from homeassistant.const import (
CONF_NAME, CONF_NAME,
@ -46,6 +59,9 @@ SUPPORT_APPLE_TV = (
| SUPPORT_STOP | SUPPORT_STOP
| SUPPORT_NEXT_TRACK | SUPPORT_NEXT_TRACK
| SUPPORT_PREVIOUS_TRACK | SUPPORT_PREVIOUS_TRACK
| SUPPORT_VOLUME_STEP
| SUPPORT_REPEAT_SET
| SUPPORT_SHUFFLE_SET
) )
@ -110,17 +126,15 @@ class AppleTvMediaPlayer(AppleTVEntity, MediaPlayerEntity):
@property @property
def app_id(self): def app_id(self):
"""ID of the current running app.""" """ID of the current running app."""
if self.atv: if self._is_feature_available(FeatureName.App):
if self.atv.features.in_state(FeatureState.Available, FeatureName.App): return self.atv.metadata.app.identifier
return self.atv.metadata.app.identifier
return None return None
@property @property
def app_name(self): def app_name(self):
"""Name of the current running app.""" """Name of the current running app."""
if self.atv: if self._is_feature_available(FeatureName.App):
if self.atv.features.in_state(FeatureState.Available, FeatureName.App): return self.atv.metadata.app.name
return self.atv.metadata.app.name
return None return None
@property @property
@ -198,6 +212,23 @@ class AppleTvMediaPlayer(AppleTVEntity, MediaPlayerEntity):
return self._playing.album return self._playing.album
return None return None
@property
def repeat(self):
"""Return current repeat mode."""
if self._is_feature_available(FeatureName.Repeat):
return {
RepeatState.Track: REPEAT_MODE_ONE,
RepeatState.All: REPEAT_MODE_ALL,
}.get(self._playing.repeat, REPEAT_MODE_OFF)
return None
@property
def shuffle(self):
"""Boolean if shuffle is enabled."""
if self._is_feature_available(FeatureName.Shuffle):
return self._playing.shuffle != ShuffleState.Off
return None
@property @property
def supported_features(self): def supported_features(self):
"""Flag media player features that are supported.""" """Flag media player features that are supported."""
@ -221,39 +252,61 @@ class AppleTvMediaPlayer(AppleTVEntity, MediaPlayerEntity):
async def async_media_play_pause(self): async def async_media_play_pause(self):
"""Pause media on media player.""" """Pause media on media player."""
if self._playing: if self._playing:
state = self.state await self.atv.remote_control.play_pause()
if state == STATE_PAUSED:
await self.atv.remote_control.play()
elif state == STATE_PLAYING:
await self.atv.remote_control.pause()
return None return None
async def async_media_play(self): async def async_media_play(self):
"""Play media.""" """Play media."""
if self._playing: if self.atv:
await self.atv.remote_control.play() await self.atv.remote_control.play()
async def async_media_stop(self): async def async_media_stop(self):
"""Stop the media player.""" """Stop the media player."""
if self._playing: if self.atv:
await self.atv.remote_control.stop() await self.atv.remote_control.stop()
async def async_media_pause(self): async def async_media_pause(self):
"""Pause the media player.""" """Pause the media player."""
if self._playing: if self.atv:
await self.atv.remote_control.pause() await self.atv.remote_control.pause()
async def async_media_next_track(self): async def async_media_next_track(self):
"""Send next track command.""" """Send next track command."""
if self._playing: if self.atv:
await self.atv.remote_control.next() await self.atv.remote_control.next()
async def async_media_previous_track(self): async def async_media_previous_track(self):
"""Send previous track command.""" """Send previous track command."""
if self._playing: if self.atv:
await self.atv.remote_control.previous() await self.atv.remote_control.previous()
async def async_media_seek(self, position): async def async_media_seek(self, position):
"""Send seek command.""" """Send seek command."""
if self._playing: if self.atv:
await self.atv.remote_control.set_position(position) await self.atv.remote_control.set_position(position)
async def async_volume_up(self):
"""Turn volume up for media player."""
if self.atv:
await self.atv.remote_control.volume_up()
async def async_volume_down(self):
"""Turn volume down for media player."""
if self.atv:
await self.atv.remote_control.volume_down()
async def async_set_repeat(self, repeat):
"""Set repeat mode."""
if self.atv:
mode = {
REPEAT_MODE_ONE: RepeatState.Track,
REPEAT_MODE_ALL: RepeatState.All,
}.get(repeat, RepeatState.Off)
await self.atv.remote_control.set_repeat(mode)
async def async_set_shuffle(self, shuffle):
"""Enable/disable shuffle mode."""
if self.atv:
await self.atv.remote_control.set_shuffle(
ShuffleState.Songs if shuffle else ShuffleState.Off
)