[sonos] Add bass/treble/loudness controls (#9918)

* [sonos] Add bass/treble/loudness controls

Related to #9874

Disable these controls when the output level is fixed

* Review suggestion: use OnOffType.from
* Add bass/treble/loudness channels to Arc and Arc SL models
* Review comment: remove usage of keySet

Factorize code
Define constants

* Use Map.of to simplify the code
* Review comments considered

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2021-01-25 17:50:45 +01:00 committed by GitHub
parent f926cd8080
commit 163806e322
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 321 additions and 280 deletions

View File

@ -51,6 +51,7 @@ The devices support the following channels:
| alarm | Switch | W | Set the first occurring alarm either ON or OFF. Alarms first have to be defined through the Sonos Controller app | all |
| alarmproperties | String | R | Properties of the alarm currently running | all |
| alarmrunning | Switch | R | Set to ON if the alarm was triggered | all |
| bass | Number | RW | Set or get the bass level adjustment (value in range -10 / 10) | all |
| clearqueue | Switch | W | Suppress all songs from the current queue | all |
| control | Player | RW | Control the Zone Player, e.g. PLAY/PAUSE/NEXT/PREVIOUS | all |
| coordinator | String | R | UDN of the coordinator for the current group | all |
@ -68,6 +69,7 @@ The devices support the following channels:
| analoglinein | Switch | R | Indicator set to ON when the analog line-in of the Zone Player is connected | Amp |
| digitallinein | Switch | R | Indicator set to ON when the digital line-in of the Zone Player is connected | Amp |
| localcoordinator | Switch | R | Indicator set to ON if the this Zone Player is the Zone Group Coordinator | all |
| loudness | Switch | RW | Enable or disable the loudness | all |
| mute | Switch | RW | Set or get the mute state of the master volume of the Zone Player | all |
| nightmode | Switch | RW | Enable or disable the night mode feature | PLAYBAR, PLAYBASE, Beam, Amp |
| notificationsound | String | W | Play a notification sound by a given URI | all |
@ -93,6 +95,7 @@ The devices support the following channels:
| standalone | Switch | W | Make the Zone Player leave its Group and become a standalone Zone Player | all |
| state | String | R | The State channel contains state of the Zone Player, e.g. PLAYING, STOPPED, ... | all |
| stop | Switch | W | Write `ON` to this channel: Stops the Zone Player player. | all |
| treble | Number | RW | Set or get the treble level adjustment (value in range -10 / 10) | all |
| subwoofer | Switch | RW | Enable or disable the subwoofer | Arc, Arc SL |
| subwoofergain | Number | RW | Set or get the subwoofer gain adjustment (value in range -15 / 15) | Arc, Arc SL |
| surround | Switch | RW | Enable or disable the surround audio | Arc, Arc SL |

View File

@ -81,6 +81,7 @@ public class SonosBindingConstants {
public static final String ALARM = "alarm";
public static final String ALARMPROPERTIES = "alarmproperties";
public static final String ALARMRUNNING = "alarmrunning";
public static final String BASS = "bass";
public static final String CLEARQUEUE = "clearqueue";
public static final String CONTROL = "control";
public static final String COORDINATOR = "coordinator";
@ -98,6 +99,7 @@ public class SonosBindingConstants {
public static final String ANALOGLINEIN = "analoglinein";
public static final String DIGITALLINEIN = "digitallinein";
public static final String LOCALCOORDINATOR = "localcoordinator";
public static final String LOUDNESS = "loudness";
public static final String MUTE = "mute";
public static final String NIGHTMODE = "nightmode";
public static final String NOTIFICATIONSOUND = "notificationsound";
@ -123,6 +125,7 @@ public class SonosBindingConstants {
public static final String STANDALONE = "standalone";
public static final String STATE = "state";
public static final String STOP = "stop";
public static final String TREBLE = "treble";
public static final String SUBWOOFER = "subwoofer";
public static final String SUBWOOFERGAIN = "subwoofergain";
public static final String SURROUND = "surround";

View File

@ -103,14 +103,60 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
private static final String LINEINCONNECTED = "LineInConnected";
private static final String TOSLINEINCONNECTED = "TOSLinkConnected";
private static final Collection<String> SERVICE_SUBSCRIPTIONS = Arrays.asList("DeviceProperties", "AVTransport",
"ZoneGroupTopology", "GroupManagement", "RenderingControl", "AudioIn", "HTControl", "ContentDirectory");
private static final String SERVICE_DEVICE_PROPERTIES = "DeviceProperties";
private static final String SERVICE_AV_TRANSPORT = "AVTransport";
private static final String SERVICE_RENDERING_CONTROL = "RenderingControl";
private static final String SERVICE_ZONE_GROUP_TOPOLOGY = "ZoneGroupTopology";
private static final String SERVICE_GROUP_MANAGEMENT = "GroupManagement";
private static final String SERVICE_AUDIO_IN = "AudioIn";
private static final String SERVICE_HT_CONTROL = "HTControl";
private static final String SERVICE_CONTENT_DIRECTORY = "ContentDirectory";
private static final String SERVICE_ALARM_CLOCK = "AlarmClock";
private static final Collection<String> SERVICE_SUBSCRIPTIONS = Arrays.asList(SERVICE_DEVICE_PROPERTIES,
SERVICE_AV_TRANSPORT, SERVICE_ZONE_GROUP_TOPOLOGY, SERVICE_GROUP_MANAGEMENT, SERVICE_RENDERING_CONTROL,
SERVICE_AUDIO_IN, SERVICE_HT_CONTROL, SERVICE_CONTENT_DIRECTORY);
protected static final int SUBSCRIPTION_DURATION = 1800;
private static final String ACTION_GET_ZONE_ATTRIBUTES = "GetZoneAttributes";
private static final String ACTION_GET_ZONE_INFO = "GetZoneInfo";
private static final String ACTION_GET_LED_STATE = "GetLEDState";
private static final String ACTION_SET_LED_STATE = "SetLEDState";
private static final String ACTION_GET_POSITION_INFO = "GetPositionInfo";
private static final String ACTION_SET_AV_TRANSPORT_URI = "SetAVTransportURI";
private static final String ACTION_SEEK = "Seek";
private static final String ACTION_PLAY = "Play";
private static final String ACTION_STOP = "Stop";
private static final String ACTION_PAUSE = "Pause";
private static final String ACTION_PREVIOUS = "Previous";
private static final String ACTION_NEXT = "Next";
private static final String ACTION_ADD_URI_TO_QUEUE = "AddURIToQueue";
private static final String ACTION_REMOVE_TRACK_RANGE_FROM_QUEUE = "RemoveTrackRangeFromQueue";
private static final String ACTION_REMOVE_ALL_TRACKS_FROM_QUEUE = "RemoveAllTracksFromQueue";
private static final String ACTION_SAVE_QUEUE = "SaveQueue";
private static final String ACTION_SET_PLAY_MODE = "SetPlayMode";
private static final String ACTION_BECOME_COORDINATOR_OF_STANDALONE_GROUP = "BecomeCoordinatorOfStandaloneGroup";
private static final String ACTION_GET_RUNNING_ALARM_PROPERTIES = "GetRunningAlarmProperties";
private static final String ACTION_SNOOZE_ALARM = "SnoozeAlarm";
private static final String ACTION_GET_REMAINING_SLEEP_TIMER_DURATION = "GetRemainingSleepTimerDuration";
private static final String ACTION_CONFIGURE_SLEEP_TIMER = "ConfigureSleepTimer";
private static final String ACTION_SET_VOLUME = "SetVolume";
private static final String ACTION_SET_MUTE = "SetMute";
private static final String ACTION_SET_BASS = "SetBass";
private static final String ACTION_SET_TREBLE = "SetTreble";
private static final String ACTION_SET_LOUDNESS = "SetLoudness";
private static final String ACTION_SET_EQ = "SetEQ";
private static final int SOCKET_TIMEOUT = 5000;
private static final int TUNEIN_DEFAULT_SERVICE_TYPE = 65031;
private static final int MIN_BASS = -10;
private static final int MAX_BASS = 10;
private static final int MIN_TREBLE = -10;
private static final int MAX_TREBLE = 10;
private static final int MIN_SUBWOOFER_GAIN = -15;
private static final int MAX_SUBWOOFER_GAIN = 15;
private static final int MIN_SURROUND_LEVEL = -15;
@ -264,6 +310,15 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
case VOLUME:
setVolumeForGroup(command);
break;
case BASS:
setBass(command);
break;
case TREBLE:
setTreble(command);
break;
case LOUDNESS:
setLoudness(command);
break;
case SUBWOOFER:
setSubwoofer(command);
break;
@ -427,33 +482,33 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
this.stateMap.put(variable, value);
// pre-process some variables, eg XML processing
if (service.equals("AVTransport") && variable.equals("LastChange")) {
if (service.equals(SERVICE_AV_TRANSPORT) && variable.equals("LastChange")) {
Map<String, String> parsedValues = SonosXMLParser.getAVTransportFromXML(value);
for (String parsedValue : parsedValues.keySet()) {
parsedValues.forEach((variable1, value1) -> {
// Update the transport state after the update of the media information
// to not break the notification mechanism
if (!parsedValue.equals("TransportState")) {
onValueReceived(parsedValue, parsedValues.get(parsedValue), "AVTransport");
if (!variable1.equals("TransportState")) {
onValueReceived(variable1, value1, service);
}
// Translate AVTransportURI/AVTransportURIMetaData to CurrentURI/CurrentURIMetaData
// for a compatibility with the result of the action GetMediaInfo
if (parsedValue.equals("AVTransportURI")) {
onValueReceived("CurrentURI", parsedValues.get(parsedValue), service);
} else if (parsedValue.equals("AVTransportURIMetaData")) {
onValueReceived("CurrentURIMetaData", parsedValues.get(parsedValue), service);
if (variable1.equals("AVTransportURI")) {
onValueReceived("CurrentURI", value1, service);
} else if (variable1.equals("AVTransportURIMetaData")) {
onValueReceived("CurrentURIMetaData", value1, service);
}
}
});
updateMediaInformation();
if (parsedValues.get("TransportState") != null) {
onValueReceived("TransportState", parsedValues.get("TransportState"), "AVTransport");
onValueReceived("TransportState", parsedValues.get("TransportState"), service);
}
}
if (service.equals("RenderingControl") && variable.equals("LastChange")) {
if (service.equals(SERVICE_RENDERING_CONTROL) && variable.equals("LastChange")) {
Map<String, String> parsedValues = SonosXMLParser.getRenderingControlFromXML(value);
for (String parsedValue : parsedValues.keySet()) {
onValueReceived(parsedValue, parsedValues.get(parsedValue), "RenderingControl");
}
parsedValues.forEach((variable1, value1) -> {
onValueReceived(variable1, value1, service);
});
}
List<StateOption> options = new ArrayList<>();
@ -488,12 +543,12 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
// Update state and control channels for the group members with the coordinator values
String transportState = getTransportState();
if (transportState != null) {
dispatchOnAllGroupMembers("TransportState", transportState, "AVTransport");
dispatchOnAllGroupMembers("TransportState", transportState, SERVICE_AV_TRANSPORT);
}
// Update shuffle and repeat channels for the group members with the coordinator values
String playMode = getPlayMode();
if (playMode != null) {
dispatchOnAllGroupMembers("CurrentPlayMode", playMode, "AVTransport");
dispatchOnAllGroupMembers("CurrentPlayMode", playMode, SERVICE_AV_TRANSPORT);
}
break;
case "LocalGroupUUID":
@ -508,6 +563,20 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
case "MuteMaster":
updateChannel(MUTE);
break;
case "Bass":
updateChannel(BASS);
break;
case "Treble":
updateChannel(TREBLE);
break;
case "LoudnessMaster":
updateChannel(LOUDNESS);
break;
case "OutputFixed":
updateChannel(BASS);
updateChannel(TREBLE);
updateChannel(LOUDNESS);
break;
case "SubEnabled":
updateChannel(SUBWOOFER);
break;
@ -691,12 +760,12 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
case STOP:
value = getTransportState();
if (value != null) {
newState = STATE_STOPPED.equals(value) ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(STATE_STOPPED.equals(value));
}
break;
case SHUFFLE:
if (getPlayMode() != null) {
newState = isShuffleActive() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isShuffleActive());
}
break;
case REPEAT:
@ -705,8 +774,9 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
break;
case LED:
if (getLed() != null) {
newState = isLedOn() ? OnOffType.ON : OnOffType.OFF;
value = getLed();
if (value != null) {
newState = OnOffType.from(value);
}
break;
case ZONENAME:
@ -726,7 +796,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
break;
case LOCALCOORDINATOR:
if (getGroupCoordinatorIsLocal() != null) {
newState = isGroupCoordinator() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isGroupCoordinator());
}
break;
case VOLUME:
@ -735,10 +805,28 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
newState = new PercentType(value);
}
break;
case BASS:
value = getBass();
if (value != null && !isOutputLevelFixed()) {
newState = new DecimalType(value);
}
break;
case TREBLE:
value = getTreble();
if (value != null && !isOutputLevelFixed()) {
newState = new DecimalType(value);
}
break;
case LOUDNESS:
value = getLoudness();
if (value != null && !isOutputLevelFixed()) {
newState = OnOffType.from(value);
}
break;
case MUTE:
value = getMute();
if (value != null) {
newState = isMuted() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(value);
}
break;
case SUBWOOFER:
@ -780,35 +868,35 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
case NIGHTMODE:
value = getNightMode();
if (value != null) {
newState = isNightModeOn() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(value);
}
break;
case SPEECHENHANCEMENT:
value = getDialogLevel();
if (value != null) {
newState = isSpeechEnhanced() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(value);
}
break;
case LINEIN:
if (getAnalogLineInConnected() != null) {
newState = isAnalogLineInConnected() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isAnalogLineInConnected());
} else if (getOpticalLineInConnected() != null) {
newState = isOpticalLineInConnected() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isOpticalLineInConnected());
}
break;
case ANALOGLINEIN:
if (getAnalogLineInConnected() != null) {
newState = isAnalogLineInConnected() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isAnalogLineInConnected());
}
break;
case DIGITALLINEIN:
if (getOpticalLineInConnected() != null) {
newState = isOpticalLineInConnected() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isOpticalLineInConnected());
}
break;
case ALARMRUNNING:
if (getAlarmRunning() != null) {
newState = isAlarmRunning() ? OnOffType.ON : OnOffType.OFF;
newState = OnOffType.from(isAlarmRunning());
}
break;
case ALARMPROPERTIES:
@ -985,6 +1073,14 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
}
private Map<String, String> executeAction(String serviceId, String actionId, @Nullable Map<String, String> inputs) {
Map<String, String> result = service.invokeAction(this, serviceId, actionId, inputs);
result.forEach((variable, value) -> {
this.onValueReceived(variable, value, serviceId);
});
return result;
}
private void updatePlayerState() {
if (!updateZoneInfo()) {
if (!ThingStatus.OFFLINE.equals(getThing().getStatus())) {
@ -1002,39 +1098,24 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
protected void updateCurrentZoneName() {
Map<String, String> result = service.invokeAction(this, "DeviceProperties", "GetZoneAttributes", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "DeviceProperties");
}
executeAction(SERVICE_DEVICE_PROPERTIES, ACTION_GET_ZONE_ATTRIBUTES, null);
}
protected void updateLed() {
Map<String, String> result = service.invokeAction(this, "DeviceProperties", "GetLEDState", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "DeviceProperties");
}
executeAction(SERVICE_DEVICE_PROPERTIES, ACTION_GET_LED_STATE, null);
}
protected void updateTime() {
Map<String, String> result = service.invokeAction(this, "AlarmClock", "GetTimeNow", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AlarmClock");
}
executeAction(SERVICE_ALARM_CLOCK, "GetTimeNow", null);
}
protected void updatePosition() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "GetPositionInfo", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_GET_POSITION_INFO, null);
}
protected void updateRunningAlarmProperties() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "GetRunningAlarmProperties", null);
Map<String, String> result = service.invokeAction(this, SERVICE_AV_TRANSPORT,
ACTION_GET_RUNNING_ALARM_PROPERTIES, null);
String alarmID = result.get("AlarmID");
String loggedStartTime = result.get("LoggedStartTime");
@ -1046,16 +1127,13 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
result.put("RunningAlarmProperties", newStringValue);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
result.forEach((variable, value) -> {
this.onValueReceived(variable, value, SERVICE_AV_TRANSPORT);
});
}
protected boolean updateZoneInfo() {
Map<String, String> result = service.invokeAction(this, "DeviceProperties", "GetZoneInfo", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "DeviceProperties");
}
Map<String, String> result = executeAction(SERVICE_DEVICE_PROPERTIES, ACTION_GET_ZONE_INFO, null);
Map<String, String> properties = editProperties();
String value = stateMap.get("HardwareVersion");
@ -1209,14 +1287,17 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
handlerForImageUpdate = memberHandler;
}
memberHandler.onValueReceived("CurrentTuneInStationId", (stationID != null) ? stationID : "",
"AVTransport");
SERVICE_AV_TRANSPORT);
if (needsUpdating) {
memberHandler.onValueReceived("CurrentArtist", (artist != null) ? artist : "", "AVTransport");
memberHandler.onValueReceived("CurrentAlbum", (album != null) ? album : "", "AVTransport");
memberHandler.onValueReceived("CurrentTitle", (title != null) ? title : "", "AVTransport");
memberHandler.onValueReceived("CurrentArtist", (artist != null) ? artist : "",
SERVICE_AV_TRANSPORT);
memberHandler.onValueReceived("CurrentAlbum", (album != null) ? album : "",
SERVICE_AV_TRANSPORT);
memberHandler.onValueReceived("CurrentTitle", (title != null) ? title : "",
SERVICE_AV_TRANSPORT);
memberHandler.onValueReceived("CurrentURIFormatted", (resultString != null) ? resultString : "",
"AVTransport");
memberHandler.onValueReceived("CurrentAlbumArtURI", albumArtURI, "AVTransport");
SERVICE_AV_TRANSPORT);
memberHandler.onValueReceived("CurrentAlbumArtURI", albumArtURI, SERVICE_AV_TRANSPORT);
}
}
} catch (IllegalStateException e) {
@ -1315,6 +1396,22 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
return stateMap.get("VolumeMaster");
}
public boolean isOutputLevelFixed() {
return "1".equals(stateMap.get("OutputFixed"));
}
public @Nullable String getBass() {
return stateMap.get("Bass");
}
public @Nullable String getTreble() {
return stateMap.get("Treble");
}
public @Nullable String getLoudness() {
return stateMap.get("LoudnessMaster");
}
public @Nullable String getSurroundEnabled() {
return stateMap.get("SurroundEnabled");
}
@ -1427,7 +1524,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
inputs.put("RequestedCount", Integer.toString(200));
inputs.put("SortCriteria", "");
Map<String, String> result = service.invokeAction(this, "ContentDirectory", "Browse", inputs);
Map<String, String> result = service.invokeAction(this, SERVICE_CONTENT_DIRECTORY, "Browse", inputs);
String initialResult = result.get("Result");
if (initialResult == null) {
@ -1442,7 +1539,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
while (startAt < totalMatches) {
inputs.put("StartingIndex", Long.toString(startAt));
result = service.invokeAction(this, "ContentDirectory", "Browse", inputs);
result = service.invokeAction(this, SERVICE_CONTENT_DIRECTORY, "Browse", inputs);
// Execute this action synchronously
String nextResult = result.get("Result");
@ -1469,7 +1566,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
inputs.put("RequestedCount", "1");
inputs.put("SortCriteria", "");
Map<String, String> result = service.invokeAction(this, "ContentDirectory", "Browse", inputs);
Map<String, String> result = service.invokeAction(this, SERVICE_CONTENT_DIRECTORY, "Browse", inputs);
return getResultEntry(result, "TotalMatches", type, "dc:title");
}
@ -1640,22 +1737,12 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
public void saveQueue(String name, String queueID) {
Map<String, String> inputs = new HashMap<>();
inputs.put("Title", name);
inputs.put("ObjectID", queueID);
Map<String, String> result = service.invokeAction(this, "AVTransport", "SaveQueue", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_SAVE_QUEUE, Map.of("Title", name, "ObjectID", queueID));
}
public void setVolume(Command command) {
if (command instanceof OnOffType || command instanceof IncreaseDecreaseType || command instanceof DecimalType
|| command instanceof PercentType) {
Map<String, String> inputs = new HashMap<>();
String newValue = null;
String currentVolume = getVolume();
if (command == IncreaseDecreaseType.INCREASE && currentVolume != null) {
@ -1673,14 +1760,8 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
} else {
return;
}
inputs.put("Channel", "Master");
inputs.put("DesiredVolume", newValue);
Map<String, String> result = service.invokeAction(this, "RenderingControl", "SetVolume", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "RenderingControl");
}
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_VOLUME,
Map.of("Channel", "Master", "DesiredVolume", newValue));
}
}
@ -1701,6 +1782,53 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
}
public void setBass(Command command) {
if (!isOutputLevelFixed()) {
String newValue = getNewNumericValue(command, getBass(), MIN_BASS, MAX_BASS);
if (newValue != null) {
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_BASS,
Map.of("InstanceID", "0", "DesiredBass", newValue));
}
}
}
public void setTreble(Command command) {
if (!isOutputLevelFixed()) {
String newValue = getNewNumericValue(command, getTreble(), MIN_TREBLE, MAX_TREBLE);
if (newValue != null) {
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_TREBLE,
Map.of("InstanceID", "0", "DesiredTreble", newValue));
}
}
}
private @Nullable String getNewNumericValue(Command command, @Nullable String currentValue, int minValue,
int maxValue) {
String newValue = null;
if (command instanceof IncreaseDecreaseType || command instanceof DecimalType) {
if (command == IncreaseDecreaseType.INCREASE && currentValue != null) {
int i = Integer.valueOf(currentValue);
newValue = String.valueOf(Math.min(maxValue, i + 1));
} else if (command == IncreaseDecreaseType.DECREASE && currentValue != null) {
int i = Integer.valueOf(currentValue);
newValue = String.valueOf(Math.max(minValue, i - 1));
} else if (command instanceof DecimalType) {
newValue = String.valueOf(((DecimalType) command).intValue());
}
}
return newValue;
}
public void setLoudness(Command command) {
if (!isOutputLevelFixed() && (command instanceof OnOffType || command instanceof OpenClosedType
|| command instanceof UpDownType)) {
String value = (command.equals(OnOffType.ON) || command.equals(UpDownType.UP)
|| command.equals(OpenClosedType.OPEN)) ? "True" : "False";
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_LOUDNESS,
Map.of("InstanceID", "0", "Channel", "Master", "DesiredLoudness", value));
}
}
/**
* Checks if the player receiving the command is part of a group that
* consists of randomly added players or contains bonded players
@ -1790,11 +1918,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
logger.debug("Action Invalid Value Format Exception {}", ex.getMessage());
}
Map<String, String> result = service.invokeAction(this, "AVTransport", "AddURIToQueue", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_ADD_URI_TO_QUEUE, inputs);
}
public void setCurrentURI(SonosEntry newEntry) {
@ -1804,21 +1928,8 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
public void setCurrentURI(@Nullable String URI, @Nullable String URIMetaData) {
if (URI != null && URIMetaData != null) {
logger.debug("setCurrentURI URI {} URIMetaData {}", URI, URIMetaData);
Map<String, String> inputs = new HashMap<>();
try {
inputs.put("InstanceID", "0");
inputs.put("CurrentURI", URI);
inputs.put("CurrentURIMetaData", URIMetaData);
} catch (NumberFormatException ex) {
logger.debug("Action Invalid Value Format Exception {}", ex.getMessage());
}
Map<String, String> result = service.invokeAction(this, "AVTransport", "SetAVTransportURI", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_SET_AV_TRANSPORT_URI,
Map.of("InstanceID", "0", "CurrentURI", URI, "CurrentURIMetaData", URIMetaData));
}
}
@ -1836,49 +1947,20 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
protected void seek(String unit, @Nullable String target) {
if (target != null) {
Map<String, String> inputs = new HashMap<>();
try {
inputs.put("InstanceID", "0");
inputs.put("Unit", unit);
inputs.put("Target", target);
} catch (NumberFormatException ex) {
logger.debug("Action Invalid Value Format Exception {}", ex.getMessage());
}
Map<String, String> result = service.invokeAction(this, "AVTransport", "Seek", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_SEEK, Map.of("InstanceID", "0", "Unit", unit, "Target", target));
}
}
public void play() {
Map<String, String> inputs = new HashMap<>();
inputs.put("Speed", "1");
Map<String, String> result = service.invokeAction(this, "AVTransport", "Play", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_PLAY, Map.of("Speed", "1"));
}
public void stop() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "Stop", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_STOP, null);
}
public void pause() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "Pause", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_PAUSE, null);
}
public void setShuffle(Command command) {
@ -1990,34 +2072,16 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
private void setEqualizerNumericSetting(Command command, String eqType, @Nullable String currentValue, int minValue,
int maxValue) {
if (command instanceof IncreaseDecreaseType || command instanceof DecimalType) {
String newValue = null;
if (command == IncreaseDecreaseType.INCREASE && currentValue != null) {
int i = Integer.valueOf(currentValue);
newValue = String.valueOf(Math.min(maxValue, i + 1));
} else if (command == IncreaseDecreaseType.DECREASE && currentValue != null) {
int i = Integer.valueOf(currentValue);
newValue = String.valueOf(Math.max(minValue, i - 1));
} else if (command instanceof DecimalType) {
newValue = String.valueOf(((DecimalType) command).intValue());
} else {
return;
}
String newValue = getNewNumericValue(command, currentValue, minValue, maxValue);
if (newValue != null) {
setEQ(eqType, newValue);
}
}
private void setEQ(String eqType, String value) {
try {
Map<String, String> inputs = new HashMap<>();
inputs.put("InstanceID", "0");
inputs.put("EQType", eqType);
inputs.put("DesiredValue", value);
Map<String, String> result = service.invokeAction(this, "RenderingControl", "SetEQ", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "RenderingControl");
}
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_EQ,
Map.of("InstanceID", "0", "EQType", eqType, "DesiredValue", value));
} catch (IllegalStateException e) {
logger.debug("Cannot handle {} command ({})", eqType, e.getMessage());
}
@ -2027,18 +2091,10 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
return stateMap.get("NightMode");
}
public boolean isNightModeOn() {
return "1".equals(getNightMode());
}
public @Nullable String getDialogLevel() {
return stateMap.get("DialogLevel");
}
public boolean isSpeechEnhanced() {
return "1".equals(getDialogLevel());
}
public @Nullable String getPlayMode() {
return stateMap.get("CurrentPlayMode");
}
@ -2072,15 +2128,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
protected void updatePlayMode(String playMode) {
Map<String, String> inputs = new HashMap<>();
inputs.put("InstanceID", "0");
inputs.put("NewPlayMode", playMode);
Map<String, String> result = service.invokeAction(this, "AVTransport", "SetPlayMode", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_SET_PLAY_MODE, Map.of("InstanceID", "0", "NewPlayMode", playMode));
}
/**
@ -2088,14 +2136,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
*
*/
public void removeAllTracksFromQueue() {
Map<String, String> inputs = new HashMap<>();
inputs.put("InstanceID", "0");
Map<String, String> result = service.invokeAction(this, "AVTransport", "RemoveAllTracksFromQueue", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_REMOVE_ALL_TRACKS_FROM_QUEUE, Map.of("InstanceID", "0"));
}
/**
@ -2219,31 +2260,15 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
public void setMute(Command command) {
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
Map<String, String> inputs = new HashMap<>();
inputs.put("Channel", "Master");
if (command.equals(OnOffType.ON) || command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)) {
inputs.put("DesiredMute", "True");
} else if (command.equals(OnOffType.OFF) || command.equals(UpDownType.DOWN)
|| command.equals(OpenClosedType.CLOSED)) {
inputs.put("DesiredMute", "False");
}
Map<String, String> result = service.invokeAction(this, "RenderingControl", "SetMute", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "RenderingControl");
}
String value = (command.equals(OnOffType.ON) || command.equals(UpDownType.UP)
|| command.equals(OpenClosedType.OPEN)) ? "True" : "False";
executeAction(SERVICE_RENDERING_CONTROL, ACTION_SET_MUTE,
Map.of("Channel", "Master", "DesiredMute", value));
}
}
public List<SonosAlarm> getCurrentAlarmList() {
Map<String, String> result = service.invokeAction(this, "AlarmClock", "ListAlarms", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AlarmClock");
}
Map<String, String> result = executeAction(SERVICE_ALARM_CLOCK, "ListAlarms", null);
String alarmList = result.get("CurrentAlarmList");
return alarmList == null ? Collections.emptyList() : SonosXMLParser.getAlarmsFromStringResult(alarmList);
}
@ -2276,11 +2301,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
logger.debug("Action Invalid Value Format Exception {}", ex.getMessage());
}
Map<String, String> result = service.invokeAction(this, "AlarmClock", "UpdateAlarm", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AlarmClock");
}
executeAction(SERVICE_ALARM_CLOCK, "UpdateAlarm", inputs);
}
public void setAlarm(Command command) {
@ -2383,11 +2404,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
logger.debug("Action Invalid Value Format Exception {}", ex.getMessage());
}
Map<String, String> result = service.invokeAction(this, "AVTransport", "SnoozeAlarm", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_SNOOZE_ALARM, inputs);
} else {
logger.debug("There is no alarm running on {}", getUDN());
}
@ -2410,12 +2427,7 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
public void becomeStandAlonePlayer() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "BecomeCoordinatorOfStandaloneGroup",
null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_BECOME_COORDINATOR_OF_STANDALONE_GROUP, null);
}
public void addMember(Command command) {
@ -2793,22 +2805,12 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
*/
public void removeRangeOfTracksFromQueue(Command command) {
if (command instanceof StringType) {
Map<String, String> inputs = new HashMap<>();
String[] rangeInputSplit = command.toString().split(",");
// If range input is incorrect, remove the first song by default
String startIndex = rangeInputSplit[0] != null ? rangeInputSplit[0] : "1";
String numberOfTracks = rangeInputSplit[1] != null ? rangeInputSplit[1] : "1";
inputs.put("InstanceID", "0");
inputs.put("StartingIndex", startIndex);
inputs.put("NumberOfTracks", numberOfTracks);
Map<String, String> result = service.invokeAction(this, "AVTransport", "RemoveTrackRangeFromQueue", inputs);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_REMOVE_TRACK_RANGE_FROM_QUEUE,
Map.of("InstanceID", "0", "StartingIndex", startIndex, "NumberOfTracks", numberOfTracks));
}
}
@ -2841,23 +2843,10 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
public void setLed(Command command) {
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
Map<String, String> inputs = new HashMap<>();
if (command.equals(OnOffType.ON) || command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)) {
inputs.put("DesiredLEDState", "On");
} else if (command.equals(OnOffType.OFF) || command.equals(UpDownType.DOWN)
|| command.equals(OpenClosedType.CLOSED)) {
inputs.put("DesiredLEDState", "Off");
}
Map<String, String> result = service.invokeAction(this, "DeviceProperties", "SetLEDState", inputs);
Map<String, String> result2 = service.invokeAction(this, "DeviceProperties", "GetLEDState", null);
result.putAll(result2);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "DeviceProperties");
}
String value = (command.equals(OnOffType.ON) || command.equals(UpDownType.UP)
|| command.equals(OpenClosedType.OPEN)) ? "On" : "Off";
executeAction(SERVICE_DEVICE_PROPERTIES, ACTION_SET_LED_STATE, Map.of("DesiredLEDState", value));
executeAction(SERVICE_DEVICE_PROPERTIES, ACTION_GET_LED_STATE, null);
}
}
@ -2877,19 +2866,11 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
}
public void previous() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "Previous", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_PREVIOUS, null);
}
public void next() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "Next", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_NEXT, null);
}
public void stopPlaying(Command command) {
@ -3143,18 +3124,10 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
return stateMap.get("MuteMaster");
}
public boolean isMuted() {
return "1".equals(getMute());
}
public @Nullable String getLed() {
return stateMap.get("CurrentLEDState");
}
public boolean isLedOn() {
return "On".equals(getLed());
}
public @Nullable String getCurrentZoneName() {
return stateMap.get("CurrentZoneName");
}
@ -3219,19 +3192,13 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici
*/
public void setSleepTimer(Command command) {
if (command instanceof DecimalType) {
Map<String, String> inputs = new HashMap<>();
inputs.put("InstanceID", "0");
inputs.put("NewSleepTimerDuration", sleepSecondsToTimeStr(((DecimalType) command).longValue()));
this.service.invokeAction(this, "AVTransport", "ConfigureSleepTimer", inputs);
this.service.invokeAction(this, SERVICE_AV_TRANSPORT, ACTION_CONFIGURE_SLEEP_TIMER, Map.of("InstanceID",
"0", "NewSleepTimerDuration", sleepSecondsToTimeStr(((DecimalType) command).longValue())));
}
}
protected void updateSleepTimerDuration() {
Map<String, String> result = service.invokeAction(this, "AVTransport", "GetRemainingSleepTimerDuration", null);
for (String variable : result.keySet()) {
this.onValueReceived(variable, result.get(variable), "AVTransport");
}
executeAction(SERVICE_AV_TRANSPORT, ACTION_GET_REMAINING_SLEEP_TIMER_DURATION, null);
}
private String sleepSecondsToTimeStr(long sleepSeconds) {

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -45,6 +47,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -14,6 +14,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -26,6 +27,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -44,6 +46,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -15,6 +15,7 @@
<channel id="alarm" typeId="alarm"/>
<channel id="alarmproperties" typeId="alarmproperties"/>
<channel id="alarmrunning" typeId="alarmrunning"/>
<channel id="bass" typeId="bass"/>
<channel id="control" typeId="system.media-control"/>
<channel id="currentalbum" typeId="currentalbum"/>
<channel id="currentalbumart" typeId="currentalbumart"/>
@ -27,6 +28,7 @@
<channel id="favorite" typeId="favorite"/>
<channel id="led" typeId="led"/>
<channel id="localcoordinator" typeId="localcoordinator"/>
<channel id="loudness" typeId="loudness"/>
<channel id="mute" typeId="system.mute"/>
<channel id="notificationsound" typeId="notificationsound"/>
<channel id="playlist" typeId="playlist"/>
@ -46,6 +48,7 @@
<channel id="standalone" typeId="standalone"/>
<channel id="state" typeId="state"/>
<channel id="stop" typeId="stop"/>
<channel id="treble" typeId="treble"/>
<channel id="tuneinstationid" typeId="tuneinstationid"/>
<channel id="volume" typeId="system.volume"/>
<channel id="zonegroupid" typeId="zonegroupid"/>

View File

@ -32,6 +32,13 @@
<state readOnly="true"/>
</channel-type>
<channel-type id="bass" advanced="true">
<item-type>Number</item-type>
<label>Bass</label>
<description>Set or get the bass level adjustment</description>
<state min="-10" max="10" step="1" readOnly="false" pattern="%d"/>
</channel-type>
<channel-type id="clearqueue" advanced="true">
<item-type>Switch</item-type>
<label>Clear Queue</label>
@ -106,6 +113,12 @@
<state readOnly="true"/>
</channel-type>
<channel-type id="loudness" advanced="true">
<item-type>Switch</item-type>
<label>Loudness</label>
<description>Enable or disable the loudness</description>
</channel-type>
<channel-type id="nightmode" advanced="true">
<item-type>Switch</item-type>
<label>Night Mode</label>
@ -251,6 +264,13 @@
<description>Stop the Zone Player. ON if the player is stopped.</description>
</channel-type>
<channel-type id="treble" advanced="true">
<item-type>Number</item-type>
<label>Treble</label>
<description>Set or get the treble level adjustment</description>
<state min="-10" max="10" step="1" readOnly="false" pattern="%d"/>
</channel-type>
<channel-type id="subwoofer" advanced="true">
<item-type>Switch</item-type>
<label>Subwoofer</label>