Shuffle support in Sonos (#10875)

* initial commit of shuffle option for sonos

* added test

* Small adjustments to adhere to review requests

* Removed unnessesary setting of variable. Use shuffle state from soco instead
pull/10765/head
Marcus Schmidt 2017-12-07 20:44:06 +01:00 committed by Adam Mills
parent 3c1f8cd882
commit 929d49ed6f
2 changed files with 34 additions and 4 deletions

View File

@ -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

View File

@ -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')