Skip to content

Commit 5fb88e8

Browse files
Add additional endpoints and fields for Audio Clips
1 parent 1df6b9d commit 5fb88e8

4 files changed

Lines changed: 176 additions & 10 deletions

File tree

src/main/java/engineer/nightowl/sonos/api/domain/SonosAudioClip.java

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package engineer.nightowl.sonos.api.domain;
22

3+
import engineer.nightowl.sonos.api.enums.SonosAudioClipErrorCode;
4+
import engineer.nightowl.sonos.api.enums.SonosClipState;
35
import engineer.nightowl.sonos.api.enums.SonosClipType;
46
import engineer.nightowl.sonos.api.enums.SonosPriority;
7+
import org.apache.commons.lang3.builder.EqualsBuilder;
8+
import org.apache.commons.lang3.builder.HashCodeBuilder;
59

610
import java.net.URI;
711

@@ -16,7 +20,11 @@ public class SonosAudioClip {
1620
private String appId;
1721
private SonosPriority priority;
1822
private SonosClipType clipType;
23+
private SonosClipState status;
24+
private SonosAudioClipErrorCode errorCode;
25+
private String httpAuthorization;
1926
private URI streamUrl;
27+
private Integer volume;
2028

2129
/**
2230
* Default constructor
@@ -26,22 +34,31 @@ public SonosAudioClip() {
2634

2735
/**
2836
* Full args constructor
29-
*
30-
* @param id Sonos generates this unique identifier and assigned to the audio clip.
31-
* @param name User identifiable string.
32-
* @param appId This string identifies the app that created the audioClip. Companies should use their reversed Internet domain name as the identifier, similar to com.acme.app.
33-
* @param priority (Optional) Clip priority. Clips are low priority by default (not yet implemented).
34-
* @param clipType (Optional) Sonos plays a built-in sound when this option is provided. The default value is CHIME.
35-
* @param streamUrl (Optional) Sonos will play this URL when you provide one. The caller does not need to specify a CUSTOM clipType in addition to providing the streamUrl. Sonos supports only MP3 or WAV files as audio clips.
37+
* @param id Sonos generates this unique identifier and assigned to the audio clip.
38+
* @param name User identifiable string.
39+
* @param appId This string identifies the app that created the audioClip. Companies should use their reversed Internet domain name as the identifier, similar to com.acme.app.
40+
* @param priority (Optional) Clip priority. Clips are low priority by default (not yet implemented).
41+
* @param clipType (Optional) Sonos plays a built-in sound when this option is provided. The default value is CHIME.
42+
* @param status This field indicates the state of the audio clip, for example, if it’s active, it’s currently playing. Audio clips transition from pending (on load) to active to done. Sonos returns the state only in events.
43+
* @param errorCode (Optional) Custom error code for audio clips.
44+
* @param streamUrl (Optional) Sonos will play this URL when you provide one. The caller does not need to specify a CUSTOM clipType in addition to providing the streamUrl. Sonos supports only MP3 or WAV files as audio clips.
45+
* @param httpAuthorization (Optional) Set a string to pass in the Authorization header when fetching the streamUrl. Omit this parameter to omit the Authorization header. Sonos includes the Authorization header when the streamUrl is secure (HTTPS). Sonos supports an httpAuthorization value up to 512 bytes.
46+
* @param volume (Optional) Audio Clip playback volume, between 0 and 100. There are internal upper and lower limits for the audio clip volume level in order to prevent the audio clip from being too loud or inaudible.
47+
* If the parameter is beyond those limits, Sonos automatically adjusts the audio clip volume to the lower or upper limit. The default behavior is to playback at the current player volume.
3648
*/
3749
public SonosAudioClip(final String id, final String name, final String appId, final SonosPriority priority,
38-
final SonosClipType clipType, final URI streamUrl) {
50+
final SonosClipType clipType, final SonosClipState status, final SonosAudioClipErrorCode errorCode,
51+
final URI streamUrl, final String httpAuthorization, final Integer volume) {
3952
this.id = id;
4053
this.name = name;
4154
this.appId = appId;
4255
this.priority = priority;
4356
this.clipType = clipType;
57+
this.status = status;
58+
this.errorCode = errorCode;
4459
this.streamUrl = streamUrl;
60+
this.httpAuthorization = httpAuthorization;
61+
this.volume = volume;
4562
}
4663

4764
public String getId() {
@@ -76,6 +93,16 @@ public void setPriority(final SonosPriority priority) {
7693
this.priority = priority;
7794
}
7895

96+
public SonosAudioClipErrorCode getErrorCode()
97+
{
98+
return errorCode;
99+
}
100+
101+
public void setErrorCode(SonosAudioClipErrorCode errorCode)
102+
{
103+
this.errorCode = errorCode;
104+
}
105+
79106
public SonosClipType getClipType() {
80107
return clipType;
81108
}
@@ -92,15 +119,90 @@ public void setStreamUrl(final URI streamUrl) {
92119
this.streamUrl = streamUrl;
93120
}
94121

122+
public SonosClipState getStatus()
123+
{
124+
return status;
125+
}
126+
127+
public void setStatus(SonosClipState status)
128+
{
129+
this.status = status;
130+
}
131+
132+
public String getHttpAuthorization()
133+
{
134+
return httpAuthorization;
135+
}
136+
137+
public void setHttpAuthorization(String httpAuthorization)
138+
{
139+
this.httpAuthorization = httpAuthorization;
140+
}
141+
142+
public Integer getVolume()
143+
{
144+
return volume;
145+
}
146+
147+
public void setVolume(Integer volume)
148+
{
149+
this.volume = volume;
150+
}
151+
95152
@Override
96-
public String toString() {
153+
public String toString()
154+
{
97155
return "SonosAudioClip{" +
98156
"id='" + id + '\'' +
99157
", name='" + name + '\'' +
100158
", appId='" + appId + '\'' +
101159
", priority=" + priority +
102160
", clipType=" + clipType +
161+
", status=" + status +
162+
", errorCode=" + errorCode +
163+
", httpAuthorization='" + httpAuthorization + '\'' +
103164
", streamUrl=" + streamUrl +
165+
", volume=" + volume +
104166
'}';
105167
}
168+
169+
@Override
170+
public boolean equals(Object o)
171+
{
172+
if (this == o) return true;
173+
174+
if (o == null || getClass() != o.getClass()) return false;
175+
176+
SonosAudioClip that = (SonosAudioClip) o;
177+
178+
return new EqualsBuilder()
179+
.append(id, that.id)
180+
.append(name, that.name)
181+
.append(appId, that.appId)
182+
.append(priority, that.priority)
183+
.append(clipType, that.clipType)
184+
.append(status, that.status)
185+
.append(errorCode, that.errorCode)
186+
.append(httpAuthorization, that.httpAuthorization)
187+
.append(streamUrl, that.streamUrl)
188+
.append(volume, that.volume)
189+
.isEquals();
190+
}
191+
192+
@Override
193+
public int hashCode()
194+
{
195+
return new HashCodeBuilder(17, 37)
196+
.append(id)
197+
.append(name)
198+
.append(appId)
199+
.append(priority)
200+
.append(clipType)
201+
.append(status)
202+
.append(errorCode)
203+
.append(httpAuthorization)
204+
.append(streamUrl)
205+
.append(volume)
206+
.toHashCode();
207+
}
106208
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package engineer.nightowl.sonos.api.enums;
2+
3+
/**
4+
* <p>SonosSessionErrorCode class.</p>
5+
*/
6+
public enum SonosAudioClipErrorCode implements SonosErrorBase
7+
{
8+
ERROR_AUDIO_CLIP_DO_NOT_DISTURB("The user has enabled “do not disturb” mode, which temporarily disables audio clips (not yet implemented)."),
9+
ERROR_AUDIO_CLIP_ID_NOT_FOUND("The specified audio clip id was not recognized by the player. This may be because the player purged it from memory. Players purge audio clips from memory after playing them."),
10+
ERROR_AUDIO_CLIP_MEDIA_ERROR("The media type is not supported by Sonos."),
11+
ERROR_AUDIO_CLIP_CANCEL("The clip was canceled before activation. When canceled, the status of the clip moves from pending to dismissed."),
12+
ERROR_AUDIO_CLIP_EXPIRE("The clip expired prior to activation.");
13+
14+
private String errorMessage;
15+
16+
SonosAudioClipErrorCode(final String errorMessage)
17+
{
18+
this.errorMessage = errorMessage;
19+
}
20+
21+
public String getErrorMessage()
22+
{
23+
return errorMessage;
24+
}
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package engineer.nightowl.sonos.api.enums;
2+
3+
public enum SonosClipState
4+
{
5+
ACTIVE("Currently playing"),
6+
DISMISSED("Dismissed"),
7+
DONE("Playback complete"),
8+
INTERRUPTED("Playback interrupted, for example, by a high priority audio clip"),
9+
PENDING("Scheduled for playback, but not active");
10+
11+
private String extraInfo;
12+
13+
SonosClipState(final String extraInfo)
14+
{
15+
this.extraInfo = extraInfo;
16+
}
17+
18+
public String getExtraInfo()
19+
{
20+
return extraInfo;
21+
}
22+
}

src/main/java/engineer/nightowl/sonos/api/resource/AudioClipResource.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import engineer.nightowl.sonos.api.SonosApiClient;
44
import engineer.nightowl.sonos.api.domain.SonosAudioClip;
5+
import engineer.nightowl.sonos.api.domain.SonosSuccess;
56
import engineer.nightowl.sonos.api.exception.SonosApiClientException;
67
import engineer.nightowl.sonos.api.exception.SonosApiError;
78

@@ -21,7 +22,7 @@ public AudioClipResource(final SonosApiClient apiClient) {
2122
}
2223

2324
/**
24-
* Schedule a provided audioClip for playback. Only supported by Sonos One and Beam
25+
* Schedule a provided audioClip for playback
2526
*
2627
* @param clientToken for the user
2728
* @param playerId to play the audioClip on
@@ -36,4 +37,20 @@ public SonosAudioClip loadAudioClip(final String clientToken, final String playe
3637
return postToApi(SonosAudioClip.class, clientToken, String.format("/v1/players/%s/audioClip", playerId), audioClip);
3738
}
3839

40+
/**
41+
* Cancel a specified audioClip via its ID.
42+
*
43+
* @param clientToken for the user
44+
* @param playerId the audioClip is scheduled to play on
45+
* @param clipId of the audioClip
46+
* @return whether the clip was cancelled
47+
* @throws engineer.nightowl.sonos.api.exception.SonosApiClientException if an error occurs during the call
48+
* @throws engineer.nightowl.sonos.api.exception.SonosApiError if there is an error from the API
49+
* @see <a href="https://developer.sonos.com/reference/control-api/audioclip/loadaudioclip/">Sonos docs</a>
50+
*/
51+
public SonosSuccess cancelAudioClip(final String clientToken, final String playerId, final String clipId)
52+
throws SonosApiClientException, SonosApiError {
53+
return deleteFromApi(SonosSuccess.class, clientToken, String.format("/v1/players/%s/audioClip/%s", playerId, clipId));
54+
}
55+
3956
}

0 commit comments

Comments
 (0)