Handle missing mpd capabilities (#15945)

* Handle missing mpd capabilities

It is possible to configure mpd without volume or playlist support.
Gracefully degrade when either of these features appears to be missing.

Resolves: #14459, #15927

* Use longer name for exception

* Only return support flags post-connection

* Small consistency fixes to mpd.py for review.
This commit is contained in:
Ed Marshall 2018-08-18 00:54:23 -07:00 committed by Martin Hjelmare
parent ec2e94425e
commit e782e2c0f3

View File

@ -32,9 +32,8 @@ DEFAULT_PORT = 6600
PLAYLIST_UPDATE_INTERVAL = timedelta(seconds=120) PLAYLIST_UPDATE_INTERVAL = timedelta(seconds=120)
SUPPORT_MPD = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_STEP | \ SUPPORT_MPD = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | \
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_VOLUME_MUTE | \ SUPPORT_NEXT_TRACK | SUPPORT_PLAY_MEDIA | SUPPORT_PLAY | \
SUPPORT_PLAY_MEDIA | SUPPORT_PLAY | SUPPORT_SELECT_SOURCE | \
SUPPORT_CLEAR_PLAYLIST | SUPPORT_SHUFFLE_SET | SUPPORT_SEEK | \ SUPPORT_CLEAR_PLAYLIST | SUPPORT_SHUFFLE_SET | SUPPORT_SEEK | \
SUPPORT_STOP | SUPPORT_TURN_OFF | SUPPORT_TURN_ON SUPPORT_STOP | SUPPORT_TURN_OFF | SUPPORT_TURN_ON
@ -72,7 +71,7 @@ class MpdDevice(MediaPlayerDevice):
self._status = None self._status = None
self._currentsong = None self._currentsong = None
self._playlists = [] self._playlists = None
self._currentplaylist = None self._currentplaylist = None
self._is_connected = False self._is_connected = False
self._muted = False self._muted = False
@ -202,12 +201,24 @@ class MpdDevice(MediaPlayerDevice):
@property @property
def volume_level(self): def volume_level(self):
"""Return the volume level.""" """Return the volume level."""
return int(self._status['volume'])/100 if 'volume' in self._status:
return int(self._status['volume'])/100
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."""
return SUPPORT_MPD if self._status is None:
return None
supported = SUPPORT_MPD
if 'volume' in self._status:
supported |= \
SUPPORT_VOLUME_SET | SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE
if self._playlists is not None:
supported |= SUPPORT_SELECT_SOURCE
return supported
@property @property
def source(self): def source(self):
@ -226,27 +237,36 @@ class MpdDevice(MediaPlayerDevice):
@Throttle(PLAYLIST_UPDATE_INTERVAL) @Throttle(PLAYLIST_UPDATE_INTERVAL)
def _update_playlists(self, **kwargs): def _update_playlists(self, **kwargs):
"""Update available MPD playlists.""" """Update available MPD playlists."""
self._playlists = [] import mpd
for playlist_data in self._client.listplaylists():
self._playlists.append(playlist_data['playlist']) try:
self._playlists = []
for playlist_data in self._client.listplaylists():
self._playlists.append(playlist_data['playlist'])
except mpd.CommandError as error:
self._playlists = None
_LOGGER.warning("Playlists could not be updated: %s:", error)
def set_volume_level(self, volume): def set_volume_level(self, volume):
"""Set volume of media player.""" """Set volume of media player."""
self._client.setvol(int(volume * 100)) if 'volume' in self._status:
self._client.setvol(int(volume * 100))
def volume_up(self): def volume_up(self):
"""Service to send the MPD the command for volume up.""" """Service to send the MPD the command for volume up."""
current_volume = int(self._status['volume']) if 'volume' in self._status:
current_volume = int(self._status['volume'])
if current_volume <= 100: if current_volume <= 100:
self._client.setvol(current_volume + 5) self._client.setvol(current_volume + 5)
def volume_down(self): def volume_down(self):
"""Service to send the MPD the command for volume down.""" """Service to send the MPD the command for volume down."""
current_volume = int(self._status['volume']) if 'volume' in self._status:
current_volume = int(self._status['volume'])
if current_volume >= 0: if current_volume >= 0:
self._client.setvol(current_volume - 5) self._client.setvol(current_volume - 5)
def media_play(self): def media_play(self):
"""Service to send the MPD the command for play/pause.""" """Service to send the MPD the command for play/pause."""
@ -270,12 +290,13 @@ class MpdDevice(MediaPlayerDevice):
def mute_volume(self, mute): def mute_volume(self, mute):
"""Mute. Emulated with set_volume_level.""" """Mute. Emulated with set_volume_level."""
if mute is True: if 'volume' in self._status:
self._muted_volume = self.volume_level if mute:
self.set_volume_level(0) self._muted_volume = self.volume_level
elif mute is False: self.set_volume_level(0)
self.set_volume_level(self._muted_volume) else:
self._muted = mute self.set_volume_level(self._muted_volume)
self._muted = mute
def play_media(self, media_type, media_id, **kwargs): def play_media(self, media_type, media_id, **kwargs):
"""Send the media player the command for playing a playlist.""" """Send the media player the command for playing a playlist."""