Volume
When providing volume controls to users, you should consider the full Sonos system. Users can change volume using multiple apps and controls, so your integration should be responsive to volume changes and reflect the changes to the user. When your app changes volume, you should consider how your changes impact the system and throttle changes if necessary. We'll describe how you can handle this later.
Your integration can provide volume controls in a number of ways. For example, a user could interact with a slider to continuously set the volume and choose the best level as they hear the changes live or use hardware buttons on a phone to increase or decrease the volume incrementally relative to the current volume. To mute players, users could press a button to mute all players, or selectively mute one player at a time. Apps can set or get the following objects:
- Group volume. Apps can set a volume level for the entire group by sending a command that proportionally adjusts the volume of each player so that the average corresponds to the desired group volume level.
- Player volume. Set a volume level for an individual player.
- Group mute. Mute the group. This does not affect the group volume level.
- Player mute. Mute an individual player.
Players batch volume events and send them to apps subscribed to a volume namespace (such as groupVolume or playerVolume) asynchronously. Apps can subscribe to volume namespaces to receive volume change events, for example, to display the group volume on the user interface. See below for some guidelines on how to handle continuous volume changes.
Group volume example
The following example demonstrates how group volume is adjusted when users adjust the volume for individual players and and how to mute individual players.
Volume starts at 4 | Office volume to 22 | Group volume to 27 |
---|---|---|
Volume starts at 4 for all players. | The user moves the Office volume to 22. Sonos proportionally adjusts the group volume to 13. | The user moves group volume to 27. Sonos proportionally adjusts the Office and TV room volumes. |
When the user adjusts the group volume slider, the user interface for the players in the group should update in real-time based on volume events sent from each individual player, but the group volume slider should not update based on events. For example, for a mobile app with a slider that users can move with their finger, the group volume slider shouldn't respond to incoming events as that would cause it to move under the user's finger. When the user stops adjusting the volume for the group, by lifting their finger off the control on the app, the group volume slider should respond to volume events again.
When the user adjusts the volume for an individual player, the group volume slider should adjust to volume events. The individual player volume would not respond to events. Once the user has relinquished control, it can also respond to volume events.
Commands
You can target a group or a player with volume commands. You should always use the group volume and mute commands to set volume levels or mute states for groups rather than send a set of volume commands to individual players. When you send a group volume command, Sonos preserves the relative volume of each player by proportionally adjusting the volume for each player in the group. Sonos does this by taking a snapshot of the current volume before making changes. See the commands below for details.
Send group volume commands to the group coordinator. Send individual volume commands to any player.
setVolume
You can set the volume for a player or group to a non-negative integer from 0 to 100, which represents a percentage of maximum volume. When setting group volume, Sonos sets the individual player volume levels to maintain the proportional volume difference among them such that the average volume is the desired level.
setRelativeVolume
You can adjust the current volume of a player or group by a specified amount, a signed integer from -100 to 100. For group volume, the group coordinator calculates appropriate adjustments to individual player volume levels based on the latest snapshot, such that the overall volume level is adjusted by the specified amount, with a floor of 0 and a ceiling of 100.
setMute
You can mute a player or a group with this command.
Group mute is a binary state, a group is muted if all players in the group are muted, and is otherwise not muted. The set group volume call should not be used as a substitute for muting, because the actual mute state leaves volume levels intact. Setting the group volume to 0 effectively discards any information about different volume levels between players, and on the next snapshot and group volume transaction, all players will have the same volume level. Therefore, to preserve volume levels, use the set group mute call for muting and unmuting.
Group mute does not preserve previous mute states of individual players. That is, while group volume uses snapshots to ensure individual player volumes are kept in the right proportion to each other, setting the group mute state to true or false simply sets the mute state for all players, regardless of their previous values. If some players in a group are muted and some are not, the group mute state is false. If you set the group mute state to true, Sonos mutes all players. If you subsequently set the group mute state to false, Sonos unmutes all players.
Office player muted | Group volume muted |
---|---|
The user mutes the Office. Sonos preserves the volume level. | The user presses the speaker icon to mute group volume. All rooms are muted. Sonos preserves the Office mute state. |
Once the user presses the speaker icon again to unmute the GROUP VOLUME, all rooms will be unmuted.
Set volume or relative volume
Whether it's more appropriate to use the set group volume call or the set relative group volume depends on how the user interface of the app presents the volume control. For example, with a slider, the set group volume call is usually the right choice, as the slider has a known starting point, a set of values through which it is dragged, and a known ending point. It would be more appropriate to set the relative group volume for a volume up button, as a volume up button has no state information about the current volume level, it only represents incrementing the volume regardless of the actual numeric value.
Whether you set the group volume or the relative group volume, the volume change transaction may consist of a single action or a sequence of multiple actions. For example, a user can set the volume in a single action by clicking a volume up button once or by clicking a specific spot on a volume slider. Alternatively, a user can perform a sequence of actions, such as holding the volume up button or dragging the volume slider for a continuous volume change until their desired volume level is reached. See the section below for tips on how to handle continuous volume changes.
Group volume for headphones and audio out
Group volume commands don't always affect players with devices plugged into their line-out connections. This is to insure that someone with a headphone plugged into a player will not experience volume changes without explicitly making changes to the headphone volume. The Sonos devices with line-out connections are the Play:5 (gen 1), which has a 3.5mm headphone jack and the Connect, which has RCA analog audio out. When these players have a device plugged into their line-out connections, group-volume commands will only affect them if they are the only player in the group. If there are other players in the group, group volume commands will affect the other players, but not them. Group mute works in the same way for players with and without line-out connections.
One player group, with headphones | Two player group, one with headphones |
---|---|
Group volume commands will change volume for headphones plugged into the Office player. | Group volume commands will not change volume for headphones plugged into the Office player, but will change volume for the TV Room. |
Subscribe to the groupVolume
namespace
groupVolume
namespaceTo synchronize the volume displayed on all apps connected to the group, all apps must subscribe to the groupVolume
namespace. When you change volume or mute a player in the system, Sonos notifies all apps that are subscribed.
Handling continuous volume changes
The Sonos system is a network of apps and players. Even a simple volume slider can flood the system with commands and events. Consider the following best practices when creating a continuous volume control:
- Throttle volume commands. Limit the number of volume control commands sent to the player group. For example, set a timer to collect volume commands and send a command when the timer expires.
- Store events before processing. If a user is quickly moving a volume slider up to increase the volume, the player may not be able to send events fast enough for your app to show the current volume on the user interface. Instead of processing events as they arrive from the player, store events and process the most recent one to display the most recent volume after the user has finished changing the volume.
Suggested implementation
- Draw a group volume slider and tie it to the
groupVolume
commands and events. - Draw volume sliders for each player in the group and tie them to the playerVolume commands and events for each player.
- If there's only one player in the group, there's no need to show both group and player volume sliders. In this case, just show the group volume slider.
- Subscribe to the
groups
namespace to receive events when users add or remove players from the group. Use these events to update your user interface to correctly reflect the players in the group. - Do not send a volume change command in response to a volume event. To handle this, we recommend that:
- While the user is engaged in actively moving the slider around, ignore incoming volume events that correspond to that slider, but remember the last event.
- When the user releases the slider, set a timer for 2 seconds. When the timer expires, if the user is still not manipulating the slider, update it to the last evented value. Then stop ignoring incoming volume events for that slider.
- If the user releases a slider, then grabs it again before the 2 second timer expires, cancel the timer. In many programming languages, you can just unconditionally cancel the timer on the "start dragging" event and unconditionally start the time on the "end dragging" event.
- Since Sonos offers separate APIs for group volume and player volume, your app should not determine how group volume and player volume interact.
- Your app may receive a groups event that says the group no longer exists. This can happen if another user changes the grouping. Your user interface should not to crash in this case.
Pseudocode
The pseudocode below shows a simplified algorithm using the concepts above:
on group.coordinator.GroupVolumeEvent: // handles events from the Sonos player group
last_evented_value = evented_value
if (ignore_volume_events == false): // ignore events while dragging and for a while after
slider.value = evented_value
on slider.StartDragging:
eventsTimer.cancel() // if we start dragging again before the timer expires, cancel it
group.coordinator.SnapshotGroupVolume()
ignore_volume_events = true
on slider.ValueChange:
if commandTimer.stopped():
if (int)slider.value != last_sent_value: // fractional changes are too small to bother with
group.coordinator.SetGroupVolume((int)slider.value)
last_sent_value = (int)slider.value
actionTimer.start(100) // send at most one action every 100 milliseconds
on slider.EndDragging:
group.coordinator.SetGroupVolume((int)slider.value)
eventsTimer.start(2000) // group volume changes can be slow, keep ignoring events for two more seconds
on eventsTimer.Fire:
if last_evented_value != (int)slider.value: // once this timeout ends, update from the last evented value
slider.value = last_evented_value
ignore_volume_events = false
Updated 8 months ago