-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathAVTransport.js
More file actions
214 lines (168 loc) Β· 9.26 KB
/
AVTransport.js
File metadata and controls
214 lines (168 loc) Β· 9.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**
* Sonos library to control (almost) everything from your sonos devices
* @module sonos
* @requires './Service'
*/
const Service = require('./Service')
const Helpers = require('../helpers')
/**
* Create a new instance of AVTransport
* @class AVTransport
* @param {String} host The host param of one of your sonos speakers
* @param {Number} port The port of your sonos speaker, defaults to 1400
*/
class AVTransport extends Service {
constructor (host, port) {
super()
this.name = 'AVTransport'
this.host = host
this.port = port || 1400
this.controlURL = '/MediaRenderer/AVTransport/Control'
this.eventSubURL = '/MediaRenderer/AVTransport/Event'
this.SCPDURL = '/xml/AVTransport1.xml'
}
/**
* Set the Transport URI
* @param {object} options Object with required options
* @param {number} options.InstanceID The instance you want to control is always `0`
* @param {string} options.CurrentURI The new URI you wish to set.
* @param {string} options.CurrentURIMetaData The metadata of the uri you wish to set.
* @returns {Object} Parsed response data.
*/
async SetAVTransportURI (options) { return this._request('SetAVTransportURI', options) }
/**
* Add an URI to the queue
* @param {object} options The the required properties
* @param {number} options.InstanceID The instance you want to control is always `0`
* @param {number} options.EnqueuedURI The URI of the track you want to add
* @param {number} options.EnqueuedURIMetaData The Metadata of the track you wish to add, see `Helpers.GenerateMetadata`
* @param {number} options.DesiredFirstTrackNumberEnqueued The position in the queue
* @param {number} options.EnqueueAsNext To Queue this item as the next item set to `1`
* @returns {Object} Parsed response data.
*/
async AddURIToQueue (options) { return this._request('AddURIToQueue', options) }
async AddURIToSavedQueue (options) { return this._request('AddURIToSavedQueue', options) }
async AddMultipleURIsToQueue (options) { return this._request('AddMultipleURIsToQueue', options) }
/**
* Reorder tracks in queue
* @param {object} options All the required options
* @param {number} options.InstanceID The instance you want to edit is always `0`
* @param {number} options.UpdateID The update id, not a clue what this means. Just specify `0`
* @param {number} options.StartingIndex The index of the first song you want to move.
* @param {number} options.NumberOfTracks How many tracks do you want to move?
* @param {number} options.InsertBefore Where should these tracks be inserted?
* @returns {Object} Parsed response data.
*/
async ReorderTracksInQueue (options) { return this._request('ReorderTracksInQueue', options) }
async ReorderTracksInSavedQueue (options) { return this._request('ReorderTracksInSavedQueue', options) }
/**
* Remove a single track from the queue
* @param {object} options Object with required options
* @param {number} options.InstanceID The instance you want to control is always `0`
* @param {string} options.ObjectID The object to remove
* @param {string} options.UpdateID The update id, not a clue what this means. Just specify `0`
* @returns {Object} Parsed response data.
*/
async RemoveTrackFromQueue (options) { return this._request('RemoveTrackFromQueue', options) }
/**
* Remove a range of tracks from the queue
* @param {object} options Object with required options
* @param {number} options.InstanceID The instance you want to control is always `0`
* @param {number} options.UpdateID The update id, not a clue what this means. Just specify `0`
* @param {number} options.StartingIndex Index of the first song to remove
* @param {number} options.NumberOfTracks How many tracks to remove
* @returns {Object} Parsed response data.
*/
async RemoveTrackRangeFromQueue (options) { return this._request('RemoveTrackRangeFromQueue', options) }
async RemoveAllTracksFromQueue () { return this._request('RemoveAllTracksFromQueue', { InstanceID: 0 }) }
async SaveQueue (options) { return this._request('SaveQueue', options) }
async CreateSavedQueue (title) { return this._request('CreateSavedQueue', { InstanceID: 0, Title: title, EnqueuedURI: '', EnqueuedURIMetaData: '' }) }
async BackupQueue (options) { return this._request('BackupQueue', options) }
async GetMediaInfo () { return this._request('GetMediaInfo', { InstanceID: 0 }) }
async GetTransportInfo () { return this._request('GetTransportInfo', { InstanceID: 0 }) }
async GetPositionInfo () {
return this._request('GetPositionInfo', { InstanceID: 0 })
.then(result => {
result.Track = parseInt(result.Track)
return result
})
}
async GetDeviceCapabilities () { return this._request('GetDeviceCapabilities', { InstanceID: 0 }) }
async GetTransportSettings () { return this._request('GetTransportSettings', { InstanceID: 0 }) }
async GetCrossfadeMode () { return this._request('GetCrossfadeMode', { InstanceID: 0 }) }
async Stop () { return this._request('Stop', { InstanceID: 0 }) }
async Play () { return this._request('Play', { InstanceID: 0, Speed: 1 }) }
async Pause () { return this._request('Pause', { InstanceID: 0 }) }
/**
* Skip to other track or time
* @param {object} options Object with required options
* @param {number} options.InstanceID The instance you want to control is always `0`
* @param {number} options.Unit One of these `TRACK_NR`, `REL_TIME`, `TIME_DELTA`
* @param {number} options.Target Skip to what track number, relative time as hh:mm:ss, or ?
*/
async Seek (options) { return this._request('Seek', options) }
async Next () { return this._request('Next', { InstanceID: 0 }) }
async NextProgrammedRadioTracks () { return this._request('NextProgrammedRadioTracks') }
async Previous () { return this._request('Previous', { InstanceID: 0 }) }
async NextSection (options) { return this._request('NextSection', options) }
async PreviousSection (options) { return this._request('PreviousSection', options) }
/**
* Set the new playmode
* @param {string} playmode One of the following `NORMAL` `REPEAT_ALL` `SHUFFLE` `SHUFFLE_NOREPEAT`
* @returns {Object} Parsed response data.
*/
async SetPlayMode (playmode) { return this._request('SetPlayMode', { InstanceID: 0, NewPlayMode: playmode }) }
async SetCrossfadeMode (options) { return this._request('SetCrossfadeMode', options) }
async NotifyDeletedURI (options) { return this._request('NotifyDeletedURI', options) }
async GetCurrentTransportActions () { return this._request('GetCurrentTransportActions', { InstanceID: 0 }) }
async BecomeCoordinatorOfStandaloneGroup () { return this._request('BecomeCoordinatorOfStandaloneGroup', { InstanceID: 0 }) }
async DelegateGroupCoordinationTo (options) { return this._request('DelegateGroupCoordinationTo', options) }
async BecomeGroupCoordinator (options) { return this._request('BecomeGroupCoordinator', options) }
async BecomeGroupCoordinatorAndSource (options) { return this._request('BecomeGroupCoordinatorAndSource', options) }
/**
* Configure a sleeptimer.
* @param {string} duration the duration as 'ISO8601Time', needs sample!
* @returns {Object} Parsed response data.
*/
async ConfigureSleepTimer (duration) { return this._request('ConfigureSleepTimer', { InstanceID: 0, NewSleepTimerDuration: duration }) }
async GetRemainingSleepTimerDuration () { return this._request('GetRemainingSleepTimerDuration', { InstanceID: 0 }) }
async RunAlarm (options) { return this._request('RunAlarm', options) }
async StartAutoplay (options) { return this._request('StartAutoplay', options) }
async GetRunningAlarmProperties (options) { return this._request('GetRunningAlarmProperties', { InstanceID: 0 }) }
/**
* Snooze the current running alarm for a number of minutes.
* @param {string} duration The duration, as 'ISO8601Time', needs sample!
* @returns {Object} Parsed response data.
*/
async SnoozeAlarm (duration) { return this._request('SnoozeAlarm', { InstanceID: 0, Duration: duration }) }
/**
* Get information about the current track, parsed version of `GetPositionInfo()`
* @returns {Object} The current playing track
*/
async CurrentTrack () {
return this.GetPositionInfo()
.then(async result => {
const position = Helpers.TimeToSeconds(result.RelTime)
const duration = Helpers.TimeToSeconds(result.TrackDuration)
const trackUri = result.TrackURI || null
const queuePosition = parseInt(result.Track)
if (result.TrackMetaData && result.TrackMetaData !== 'NOT_IMPLEMENTED') { // There is some metadata, lets parse it.
const metadata = await Helpers.ParseXml(result.TrackMetaData)
const track = Helpers.ParseDIDL(metadata)
track.position = position
track.duration = duration
track.albumArtURL = !track.albumArtURI
? null
: track.albumArtURI.startsWith('http')
? track.albumArtURI
: 'http://' + this.host + ':' + this.port + track.albumArtURI
if (trackUri) track.uri = trackUri
track.queuePosition = queuePosition
return track
} else { // No metadata.
return { position, duration, queuePosition, uri: trackUri }
}
})
}
}
module.exports = AVTransport