]> git.basschouten.com Git - openhab-addons.git/commitdiff
[sonos] Add bass/treble/loudness controls (#9918)
authorlolodomo <lg.hc@free.fr>
Mon, 25 Jan 2021 16:50:45 +0000 (17:50 +0100)
committerGitHub <noreply@github.com>
Mon, 25 Jan 2021 16:50:45 +0000 (08:50 -0800)
* [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>
20 files changed:
bundles/org.openhab.binding.sonos/README.md
bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosBindingConstants.java
bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/handler/ZonePlayerHandler.java
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/Amp.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/Arc.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/ArcSL.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/Beam.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/CONNECT.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/CONNECTAMP.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/One.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/OneSL.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/PLAY1.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/PLAY3.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/PLAY5.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/PLAYBAR.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/PLAYBASE.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/Port.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/SYMFONISK.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/ZonePlayer.xml
bundles/org.openhab.binding.sonos/src/main/resources/OH-INF/thing/channels.xml

index c3be76fa85cf029d92460596bd9040573d6adf31..91d83fdbd73c2b6237432743839a71c9a83600d4 100644 (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                          |
index 4cf9485743174f5c8a194b28ef10c26020451216..08b0b7cf06e0d0c7c6f75c3a0da92c3621aedf26 100644 (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";
index bf1b9ad5cfe37f9740fd3c4be8ced9877acf931f..fdb86ce81e410a115a52771b43cbe31cb9186991 100644 (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) {
index b5c4e5876dc761aaecb81a1b416f84996702ef70..7709e906e74f0653ecf0d1392ae3c2611f8aa37a 100644 (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"/>
index fa4cd8b9031f6644c06a6bc3fb39fa957cf183f6..a825d35c0c0d2dc1e34e5a3bdac383f674cc93a8 100644 (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"/>
index ea77c44eb4d98d5ef6ef16a51a564404f763ebf8..38103bf8ae4e6b741f195edba8a5f9c042fc9624 100644 (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"/>
index 2fe0effc8c769c758acfdc615b882a336f00e9a7..2f5e7b24dc6a9575d9528404a81adc02a9bbcd7a 100644 (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"/>
index 001dab440387811b42f1b3d62b2039935627032e..b7873d1f69e75529002e09ccb316663c4d8b2b81 100644 (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"/>
index 6222b953555ed3a4d992f10987569e932e8e32a4..af08bd617c3bf3bf26f1e6c3902dd361812b96a1 100644 (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"/>
index 55886066be2f6bc3d28175305a205e6a5f969e56..ccaa8a877a353f55a2751e31ca75ea0f56073ae4 100644 (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"/>
index 9b117d88328ed866ea6fd608e2fe934428ed4cff..ee1732ddf5e8f542334a61d4bdc90e014494eb3f 100644 (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"/>
index 5afa47695f6cfaa1432c4aeba9b7a70d49e6c9b1..7f670cc6ce865ec38bd78c185665a5f462a965ac 100644 (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"/>
index 90f9d24cb4b3f5fbf1151744acc3feb624cec97a..028a2f3306f16e5f6fe6c373a7e6f507ee6ce5bb 100644 (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"/>
index 4f1e14ac45d085a667cceba281c28f7c216b1148..a7b59a227b6512b67ebac6122b82801dc979ebb6 100644 (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"/>
index d1bd3c3e1d1275aa55b5abb8c9d25ea02f2b73c4..29deb414b92edd5cc206b3b8e9ea40f2c4d16ebb 100644 (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"/>
index 044bd51cc62037f882618d5f88a225067b06578a..ccef2b90f9668aa0dcbc2575df7f2252aa728d62 100644 (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"/>
index aec986d4975fd748ba84aa5ceb494d5f9e3c0178..551e13aaa9d0f2e3d322e87a4e86c01b1c5b2e16 100644 (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"/>
index 03122f46033aba7ed220f9c26b68e6e0de656ee4..b48af646d3333a1db8a9b6456d9a9a471c784822 100644 (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"/>
index 1368dbd73e1eeaa62b9626554711d4623e0e9cdb..443a7743196a47f54512ab389635733970c79e09 100644 (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"/>
index f826a671d85449daff3ae32f5d97920b00c64436..eaaeaa44d88ce6e543a4db7af718aabdbb8ef0b3 100644 (file)
                <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>
                <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>
                <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>