Skip to content

Commit

Permalink
Add 'trueplay' property to SoCo (#775)
Browse files Browse the repository at this point in the history
  • Loading branch information
pwt committed Dec 27, 2020
1 parent 83e35da commit 35b23b8
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
47 changes: 47 additions & 0 deletions soco/core.py
Expand Up @@ -201,6 +201,7 @@ class SoCo(_SocoSingletonBase):
dialog_mode
supports_fixed_volume
fixed_volume
trueplay
status_light
buttons_enabled
Expand Down Expand Up @@ -960,6 +961,52 @@ def dialog_mode(self, dialog_mode):
]
)

@property
def trueplay(self):
"""bool: Whether Trueplay is enabled on this device.
True if on, False if off.
Devices that do not support Trueplay, or which do not have
a current Trueplay calibration, will return `None` on getting
the property, and raise a `NotSupportedException` when
setting the property.
Can only be set on visible devices. Attempting to set on non-visible
devices will raise a `SoCoNotVisibleException`.
"""
response = self.renderingControl.GetRoomCalibrationStatus([("InstanceID", 0)])
if response["RoomCalibrationAvailable"] == "0":
return None
else:
return response["RoomCalibrationEnabled"] == "1"

@trueplay.setter
def trueplay(self, trueplay):
"""Toggle the device's TruePlay setting. Only available to
Sonos speakers, not the Connect, Amp, etc., and only available to
speakers that have a current Trueplay calibration.
:param trueplay: Enable or disable Trueplay.
:type trueplay: bool
:raises NotSupportedException: If the device does not support
Trueplay or doesn't have a current calibration.
:raises SoCoNotVisibleException: If the device is not visible.
"""
response = self.renderingControl.GetRoomCalibrationStatus([("InstanceID", 0)])
if response["RoomCalibrationAvailable"] == "0":
raise NotSupportedException

if not self.is_visible:
raise SoCoNotVisibleException

trueplay_value = "1" if trueplay else "0"
self.renderingControl.SetRoomCalibrationStatus(
[
("InstanceID", 0),
("RoomCalibrationEnabled", trueplay_value),
]
)

@property
def supports_fixed_volume(self):
"""bool: Whether the device supports fixed volume output."""
Expand Down
46 changes: 43 additions & 3 deletions tests/test_core.py
Expand Up @@ -6,14 +6,12 @@

from soco import SoCo
from soco.data_structures import DidlMusicTrack, to_didl_string

from soco.exceptions import (
SoCoSlaveException,
SoCoUPnPException,
SoCoNotVisibleException,
NotSupportedException,
)

from soco.groups import ZoneGroup
from soco.xml import XML

Expand Down Expand Up @@ -1155,6 +1153,49 @@ def test_soco_loudness(self, moco):
[("InstanceID", 0), ("Channel", "Master"), ("DesiredLoudness", "0")]
)

def test_soco_trueplay(self, moco):
moco.renderingControl.GetRoomCalibrationStatus.return_value = {
"RoomCalibrationAvailable": "0",
"RoomCalibrationEnabled": "0",
}
assert moco.trueplay is None
moco.renderingControl.GetRoomCalibrationStatus.assert_called_with(
[("InstanceID", 0)]
)
moco.renderingControl.GetRoomCalibrationStatus.return_value = {
"RoomCalibrationAvailable": "1",
"RoomCalibrationEnabled": "1",
}
assert moco.trueplay
moco.renderingControl.GetRoomCalibrationStatus.assert_called_with(
[("InstanceID", 0)]
)
# Setter tests for 'is_visible' property, so this needs to be
# mocked.
with mock.patch(
"soco.SoCo.is_visible", new_callable=mock.PropertyMock
) as mock_is_visible:
mock_is_visible.return_value = True
moco.trueplay = False
moco.renderingControl.SetRoomCalibrationStatus.assert_called_with(
[
("InstanceID", 0),
("RoomCalibrationEnabled", "0"),
]
)
moco.trueplay = True
moco.renderingControl.SetRoomCalibrationStatus.assert_called_with(
[
("InstanceID", 0),
("RoomCalibrationEnabled", "1"),
]
)
# Check for exception if attempt to set the property on a
# non-visible speaker.
mock_is_visible.return_value = False
with pytest.raises(SoCoNotVisibleException):
moco.trueplay = True

def test_soco_fixed_volume(self, moco):
moco.renderingControl.GetSupportsOutputFixed.return_value = {
"CurrentSupportsFixed": "1"
Expand All @@ -1170,7 +1211,6 @@ def test_soco_fixed_volume(self, moco):
moco.renderingControl.GetSupportsOutputFixed.assert_called_with(
[("InstanceID", 0)]
)

moco.renderingControl.GetOutputFixed.return_value = {"CurrentFixed": "1"}
assert moco.fixed_volume
moco.renderingControl.GetOutputFixed.assert_called_once_with(
Expand Down

0 comments on commit 35b23b8

Please sign in to comment.