diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index 47786e793ca..61c2773df05 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -19,7 +19,7 @@ from homeassistant.components.media_player import ( SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_CLEAR_PLAYLIST, SUPPORT_SELECT_SOURCE, MediaPlayerDevice, PLATFORM_SCHEMA, SUPPORT_STOP, - SUPPORT_PLAY) + SUPPORT_PLAY, SUPPORT_SHUFFLE_SET) from homeassistant.const import ( STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_OFF, ATTR_ENTITY_ID, CONF_HOSTS, ATTR_TIME) @@ -43,7 +43,7 @@ _REQUESTS_LOGGER.setLevel(logging.ERROR) SUPPORT_SONOS = SUPPORT_STOP | SUPPORT_PAUSE | SUPPORT_VOLUME_SET |\ SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK |\ SUPPORT_PLAY_MEDIA | SUPPORT_SEEK | SUPPORT_CLEAR_PLAYLIST |\ - SUPPORT_SELECT_SOURCE | SUPPORT_PLAY + SUPPORT_SELECT_SOURCE | SUPPORT_PLAY | SUPPORT_SHUFFLE_SET SERVICE_JOIN = 'sonos_join' SERVICE_UNJOIN = 'sonos_unjoin' @@ -331,6 +331,7 @@ class SonosDevice(MediaPlayerDevice): self._support_previous_track = False self._support_next_track = False self._support_play = False + self._support_shuffle_set = True self._support_stop = False self._support_pause = False self._current_track_uri = None @@ -450,6 +451,7 @@ class SonosDevice(MediaPlayerDevice): self._support_previous_track = False self._support_next_track = False self._support_play = False + self._support_shuffle_set = False self._support_stop = False self._support_pause = False self._is_playing_tv = False @@ -536,6 +538,7 @@ class SonosDevice(MediaPlayerDevice): support_play = False support_stop = True support_pause = False + support_shuffle_set = False if is_playing_tv: media_artist = SUPPORT_SOURCE_TV @@ -558,6 +561,7 @@ class SonosDevice(MediaPlayerDevice): support_play = True support_stop = True support_pause = False + support_shuffle_set = False source_name = 'Radio' # Check if currently playing radio station is in favorites @@ -622,6 +626,7 @@ class SonosDevice(MediaPlayerDevice): support_play = True support_stop = True support_pause = True + support_shuffle_set = True position_info = self._player.avTransport.GetPositionInfo( [('InstanceID', 0), @@ -694,6 +699,7 @@ class SonosDevice(MediaPlayerDevice): self._support_previous_track = support_previous_track self._support_next_track = support_next_track self._support_play = support_play + self._support_shuffle_set = support_shuffle_set self._support_stop = support_stop self._support_pause = support_pause self._is_playing_tv = is_playing_tv @@ -762,6 +768,11 @@ class SonosDevice(MediaPlayerDevice): """Return true if volume is muted.""" return self._player_volume_muted + @property + def shuffle(self): + """Shuffling state.""" + return True if self._player.play_mode == 'SHUFFLE' else False + @property def media_content_id(self): """Content ID of current playing media.""" @@ -850,7 +861,8 @@ class SonosDevice(MediaPlayerDevice): if not self._support_play: supported = supported ^ SUPPORT_PLAY - + if not self._support_shuffle_set: + supported = supported ^ SUPPORT_SHUFFLE_SET if not self._support_stop: supported = supported ^ SUPPORT_STOP @@ -874,6 +886,11 @@ class SonosDevice(MediaPlayerDevice): """Set volume level, range 0..1.""" self._player.volume = str(int(volume * 100)) + @soco_error + def set_shuffle(self, shuffle): + """Enable/Disable shuffle mode.""" + self._player.play_mode = 'SHUFFLE' if shuffle else 'NORMAL' + @soco_error def mute_volume(self, mute): """Mute (true) or unmute (false) media player.""" @@ -932,7 +949,6 @@ class SonosDevice(MediaPlayerDevice): self._player.stop() self._player.clear_queue() - self._player.play_mode = 'NORMAL' self._player.add_to_queue(didl) @property diff --git a/tests/components/media_player/test_sonos.py b/tests/components/media_player/test_sonos.py index 8c62c6c84e9..33f7a0e882d 100644 --- a/tests/components/media_player/test_sonos.py +++ b/tests/components/media_player/test_sonos.py @@ -281,6 +281,20 @@ class TestSonosMediaPlayer(unittest.TestCase): self.assertEqual(unjoinMock.call_count, 1) self.assertEqual(unjoinMock.call_args, mock.call()) + @mock.patch('soco.SoCo', new=SoCoMock) + @mock.patch('socket.create_connection', side_effect=socket.error()) + def test_set_shuffle(self, shuffle_set_mock, *args): + """Ensuring soco methods called for sonos_snapshot service.""" + sonos.setup_platform(self.hass, {}, fake_add_device, { + 'host': '192.0.2.1' + }) + device = self.hass.data[sonos.DATA_SONOS][-1] + device.hass = self.hass + + device.set_shuffle(True) + self.assertEqual(shuffle_set_mock.call_count, 1) + self.assertEqual(device._player.play_mode, 'SHUFFLE') + @mock.patch('soco.SoCo', new=SoCoMock) @mock.patch('socket.create_connection', side_effect=socket.error()) @mock.patch.object(SoCoMock, 'set_sleep_timer')