-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSonosUPnP.h
570 lines (490 loc) · 24.3 KB
/
SonosUPnP.h
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
/************************************************************************/
/* Sonos UPnP, an UPnP based read/write remote control library, v1.1. */
/* */
/* This library is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* This library is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
/* General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this library. If not, see <http://www.gnu.org/licenses/>. */
/* */
/* Written by Thomas Mittet ([email protected]) January 2015. */
/************************************************************************/
struct JukeBoxSong
{
char artist[48];
char title[32];
char path[128];
int scheme; // sonos scheme
};
int GetSlotForMusicFile(char *musicfilename);
//# define DEBUG_XGEN 1
#ifndef SonosUPnP_h
#define SonosUPnP_h
//#define SONOS_WRITE_ONLY_MODE
#include "Arduino.h"
//#include "avr/pgmspace.h"
#include "pgmspace.h"
#ifndef SONOS_WRITE_ONLY_MODE
#include "MicroXPath_P.h"
#endif
#if defined(__AVR__)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif
// HTTP:
#define HTTP_VERSION " HTTP/1.1\n"
#define HEADER_HOST "Host: %d.%d.%d.%d:%d\n"
#define HEADER_CONTENT_TYPE "Content-Type: text/xml; charset=\"utf-8\"\n"
#define HEADER_CONTENT_LENGTH "Content-Length: %d\n"
#define HEADER_SOAP_ACTION "SOAPAction: \"urn:"
#define HEADER_SOAP_ACTION_END "\"\n"
#define HEADER_CONNECTION "Connection: close\n"
// SOAP tag data:
#define SOAP_ENVELOPE_START "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
#define SOAP_ENVELOPE_END "</s:Envelope>"
#define SOAP_BODY_START "<s:Body>"
#define SOAP_BODY_END "</s:Body>"
#define SOAP_TAG_START "<%s>"
#define SOAP_TAG_END "</%s>"
#define SOAP_TAG_LEN 5
#define SOAP_TAG_ENVELOPE "s:Envelope"
#define SOAP_TAG_BODY "s:Body"
// UPnP config:
#define UPNP_PORT 1400
#define UPNP_MULTICAST_IP (byte[]) {239,255,255,250}
#define UPNP_MULTICAST_PORT 1900
#define UPNP_MULTICAST_TIMEOUT_S 2
#define UPNP_RESPONSE_TIMEOUT_MS 3000
#define UPNP_DEVICE_SCAN "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 2\r\nST: urn:schemas-upnp-org:device:ZonePlayer:1\r\n\0"
//#define UPNP_DEVICE_SCAN "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 2\r\nST: ssdp:all\r\n\0"
// UPnP tag data:
#define SOAP_ACTION_START_TAG_START "<u:"
#define SOAP_ACTION_START_TAG_NS " xmlns:u=\"urn:"
#define SOAP_ACTION_START_TAG_END "\">"
#define SOAP_ACTION_END_TAG_START "</u:"
#define SOAP_ACTION_END_TAG_END ">"
#define SOAP_ACTION_TAG_LEN 24
// UPnP service data:
#define UPNP_URN_SCHEMA "schemas-upnp-org:service:"
#define UPNP_AV_TRANSPORT 1
#define UPNP_AV_TRANSPORT_SERVICE "AVTransport:1"
#define UPNP_AV_TRANSPORT_ENDPOINT "/MediaRenderer/AVTransport/Control"
#define UPNP_RENDERING_CONTROL 2
#define UPNP_RENDERING_CONTROL_SERVICE "RenderingControl:1"
#define UPNP_RENDERING_CONTROL_ENDPOINT "/MediaRenderer/RenderingControl/Control"
#define UPNP_DEVICE_PROPERTIES 3
#define UPNP_DEVICE_PROPERTIES_SERVICE "DeviceProperties:1"
#define UPNP_DEVICE_PROPERTIES_ENDPOINT "/DeviceProperties/Control"
// UPnP service data: added by frank
#define UPNP_CONTENT_DIRECTORY 4
#define UPNP_CONTENT_DIRECTORY_SERVICE "ContentDirectory:1"
#define UPNP_CONTENT_DIRECTORY_ENDPOINT "/MediaServer/ContentDirectory/Control"
#define SONOS_TAG_BROWSE "Browse"
#define SONOS_TAG_BROWSE_RESPONSE "u:BrowseResponse"
#define SONOS_TAG_BROWSE_FLAG "BrowseFlag"
#define SONOS_TAG_GET_ZONE_ATTR "GetZoneAttributes"
#define SONOS_TAG_GET_ZONE_ATTR_RESPONSE "u:GetZoneAttributesResponse"
#define SONOS_TAG_ZONENAME "CurrentZoneName"
#define SONOS_TAG_GET_ZONE_INFO "GetZoneInfo"
#define SONOS_TAG_GET_ZONE_INFO_RESPONSE "u:GetZoneInfoResponse"
#define SONOS_TAG_SERIAL "ExtraInfo"
#define SONOS_GET_ZPSUPPORTINFO "ZPSupportInfo"
#define SONOS_GET_ZPINFO "ZPInfo"
#define SONOS_GET_ZPZONE "ZoneName"
#define SONOS_GET_ZPLOCALUID "LocalUID"
#define SONOS_GET_ZPSERIAL "SerialNumber"
#define SONOS_GET_ZPSERIESID "SeriesID"
// Sonos speaker state control:
/*
<u:Play>
<InstanceID>0</InstanceID>
<Speed>1</Speed>
</u:Play>
<u:Seek>
<InstanceID>0</InstanceID>
<Unit>REL_TIME</Unit>
<Target>0:01:02</Target>
</u:Seek>
*/
#define SONOS_TAG_PLAY "Play"
#define SONOS_SOURCE_RINCON_TEMPLATE "RINCON_%s0%d%s"
#define SONOS_TAG_SPEED "Speed"
#define SONOS_TAG_STOP "Stop"
#define SONOS_TAG_PAUSE "Pause"
#define SONOS_TAG_PREVIOUS "Previous"
#define SONOS_TAG_NEXT "Next"
#define SONOS_DIRECTION_BACKWARD 0
#define SONOS_DIRECTION_FORWARD 1
#define SONOS_INSTANCE_ID_0_TAG "<InstanceID>0</InstanceID>"
#define SONOS_TAG_SEEK "Seek"
#define SONOS_TAG_TARGET "Target"
#define SONOS_SEEK_MODE_TAG_START "<Unit>"
#define SONOS_SEEK_MODE_TAG_END "</Unit>"
#define SONOS_SEEK_MODE_TRACK_NR "TRACK_NR"
#define SONOS_SEEK_MODE_REL_TIME "REL_TIME"
#define SONOS_TIME_FORMAT_TEMPLATE "%d:%02d:%02d"
#define SONOS_TAG_SET_AV_TRANSPORT_URI "SetAVTransportURI"
#define SONOS_TAG_CURRENT_URI "CurrentURI"
#define SONOS_URI_META_LIGHT_START "<CurrentURIMetaData>"
#define SONOS_URI_META_LIGHT_END "</CurrentURIMetaData>"
#define SONOS_RADIO_META_FULL_START "<CurrentURIMetaData><DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="R:0/0/46" parentID="R:0/0" restricted="true"><dc:title>"
#define SONOS_RADIO_META_FULL_END "</dc:title><upnp:class>object.item.audioItem.audioBroadcast</upnp:class><desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">SA_RINCON65031_</desc></item></DIDL-Lite></CurrentURIMetaData>"
#define SONOS_TAG_BECOME_COORDINATOR_OF_STANDALONE_GROUP "BecomeCoordinatorOfStandaloneGroup"
#define SONOS_TAG_SET_LED_STATE "SetLEDState"
#define SONOS_TAG_DESIRED_LED_STATE "DesiredLEDState"
// Playlist & Queue
/*
<u:AddURIToQueueResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<FirstTrackNumberEnqueued>21</FirstTrackNumberEnqueued>
<NumTracksAdded>36</NumTracksAdded>
<NewQueueLength>56</NewQueueLength>
</u:AddURIToQueueResponse>
*/
#define SONOS_TAG_ADD_URI_TO_QUEUE "AddURIToQueue"
#define SONOS_TAG_ENQUEUED_URI "EnqueuedURI"
#define SONOS_SAVED_QUEUES "file:///jffs/settings/savedqueues.rsq#%d"
#define SONOS_TAG_REMOVE_ALL_TRACKS_FROM_QUEUE "RemoveAllTracksFromQueue"
#define SONOS_PLAYLIST_META_LIGHT_START "<EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>"
#define SONOS_PLAYLIST_META_LIGHT_END "0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>1</EnqueueAsNext>"
//#define SONOS_PLAYLIST_META_FULL_START "<EnqueuedURIMetaData><DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="SQ:0" parentID="SQ:" restricted="true"><dc:title>"
//#define SONOS_PLAYLIST_META_FULL_END "</dc:title><upnp:class>object.container.playlistContainer</upnp:class><desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">RINCON_AssociatedZPUDN</desc></item></DIDL-Lite></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>1</EnqueueAsNext>"
// Track & source:
/*
<u:GetPositionInfoResponse>
<Track>1</Track>
<TrackDuration>0:03:21</TrackDuration>
<TrackMetaData>[Meta data in DIDL-Lite]</TrackMetaData>
<TrackURI></TrackURI>
<RelTime>0:01:23</RelTime>
<AbsTime>NOT_IMPLEMENTED</AbsTime>
<RelCount>2147483647</RelCount>
<AbsCount>2147483647</AbsCount>
</u:GetPositionInfoResponse>
*/
#define SONOS_TAG_GET_POSITION_INFO "GetPositionInfo"
#define SONOS_TAG_GET_POSITION_INFO_RESPONSE "u:GetPositionInfoResponse"
#define SONOS_TAG_TRACK "Track"
#define SONOS_TAG_NRTRACKS "NrTracks"
#define SONOS_TAG_TRACK_DURATION "TrackDuration"
#define SONOS_TAG_MEDIA_DURATION "MediaDuration"
#define SONOS_TAG_TRACK_URI "TrackURI"
#define SONOS_TAG_CURRENT_URI "CurrentURI"
#define SONOS_TAG_REL_TIME "RelTime"
#define SONOS_TAG_TRACK_METADATA "TrackMetaData"
#define SONOS_TAG_TRACKMETA "TrackMetaData"
#define SONOS_ATTRIB_TITLE "dc:title"
#define SONOS_ATTRIB_CREATOR "dc:creator"
#define SONOS_ATTRIB_ALBUM "upnp:album"
#define SONOS_ATTRIB_ARTIST "r:albumArtist"
#define SONOS_MAXSOURCE 14
#define SONOS_SOURCE_UNKNOWN_SCHEME "z-sonos-unknown:\0"
#define SONOS_SOURCE_SPOTIFY_SCHEME "x-sonos-spotify:\0"
#define SONOS_SOURCE_FILE_SCHEME "x-file-cifs:\0"
#define SONOS_SOURCE_LIBRARY_SCHEME "x-sonos-http:librarytrack\0" // apple afspeellijsten
#define SONOS_SOURCE_HTTP_SCHEME "x-sonos-http:\0"
#define SONOS_SOURCE_RADIO_SCHEME "x-rincon-mp3radio:\0"
#define SONOS_SOURCE_RADIO_AAC_SCHEME "aac:\0"
#define SONOS_SOURCE_LINEIN_SCHEME "x-rincon-stream:\0"
#define SONOS_SOURCE_MASTER_SCHEME "x-rincon:\0"
#define SONOS_SOURCE_QUEUE_SCHEME "x-rincon-queue:\0"
#define SONOS_SOURCE_SPOTIFYSTATION_SCHEME "x-sonosprog-spotify:\0"
#define SONOS_SOURCE_LOCALHTTP_SCHEME "http:\0"
#define SONOS_SOURCE_LOCALHTTPS_SCHEME "https:\0"
#define SONOS_SOURCE_SPOTIFY_RADIO_SCHEME "x-sonos-vli:\0" // apple afspeellijsten
#define SONOS_SOURCE_UNKNOWN 0
#define SONOS_SOURCE_SPOTIFY 1
#define SONOS_SOURCE_FILE 2
#define SONOS_SOURCE_LIBRARY 3
#define SONOS_SOURCE_HTTP 4
#define SONOS_SOURCE_RADIO 5
#define SONOS_SOURCE_RADIO_AAC 6
#define SONOS_SOURCE_LINEIN 7
#define SONOS_SOURCE_MASTER 8
#define SONOS_SOURCE_QUEUE 9
#define SONOS_SOURCE_SPOTIFYSTATION 10
#define SONOS_SOURCE_LOCALHTTP 11
#define SONOS_SOURCE_LOCALHTTPS 12
#define SONOS_SOURCE_SPOTIFY_RADIO 13
#define UNKNOWN_SCHEME "Unknown"
#define SPOTIFY_SCHEME "Spotify"
#define FILE_SCHEME "File"
#define LIBRARY_SCHEME "Libray"
#define HTTP_SCHEME "Http" // sonos thema radio , apple thema radio
#define RADIO_SCHEME "Radio"
#define RADIO_AAC_SCHEME "Radio AAC"
#define LINEIN_SCHEME "Line-In"
#define MASTER_SCHEME "Master"
#define QUEUE_SCHEME "Queue"
#define SPOTIFYSTATION_SCHEME "Spotify Station"
#define LOCALHTTP_SCHEME "Local Http"
#define LOCALHTTPS_SCHEME "Local Https"
#define SPOTIFY_RADIO_SCHEME "Spotify Radio"
#define SONOS_TAG_GET_MEDIA_INFO "GetMediaInfo"
#define SONOS_TAG_GET_MEDIA_INFO_RESPONSE "u:GetMediaInfoResponse"
#define SONOS_TAG_CURRENTURIMETADATA "CurrentURIMetaData"
// Volume, bass & treble:
/*
<u:GetVolume>
<InstanceID>0</InstanceID>
<Channel>Master</Channel>
</u:GetVolume>
<u:GetVolumeResponse>
<CurrentVolume>[0-100]</CurrentVolume>
</u:GetVolumeResponse>
*/
#define SONOS_TAG_CHANNEL "Channel"
#define SONOS_CHANNEL_MASTER "Master"
//#define SONOS_CHANNEL_LEFT "LF"
//#define SONOS_CHANNEL_RIGHT "RF"
#define SONOS_TAG_GET_MUTE "GetMute"
#define SONOS_TAG_GET_MUTE_RESPONSE "u:GetMuteResponse"
#define SONOS_TAG_CURRENT_MUTE "CurrentMute"
#define SONOS_TAG_GET_VOLUME "GetVolume"
#define SONOS_TAG_GET_VOLUME_RESPONSE "u:GetVolumeResponse"
#define SONOS_TAG_CURRENT_VOLUME "CurrentVolume"
#define SONOS_TAG_GET_OUTPUT_FIXED "GetOutputFixed"
#define SONOS_TAG_GET_FIXED_RESPONSE "u:GetOutputFixedResponse"
#define SONOS_TAG_CURRENT_FIXED "CurrentFixed"
#define SONOS_TAG_GET_BASS "GetBass"
#define SONOS_TAG_GET_BASS_RESPONSE "u:GetBassResponse"
#define SONOS_TAG_CURRENT_BASS "CurrentBass"
#define SONOS_TAG_GET_TREBLE "GetTreble"
#define SONOS_TAG_GET_TREBLE_RESPONSE "u:GetTrebleResponse"
#define SONOS_TAG_CURRENT_TREBLE "CurrentTreble"
#define SONOS_TAG_GET_LOUDNESS "GetLoudness"
#define SONOS_TAG_GET_LOUDNESS_RESPONSE "u:GetLoudnessResponse"
#define SONOS_TAG_CURRENT_LOUDNESS "CurrentLoudness"
// Set volume, bass & treble:
/*
<u:SetVolume>
<InstanceID>0</InstanceID>
<Channel>Master</Channel>
<DesiredVolume>[0-100]</DesiredVolume>
</u:SetVolume>
*/
#define SONOS_TAG_SET_MUTE "SetMute"
#define SONOS_TAG_DESIRED_MUTE "DesiredMute"
#define SONOS_TAG_SET_VOLUME "SetVolume"
#define SONOS_TAG_DESIRED_VOLUME "DesiredVolume"
#define SONOS_TAG_SET_BASS "SetBass"
#define SONOS_TAG_DESIRED_BASS "DesiredBass"
#define SONOS_TAG_SET_TREBLE "SetTreble"
#define SONOS_TAG_DESIRED_TREBLE "DesiredTreble"
#define SONOS_TAG_SET_LOUDNESS "SetLoudness"
#define SONOS_TAG_DESIRED_LOUDNESS "DesiredLoudness"
#define SONOS_CHANNEL_TAG_START "<Channel>"
#define SONOS_CHANNEL_TAG_END "</Channel>"
// Play Mode:
/*
<u:GetTransportSettingsResponse>
<PlayMode>[NORMAL/REPEAT_ALL/SHUFFLE/SHUFFLE_NOREPEAT]</PlayMode>
<RecQualityMode>NOT_IMPLEMENTED</RecQualityMode>
</u:GetTransportSettingsResponse>
*/
#define SONOS_TAG_GET_TRANSPORT_SETTINGS "GetTransportSettings"
#define SONOS_TAG_GET_TRANSPORT_SETTINGS_RESPONSE "u:GetTransportSettingsResponse"
#define SONOS_TAG_PLAY_MODE "PlayMode"
#define SONOS_PLAY_MODE_NORMAL B00
#define SONOS_PLAY_MODE_NORMAL_VALUE "NORMAL"
#define SONOS_PLAY_MODE_REPEAT B01
#define SONOS_PLAY_MODE_REPEAT_VALUE "REPEAT_ALL"
#define SONOS_PLAY_MODE_SHUFFLE B10
#define SONOS_PLAY_MODE_SHUFFLE_VALUE "SHUFFLE_NOREPEAT"
#define SONOS_PLAY_MODE_SHUFFLE_REPEAT B11
#define SONOS_PLAY_MODE_SHUFFLE_REPEAT_VALUE "SHUFFLE"
// Set Play Mode:
#define SONOS_TAG_SET_PLAY_MODE "SetPlayMode"
#define SONOS_TAG_NEW_PLAY_MODE "NewPlayMode"
// State:
/*
<u:GetTransportInfoResponse>
<CurrentTransportState>[PLAYING/PAUSED_PLAYBACK/STOPPED]</CurrentTransportState>
<CurrentTransportStatus>[OK/ERROR]</CurrentTransportStatus>
<CurrentSpeed>1</CurrentSpeed>
</u:GetTransportInfoResponse>
*/
#define SONOS_TAG_GET_MEDIA_INFO "GetMediaInfo"
#define SONOS_TAG_GET_MEDIA_INFO_RESPONSE "u:GetMediaInfoResponse"
#define SONOS_TAG_MEDIUM_STATUS "PlayMedium"
#define SONOS_MEDIUM_NONE 1
#define SONOS_MEDIUM_NONE_VALUE "NONE"
#define SONOS_MEDIUM_LINEIN 2
#define SONOS_MEDIUM_LINEIN_VALUE "LINE-IN"
#define SONOS_MEDIUM_NETWORK 3
#define SONOS_MEDIUM_NETWORK_VALUE "NETWORK"
#define SONOS_TAG_ARTIST_STATUS "CurrentURIMetaData"
#define SONOS_TAG_GET_TRANSPORT_INFO "GetTransportInfo"
#define SONOS_TAG_GET_TRANSPORT_INFO_RESPONSE "u:GetTransportInfoResponse"
#define SONOS_TAG_CURRENT_TRANSPORT_STATE "CurrentTransportState"
#define SONOS_STATE_PLAYING 1
#define SONOS_STATE_PLAYING_VALUE "PLAYING"
#define SONOS_STATE_PAUSED 2
#define SONOS_STATE_PAUSED_VALUE "PAUSED_PLAYBACK"
#define SONOS_STATE_STOPPED 3
#define SONOS_STATE_STOPPED_VALUE "STOPPED"
struct TrackInfo
{
uint16_t number;
uint32_t duration;
uint32_t position;
char *uri;
char *trackmetadata; // hier komt de artiest en track titel terecht - frank - 21mei2020
};
struct FullTrackInfo // JV new, pass text-info as char string
{
uint16_t number;
char *duration;
char *position;
char *creator;
char *title;
char *album;
char *artist;
};
struct SonosInfo // JV new, pass text info as Char string
{
uint16_t number;
char *uid; // Rincon-xxxx 32 bytes
char *serial; // 16 bytes serialnumber short - no '-'
char *seriesid; // Series ID or Sonos Type - 16bytes
char *zone; // Zone name - 32 bytes
char *medium; // medium - network, linein etc
char *status; // Status - play/stop/pause etc
char *playmode; // playmode, see SONOS_PLAY_MODE definitions
char *source; // source, defined in URI , see SONOS_SOURCE definitions
};
struct MediaInfo
{
uint16_t numberTracks;
char *uri;
char *uriMeta;
};
// https://developer.sonos.com/reference/sonos-music-api/getmediametadata/
// http://blog.travelmarx.com/2010/06/exploring-sonos-via-upnp.html
#define SONOS_TAG_GET_MEDIAMETADATA "GetMediaMetadata" // frank 24JUL20
#define SONOS_TAG_GET_MEDIAMETADATARESPONSE "GetMediaMetadataResponse" // frank 24JUL20
#define SONOS_TAG_GET_MEDIAMETADATARESULT "GetMediaMetadataResult" // frank 24JUL20
#define SONOS_TAG_ID "Id" // frank 24JUL20
#define SONOS_TAG_TITLE "Title" // frank 24JUL20
class SonosUPnP
{
public:
SonosUPnP(WiFiClient client, void (*ethernetErrCallback)(void));
void setAVTransportURI(IPAddress speakerIP, const char *scheme, const char *address);
void seekTrack(IPAddress speakerIP, uint16_t index);
void seekTime(IPAddress speakerIP, uint8_t hour, uint8_t minute, uint8_t second);
void setPlayMode(IPAddress speakerIP, uint8_t playMode);
void play(IPAddress speakerIP);
void playFile(IPAddress speakerIP, const char *path);
void playHttp(IPAddress speakerIP, const char *address);
void playRadio(IPAddress speakerIP, const char *address, const char *title);
void playLineIn(IPAddress speakerIP, const char *speakerID);
void playQueue(IPAddress speakerIP, const char *speakerID);
void playConnectToMaster(IPAddress speakerIP, const char *masterSpeakerID);
void disconnectFromMaster(IPAddress speakerIP);
void stop(IPAddress speakerIP);
void pause(IPAddress speakerIP);
void skip(IPAddress speakerIP, uint8_t direction);
void setMute(IPAddress speakerIP, bool state);
void setVolume(IPAddress speakerIP, uint8_t volume);
void setVolume(IPAddress speakerIP, uint8_t volume, const char *channel);
void setBass(IPAddress speakerIP, int8_t bass);
void setTreble(IPAddress speakerIP, int8_t treble);
void setLoudness(IPAddress speakerIP, bool state);
void setStatusLight(IPAddress speakerIP, bool state);
void addPlaylistToQueue(IPAddress speakerIP, uint16_t playlistIndex);
void addTrackToQueue(IPAddress speakerIP, const char *scheme, const char *address);
void removeAllTracksFromQueue(IPAddress speakerIP);
uint8_t CheckUPnP(IPAddress *List,int Listsize); // new JV uPnP IPlist check by SSDP over UDP
#ifndef SONOS_WRITE_ONLY_MODE
void setRepeat(IPAddress speakerIP, bool repeat);
void setShuffle(IPAddress speakerIP, bool shuffle);
void toggleRepeat(IPAddress speakerIP);
void toggleShuffle(IPAddress speakerIP);
void togglePause(IPAddress speakerIP);
void toggleMute(IPAddress speakerIP);
void toggleLoudness(IPAddress speakerIP);
uint8_t getState(IPAddress speakerIP,char *buf); // new JV : string passthrough
uint8_t getState(IPAddress speakerIP);
uint8_t getMedium(IPAddress speakerIP,char *buf); // new JV : string passthrough
uint8_t getMedium(IPAddress speakerIP); // new JV
uint8_t getPlayMode(IPAddress speakerIP,char *buf); // new JV : string passthrough
bool getZone(IPAddress speakerIP,char *buf); // new JV : string passthrough
bool getSerial(IPAddress speakerIP,char *buf); // new JV : string passthrough
uint8_t getSource(IPAddress speakerIP,char *buf); // new JV : string passthrough
uint8_t getSource(IPAddress speakerIP);
uint8_t getPlayMode(IPAddress speakerIP);
bool getRepeat(IPAddress speakerIP);
bool getShuffle(IPAddress speakerIP);
// TrackInfo getTrackInfo(IPAddress speakerIP, char *uriBuffer, size_t uriBufferSize);
TrackInfo getTrackInfo(IPAddress speakerIP, char *uriBuffer, size_t uriBufferSize, char *metaBuffer, size_t metaBufferSize);
// FB 7okt2020
MediaInfo getMediaInfo(IPAddress speakerIP, char *uriBuffer, size_t uriBufferSize, char *metaBuffer, size_t metaBufferSize);
uint16_t getTrackNumber(IPAddress speakerIP);
void getTrackURI(IPAddress speakerIP, char *resultBuffer, size_t resultBufferSize);
void getTrackCreator(IPAddress speakerIP, char *resultBuffer, size_t resultBufferSize); // new JV - parse XML Metadata attribute Creator
void getTrackTitle(IPAddress speakerIP, char *resultBuffer, size_t resultBufferSize); // new JV - parse XML Metadata attribute Title
void getTrackAlbum(IPAddress speakerIP, char *resultBuffer, size_t resultBufferSize); // new JV - parse XML Metadata attribute Album
uint8_t getSourceFromURI(const char *uri);
uint32_t getTrackDurationInSeconds(IPAddress speakerIP);
uint32_t getTrackPositionInSeconds(IPAddress speakerIP);
uint16_t getTrackPositionPerMille(IPAddress speakerIP);
bool getMute(IPAddress speakerIP);
uint8_t getVolume(IPAddress speakerIP);
uint8_t getVolume(IPAddress speakerIP, const char *channel);
bool getOutputFixed(IPAddress speakerIP);
int8_t getBass(IPAddress speakerIP);
int8_t getTreble(IPAddress speakerIP);
bool getLoudness(IPAddress speakerIP);
FullTrackInfo getFullTrackInfo(IPAddress speakerIP); // 18 mei nu starten alles ombouwen naar handiger data ophalen
SonosInfo getSonosInfo(IPAddress speakerIP); // new JV - parse Get status/zp XLM
// frank 30-jun-22
int getSonosPlayLists(IPAddress speakerIP);
int getSonosPlayLists2(IPAddress speakerIP);
#endif
private:
WiFiClient ethClient;
void (*ethernetErrCallback)(void);
void seek(IPAddress speakerIP, const char *mode, const char *data);
void setAVTransportURI(IPAddress speakerIP, const char *scheme, const char *address, PGM_P metaStart_P, PGM_P metaEnd_P, const char *metaValue);
void upnpSet(IPAddress ip, uint8_t upnpMessageType, PGM_P action_P);
void upnpSet(IPAddress ip, uint8_t upnpMessageType, PGM_P action_P, const char *field, const char *value);
void upnpSet(IPAddress ip, uint8_t upnpMessageType, PGM_P action_P, const char *field, const char *valueA, const char *valueB, PGM_P extraStart_P, PGM_P extraEnd_P, const char *extraValue);
bool upnpPost(IPAddress ip, uint8_t upnpMessageType, PGM_P action_P, const char *field, const char *valueA, const char *valueB, PGM_P extraStart_P, PGM_P extraEnd_P, const char *extraValue);
// frank
bool upnpPost2(IPAddress ip, uint8_t upnpMessageType, PGM_P action_P, const char *field1, const char *valueA, const char *field2, const char *valueB, const char *field3, const char *valueC, const char *field4, const char *valueD, const char *field5, const char *valueE, const char *field6, const char *valueF);
const char *getUpnpService(uint8_t upnpMessageType);
const char *getUpnpEndpoint(uint8_t upnpMessageType);
void ethClient_write(const char *data);
void ethClient_write_P(PGM_P data_P, char *buffer, size_t bufferSize);
void ethClient_stop();
void readback_IP(IPAddress *IPa,char* buf,char pointer,char bufsize); // New JV : readback IP from (UDP)buffer
bool upnpGetzp(IPAddress ip); // New JV GET command status/zp
#ifndef SONOS_WRITE_ONLY_MODE
MicroXPath_P xPath;
void ethClient_xPath(PGM_P *path, uint8_t pathSize, char *resultBuffer, size_t resultBufferSize);
void ethClient_xPath2(PGM_P *path, uint8_t pathSize, char *resultBuffer, size_t resultBufferSize); // modified version to search/parse in Metadata
void upnpGetString(IPAddress speakerIP, uint8_t upnpMessageType, PGM_P action_P, const char *field, const char *value, PGM_P *path, uint8_t pathSize, char *resultBuffer, size_t resultBufferSize);
uint32_t getTimeInSeconds(const char *time);
uint32_t uiPow(uint16_t base, uint16_t exp);
uint8_t convertMedium(const char *input);
uint8_t convertState(const char *input);
uint8_t convertPlayMode(const char *input);
uint8_t convertMetaData(char *input );
#endif
};
#endif
//#ifdef ESP8266 //has no strlcpy_P
/* size_t ICACHE_FLASH_ATTR strlcpy_P(char* dest, const char* src, size_t size) {
const char* read = src;
char* write = dest;
*/