sonos/
generated.rs

1// This file was auto-generated by codegen! Do not edit!
2
3use crate::upnp::DecodeXml;
4use crate::xmlutil::DecodeXmlString;
5use crate::{Result, SonosDevice};
6use instant_xml::{FromXml, ToXml};
7use std::str::FromStr;
8
9/// Request and Response types for the `AVTransport` service.
10pub mod av_transport {
11    use super::*;
12
13    /// URN for the `AVTransport` service.
14    /// `urn:schemas-upnp-org:service:AVTransport:1`
15    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:AVTransport:1";
16
17    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
18    #[xml(rename = "AddMultipleURIsToQueue", ns(SERVICE_TYPE))]
19    pub struct AddMultipleUrisToQueueRequest {
20        #[xml(rename = "InstanceID", ns(""))]
21        pub instance_id: u32,
22        #[xml(rename = "UpdateID", ns(""))]
23        pub update_id: u32,
24        #[xml(rename = "NumberOfURIs", ns(""))]
25        pub number_of_uris: u32,
26        #[xml(rename = "EnqueuedURIs", ns(""))]
27        pub enqueued_uris: String,
28        #[xml(rename = "EnqueuedURIsMetaData", ns(""))]
29        pub enqueued_uris_meta_data: String,
30        #[xml(rename = "ContainerURI", ns(""))]
31        pub container_uri: String,
32        #[xml(rename = "ContainerMetaData", ns(""))]
33        pub container_meta_data: String,
34        #[xml(rename = "DesiredFirstTrackNumberEnqueued", ns(""))]
35        pub desired_first_track_number_enqueued: u32,
36        #[xml(rename = "EnqueueAsNext", ns(""))]
37        pub enqueue_as_next: bool,
38    }
39
40    #[derive(FromXml, Debug, Clone, PartialEq)]
41    #[xml(rename = "AddMultipleURIsToQueueResponse", ns(SERVICE_TYPE))]
42    pub struct AddMultipleUrisToQueueResponse {
43        #[xml(rename = "FirstTrackNumberEnqueued", ns(""))]
44        pub first_track_number_enqueued: Option<u32>,
45        #[xml(rename = "NumTracksAdded", ns(""))]
46        pub num_tracks_added: Option<u32>,
47        #[xml(rename = "NewQueueLength", ns(""))]
48        pub new_queue_length: Option<u32>,
49        #[xml(rename = "NewUpdateID", ns(""))]
50        pub new_update_id: Option<u32>,
51    }
52
53    impl crate::DecodeSoapResponse for AddMultipleUrisToQueueResponse {
54        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
55            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
56            Ok(envelope.body.payload)
57        }
58    }
59
60    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
61    #[xml(rename = "AddURIToQueue", ns(SERVICE_TYPE))]
62    pub struct AddUriToQueueRequest {
63        #[xml(rename = "InstanceID", ns(""))]
64        pub instance_id: u32,
65        #[xml(rename = "EnqueuedURI", ns(""))]
66        pub enqueued_uri: String,
67        #[xml(rename = "EnqueuedURIMetaData", ns(""))]
68        pub enqueued_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
69        /// use `0` to add at the end or `1` to insert at the beginning
70        #[xml(rename = "DesiredFirstTrackNumberEnqueued", ns(""))]
71        pub desired_first_track_number_enqueued: u32,
72        #[xml(rename = "EnqueueAsNext", ns(""))]
73        pub enqueue_as_next: bool,
74    }
75
76    #[derive(FromXml, Debug, Clone, PartialEq)]
77    #[xml(rename = "AddURIToQueueResponse", ns(SERVICE_TYPE))]
78    pub struct AddUriToQueueResponse {
79        #[xml(rename = "FirstTrackNumberEnqueued", ns(""))]
80        pub first_track_number_enqueued: Option<u32>,
81        #[xml(rename = "NumTracksAdded", ns(""))]
82        pub num_tracks_added: Option<u32>,
83        #[xml(rename = "NewQueueLength", ns(""))]
84        pub new_queue_length: Option<u32>,
85    }
86
87    impl crate::DecodeSoapResponse for AddUriToQueueResponse {
88        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
89            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
90            Ok(envelope.body.payload)
91        }
92    }
93
94    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
95    #[xml(rename = "AddURIToSavedQueue", ns(SERVICE_TYPE))]
96    pub struct AddUriToSavedQueueRequest {
97        #[xml(rename = "InstanceID", ns(""))]
98        pub instance_id: u32,
99        #[xml(rename = "ObjectID", ns(""))]
100        pub object_id: String,
101        #[xml(rename = "UpdateID", ns(""))]
102        pub update_id: u32,
103        #[xml(rename = "EnqueuedURI", ns(""))]
104        pub enqueued_uri: String,
105        #[xml(rename = "EnqueuedURIMetaData", ns(""))]
106        pub enqueued_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
107        #[xml(rename = "AddAtIndex", ns(""))]
108        pub add_at_index: u32,
109    }
110
111    #[derive(FromXml, Debug, Clone, PartialEq)]
112    #[xml(rename = "AddURIToSavedQueueResponse", ns(SERVICE_TYPE))]
113    pub struct AddUriToSavedQueueResponse {
114        #[xml(rename = "NumTracksAdded", ns(""))]
115        pub num_tracks_added: Option<u32>,
116        #[xml(rename = "NewQueueLength", ns(""))]
117        pub new_queue_length: Option<u32>,
118        #[xml(rename = "NewUpdateID", ns(""))]
119        pub new_update_id: Option<u32>,
120    }
121
122    impl crate::DecodeSoapResponse for AddUriToSavedQueueResponse {
123        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
124            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
125            Ok(envelope.body.payload)
126        }
127    }
128
129    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
130    #[xml(rename = "BackupQueue", ns(SERVICE_TYPE))]
131    pub struct BackupQueueRequest {
132        #[xml(rename = "InstanceID", ns(""))]
133        pub instance_id: u32,
134    }
135
136    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
137    #[xml(rename = "BecomeCoordinatorOfStandaloneGroup", ns(SERVICE_TYPE))]
138    pub struct BecomeCoordinatorOfStandaloneGroupRequest {
139        #[xml(rename = "InstanceID", ns(""))]
140        pub instance_id: u32,
141    }
142
143    #[derive(FromXml, Debug, Clone, PartialEq)]
144    #[xml(
145        rename = "BecomeCoordinatorOfStandaloneGroupResponse",
146        ns(SERVICE_TYPE)
147    )]
148    pub struct BecomeCoordinatorOfStandaloneGroupResponse {
149        #[xml(rename = "DelegatedGroupCoordinatorID", ns(""))]
150        pub delegated_group_coordinator_id: Option<String>,
151        #[xml(rename = "NewGroupID", ns(""))]
152        pub new_group_id: Option<String>,
153    }
154
155    impl crate::DecodeSoapResponse for BecomeCoordinatorOfStandaloneGroupResponse {
156        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
157            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
158            Ok(envelope.body.payload)
159        }
160    }
161
162    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
163    #[xml(rename = "BecomeGroupCoordinator", ns(SERVICE_TYPE))]
164    pub struct BecomeGroupCoordinatorRequest {
165        #[xml(rename = "InstanceID", ns(""))]
166        pub instance_id: u32,
167        #[xml(rename = "CurrentCoordinator", ns(""))]
168        pub current_coordinator: String,
169        #[xml(rename = "CurrentGroupID", ns(""))]
170        pub current_group_id: String,
171        #[xml(rename = "OtherMembers", ns(""))]
172        pub other_members: String,
173        #[xml(rename = "TransportSettings", ns(""))]
174        pub transport_settings: String,
175        #[xml(rename = "CurrentURI", ns(""))]
176        pub current_uri: String,
177        #[xml(rename = "CurrentURIMetaData", ns(""))]
178        pub current_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
179        #[xml(rename = "SleepTimerState", ns(""))]
180        pub sleep_timer_state: String,
181        #[xml(rename = "AlarmState", ns(""))]
182        pub alarm_state: String,
183        #[xml(rename = "StreamRestartState", ns(""))]
184        pub stream_restart_state: String,
185        #[xml(rename = "CurrentQueueTrackList", ns(""))]
186        pub current_queue_track_list: String,
187        #[xml(rename = "CurrentVLIState", ns(""))]
188        pub current_vli_state: String,
189    }
190
191    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
192    #[xml(rename = "BecomeGroupCoordinatorAndSource", ns(SERVICE_TYPE))]
193    pub struct BecomeGroupCoordinatorAndSourceRequest {
194        #[xml(rename = "InstanceID", ns(""))]
195        pub instance_id: u32,
196        #[xml(rename = "CurrentCoordinator", ns(""))]
197        pub current_coordinator: String,
198        #[xml(rename = "CurrentGroupID", ns(""))]
199        pub current_group_id: String,
200        #[xml(rename = "OtherMembers", ns(""))]
201        pub other_members: String,
202        #[xml(rename = "CurrentURI", ns(""))]
203        pub current_uri: String,
204        #[xml(rename = "CurrentURIMetaData", ns(""))]
205        pub current_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
206        #[xml(rename = "SleepTimerState", ns(""))]
207        pub sleep_timer_state: String,
208        #[xml(rename = "AlarmState", ns(""))]
209        pub alarm_state: String,
210        #[xml(rename = "StreamRestartState", ns(""))]
211        pub stream_restart_state: String,
212        #[xml(rename = "CurrentAVTTrackList", ns(""))]
213        pub current_avt_track_list: String,
214        #[xml(rename = "CurrentQueueTrackList", ns(""))]
215        pub current_queue_track_list: String,
216        #[xml(rename = "CurrentSourceState", ns(""))]
217        pub current_source_state: String,
218        #[xml(rename = "ResumePlayback", ns(""))]
219        pub resume_playback: bool,
220    }
221
222    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
223    #[xml(rename = "ChangeCoordinator", ns(SERVICE_TYPE))]
224    pub struct ChangeCoordinatorRequest {
225        #[xml(rename = "InstanceID", ns(""))]
226        pub instance_id: u32,
227        #[xml(rename = "CurrentCoordinator", ns(""))]
228        pub current_coordinator: String,
229        #[xml(rename = "NewCoordinator", ns(""))]
230        pub new_coordinator: String,
231        #[xml(rename = "NewTransportSettings", ns(""))]
232        pub new_transport_settings: String,
233        #[xml(rename = "CurrentAVTransportURI", ns(""))]
234        pub current_av_transport_uri: String,
235    }
236
237    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
238    #[xml(rename = "ChangeTransportSettings", ns(SERVICE_TYPE))]
239    pub struct ChangeTransportSettingsRequest {
240        #[xml(rename = "InstanceID", ns(""))]
241        pub instance_id: u32,
242        #[xml(rename = "NewTransportSettings", ns(""))]
243        pub new_transport_settings: String,
244        #[xml(rename = "CurrentAVTransportURI", ns(""))]
245        pub current_av_transport_uri: String,
246    }
247
248    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
249    #[xml(rename = "ConfigureSleepTimer", ns(SERVICE_TYPE))]
250    pub struct ConfigureSleepTimerRequest {
251        #[xml(rename = "InstanceID", ns(""))]
252        pub instance_id: u32,
253        /// Time to stop after, as `hh:mm:ss` or empty string to cancel
254        #[xml(rename = "NewSleepTimerDuration", ns(""))]
255        pub new_sleep_timer_duration: String,
256    }
257
258    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
259    #[xml(rename = "CreateSavedQueue", ns(SERVICE_TYPE))]
260    pub struct CreateSavedQueueRequest {
261        #[xml(rename = "InstanceID", ns(""))]
262        pub instance_id: u32,
263        #[xml(rename = "Title", ns(""))]
264        pub title: String,
265        #[xml(rename = "EnqueuedURI", ns(""))]
266        pub enqueued_uri: String,
267        #[xml(rename = "EnqueuedURIMetaData", ns(""))]
268        pub enqueued_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
269    }
270
271    #[derive(FromXml, Debug, Clone, PartialEq)]
272    #[xml(rename = "CreateSavedQueueResponse", ns(SERVICE_TYPE))]
273    pub struct CreateSavedQueueResponse {
274        #[xml(rename = "NumTracksAdded", ns(""))]
275        pub num_tracks_added: Option<u32>,
276        #[xml(rename = "NewQueueLength", ns(""))]
277        pub new_queue_length: Option<u32>,
278        #[xml(rename = "AssignedObjectID", ns(""))]
279        pub assigned_object_id: Option<String>,
280        #[xml(rename = "NewUpdateID", ns(""))]
281        pub new_update_id: Option<u32>,
282    }
283
284    impl crate::DecodeSoapResponse for CreateSavedQueueResponse {
285        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
286            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
287            Ok(envelope.body.payload)
288        }
289    }
290
291    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
292    #[xml(rename = "DelegateGroupCoordinationTo", ns(SERVICE_TYPE))]
293    pub struct DelegateGroupCoordinationToRequest {
294        #[xml(rename = "InstanceID", ns(""))]
295        pub instance_id: u32,
296        /// uuid of the new coordinator - must be in same group
297        #[xml(rename = "NewCoordinator", ns(""))]
298        pub new_coordinator: String,
299        /// Should former coordinator rejoin the group?
300        #[xml(rename = "RejoinGroup", ns(""))]
301        pub rejoin_group: bool,
302    }
303
304    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
305    #[xml(rename = "EndDirectControlSession", ns(SERVICE_TYPE))]
306    pub struct EndDirectControlSessionRequest {
307        #[xml(rename = "InstanceID", ns(""))]
308        pub instance_id: u32,
309    }
310
311    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
312    #[xml(rename = "GetCrossfadeMode", ns(SERVICE_TYPE))]
313    pub struct GetCrossfadeModeRequest {
314        #[xml(rename = "InstanceID", ns(""))]
315        pub instance_id: u32,
316    }
317
318    #[derive(FromXml, Debug, Clone, PartialEq)]
319    #[xml(rename = "GetCrossfadeModeResponse", ns(SERVICE_TYPE))]
320    pub struct GetCrossfadeModeResponse {
321        #[xml(rename = "CrossfadeMode", ns(""))]
322        pub crossfade_mode: Option<bool>,
323    }
324
325    impl crate::DecodeSoapResponse for GetCrossfadeModeResponse {
326        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
327            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
328            Ok(envelope.body.payload)
329        }
330    }
331
332    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
333    #[xml(rename = "GetCurrentTransportActions", ns(SERVICE_TYPE))]
334    pub struct GetCurrentTransportActionsRequest {
335        #[xml(rename = "InstanceID", ns(""))]
336        pub instance_id: u32,
337    }
338
339    #[derive(FromXml, Debug, Clone, PartialEq)]
340    #[xml(rename = "GetCurrentTransportActionsResponse", ns(SERVICE_TYPE))]
341    pub struct GetCurrentTransportActionsResponse {
342        #[xml(rename = "Actions", ns(""))]
343        pub actions: Option<String>,
344    }
345
346    impl crate::DecodeSoapResponse for GetCurrentTransportActionsResponse {
347        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
348            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
349            Ok(envelope.body.payload)
350        }
351    }
352
353    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
354    #[xml(rename = "GetDeviceCapabilities", ns(SERVICE_TYPE))]
355    pub struct GetDeviceCapabilitiesRequest {
356        #[xml(rename = "InstanceID", ns(""))]
357        pub instance_id: u32,
358    }
359
360    #[derive(FromXml, Debug, Clone, PartialEq)]
361    #[xml(rename = "GetDeviceCapabilitiesResponse", ns(SERVICE_TYPE))]
362    pub struct GetDeviceCapabilitiesResponse {
363        #[xml(rename = "PlayMedia", ns(""))]
364        pub play_media: Option<String>,
365        #[xml(rename = "RecMedia", ns(""))]
366        pub rec_media: Option<String>,
367        #[xml(rename = "RecQualityModes", ns(""))]
368        pub rec_quality_modes: Option<String>,
369    }
370
371    impl crate::DecodeSoapResponse for GetDeviceCapabilitiesResponse {
372        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
373            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
374            Ok(envelope.body.payload)
375        }
376    }
377
378    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
379    #[xml(rename = "GetMediaInfo", ns(SERVICE_TYPE))]
380    pub struct GetMediaInfoRequest {
381        #[xml(rename = "InstanceID", ns(""))]
382        pub instance_id: u32,
383    }
384
385    #[derive(FromXml, Debug, Clone, PartialEq)]
386    #[xml(rename = "GetMediaInfoResponse", ns(SERVICE_TYPE))]
387    pub struct GetMediaInfoResponse {
388        #[xml(rename = "NrTracks", ns(""))]
389        pub nr_tracks: Option<u32>,
390        #[xml(rename = "MediaDuration", ns(""))]
391        pub media_duration: Option<String>,
392        #[xml(rename = "CurrentURI", ns(""))]
393        pub current_uri: Option<String>,
394        #[xml(rename = "CurrentURIMetaData", ns(""))]
395        pub current_uri_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
396        #[xml(rename = "NextURI", ns(""))]
397        pub next_uri: Option<String>,
398        #[xml(rename = "NextURIMetaData", ns(""))]
399        pub next_uri_meta_data: Option<String>,
400        #[xml(rename = "PlayMedium", ns(""))]
401        pub play_medium: Option<super::PlaybackStorageMedium>,
402        #[xml(rename = "RecordMedium", ns(""))]
403        pub record_medium: Option<String>,
404        #[xml(rename = "WriteStatus", ns(""))]
405        pub write_status: Option<String>,
406    }
407
408    impl crate::DecodeSoapResponse for GetMediaInfoResponse {
409        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
410            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
411            Ok(envelope.body.payload)
412        }
413    }
414
415    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
416    #[xml(rename = "GetPositionInfo", ns(SERVICE_TYPE))]
417    pub struct GetPositionInfoRequest {
418        #[xml(rename = "InstanceID", ns(""))]
419        pub instance_id: u32,
420    }
421
422    #[derive(FromXml, Debug, Clone, PartialEq)]
423    #[xml(rename = "GetPositionInfoResponse", ns(SERVICE_TYPE))]
424    pub struct GetPositionInfoResponse {
425        #[xml(rename = "Track", ns(""))]
426        pub track: Option<u32>,
427        #[xml(rename = "TrackDuration", ns(""))]
428        pub track_duration: Option<String>,
429        #[xml(rename = "TrackMetaData", ns(""))]
430        pub track_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
431        #[xml(rename = "TrackURI", ns(""))]
432        pub track_uri: Option<String>,
433        #[xml(rename = "RelTime", ns(""))]
434        pub rel_time: Option<String>,
435        #[xml(rename = "AbsTime", ns(""))]
436        pub abs_time: Option<String>,
437        #[xml(rename = "RelCount", ns(""))]
438        pub rel_count: Option<i32>,
439        #[xml(rename = "AbsCount", ns(""))]
440        pub abs_count: Option<i32>,
441    }
442
443    impl crate::DecodeSoapResponse for GetPositionInfoResponse {
444        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
445            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
446            Ok(envelope.body.payload)
447        }
448    }
449
450    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
451    #[xml(rename = "GetRemainingSleepTimerDuration", ns(SERVICE_TYPE))]
452    pub struct GetRemainingSleepTimerDurationRequest {
453        #[xml(rename = "InstanceID", ns(""))]
454        pub instance_id: u32,
455    }
456
457    #[derive(FromXml, Debug, Clone, PartialEq)]
458    #[xml(rename = "GetRemainingSleepTimerDurationResponse", ns(SERVICE_TYPE))]
459    pub struct GetRemainingSleepTimerDurationResponse {
460        #[xml(rename = "RemainingSleepTimerDuration", ns(""))]
461        pub remaining_sleep_timer_duration: Option<String>,
462        #[xml(rename = "CurrentSleepTimerGeneration", ns(""))]
463        pub current_sleep_timer_generation: Option<u32>,
464    }
465
466    impl crate::DecodeSoapResponse for GetRemainingSleepTimerDurationResponse {
467        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
468            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
469            Ok(envelope.body.payload)
470        }
471    }
472
473    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
474    #[xml(rename = "GetRunningAlarmProperties", ns(SERVICE_TYPE))]
475    pub struct GetRunningAlarmPropertiesRequest {
476        #[xml(rename = "InstanceID", ns(""))]
477        pub instance_id: u32,
478    }
479
480    #[derive(FromXml, Debug, Clone, PartialEq)]
481    #[xml(rename = "GetRunningAlarmPropertiesResponse", ns(SERVICE_TYPE))]
482    pub struct GetRunningAlarmPropertiesResponse {
483        #[xml(rename = "AlarmID", ns(""))]
484        pub alarm_id: Option<u32>,
485        #[xml(rename = "GroupID", ns(""))]
486        pub group_id: Option<String>,
487        #[xml(rename = "LoggedStartTime", ns(""))]
488        pub logged_start_time: Option<String>,
489    }
490
491    impl crate::DecodeSoapResponse for GetRunningAlarmPropertiesResponse {
492        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
493            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
494            Ok(envelope.body.payload)
495        }
496    }
497
498    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
499    #[xml(rename = "GetTransportInfo", ns(SERVICE_TYPE))]
500    pub struct GetTransportInfoRequest {
501        #[xml(rename = "InstanceID", ns(""))]
502        pub instance_id: u32,
503    }
504
505    #[derive(FromXml, Debug, Clone, PartialEq)]
506    #[xml(rename = "GetTransportInfoResponse", ns(SERVICE_TYPE))]
507    pub struct GetTransportInfoResponse {
508        #[xml(rename = "CurrentTransportState", ns(""))]
509        pub current_transport_state: Option<super::TransportState>,
510        #[xml(rename = "CurrentTransportStatus", ns(""))]
511        pub current_transport_status: Option<String>,
512        #[xml(rename = "CurrentSpeed", ns(""))]
513        pub current_speed: Option<String>,
514    }
515
516    impl crate::DecodeSoapResponse for GetTransportInfoResponse {
517        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
518            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
519            Ok(envelope.body.payload)
520        }
521    }
522
523    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
524    #[xml(rename = "GetTransportSettings", ns(SERVICE_TYPE))]
525    pub struct GetTransportSettingsRequest {
526        #[xml(rename = "InstanceID", ns(""))]
527        pub instance_id: u32,
528    }
529
530    #[derive(FromXml, Debug, Clone, PartialEq)]
531    #[xml(rename = "GetTransportSettingsResponse", ns(SERVICE_TYPE))]
532    pub struct GetTransportSettingsResponse {
533        #[xml(rename = "PlayMode", ns(""))]
534        pub play_mode: Option<super::CurrentPlayMode>,
535        #[xml(rename = "RecQualityMode", ns(""))]
536        pub rec_quality_mode: Option<String>,
537    }
538
539    impl crate::DecodeSoapResponse for GetTransportSettingsResponse {
540        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
541            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
542            Ok(envelope.body.payload)
543        }
544    }
545
546    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
547    #[xml(rename = "Next", ns(SERVICE_TYPE))]
548    pub struct NextRequest {
549        #[xml(rename = "InstanceID", ns(""))]
550        pub instance_id: u32,
551    }
552
553    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
554    #[xml(rename = "NotifyDeletedURI", ns(SERVICE_TYPE))]
555    pub struct NotifyDeletedUriRequest {
556        #[xml(rename = "InstanceID", ns(""))]
557        pub instance_id: u32,
558        #[xml(rename = "DeletedURI", ns(""))]
559        pub deleted_uri: String,
560    }
561
562    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
563    #[xml(rename = "Pause", ns(SERVICE_TYPE))]
564    pub struct PauseRequest {
565        #[xml(rename = "InstanceID", ns(""))]
566        pub instance_id: u32,
567    }
568
569    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
570    #[xml(rename = "Play", ns(SERVICE_TYPE))]
571    pub struct PlayRequest {
572        #[xml(rename = "InstanceID", ns(""))]
573        pub instance_id: u32,
574        /// Play speed usually 1, can be a fraction of 1
575        #[xml(rename = "Speed", ns(""))]
576        pub speed: String,
577    }
578
579    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
580    #[xml(rename = "Previous", ns(SERVICE_TYPE))]
581    pub struct PreviousRequest {
582        #[xml(rename = "InstanceID", ns(""))]
583        pub instance_id: u32,
584    }
585
586    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
587    #[xml(rename = "RemoveAllTracksFromQueue", ns(SERVICE_TYPE))]
588    pub struct RemoveAllTracksFromQueueRequest {
589        #[xml(rename = "InstanceID", ns(""))]
590        pub instance_id: u32,
591    }
592
593    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
594    #[xml(rename = "RemoveTrackFromQueue", ns(SERVICE_TYPE))]
595    pub struct RemoveTrackFromQueueRequest {
596        #[xml(rename = "InstanceID", ns(""))]
597        pub instance_id: u32,
598        #[xml(rename = "ObjectID", ns(""))]
599        pub object_id: String,
600        #[xml(rename = "UpdateID", ns(""))]
601        pub update_id: u32,
602    }
603
604    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
605    #[xml(rename = "RemoveTrackRangeFromQueue", ns(SERVICE_TYPE))]
606    pub struct RemoveTrackRangeFromQueueRequest {
607        #[xml(rename = "InstanceID", ns(""))]
608        pub instance_id: u32,
609        /// Leave blank
610        #[xml(rename = "UpdateID", ns(""))]
611        pub update_id: u32,
612        /// between 1 and queue-length
613        #[xml(rename = "StartingIndex", ns(""))]
614        pub starting_index: u32,
615        #[xml(rename = "NumberOfTracks", ns(""))]
616        pub number_of_tracks: u32,
617    }
618
619    #[derive(FromXml, Debug, Clone, PartialEq)]
620    #[xml(rename = "RemoveTrackRangeFromQueueResponse", ns(SERVICE_TYPE))]
621    pub struct RemoveTrackRangeFromQueueResponse {
622        #[xml(rename = "NewUpdateID", ns(""))]
623        pub new_update_id: Option<u32>,
624    }
625
626    impl crate::DecodeSoapResponse for RemoveTrackRangeFromQueueResponse {
627        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
628            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
629            Ok(envelope.body.payload)
630        }
631    }
632
633    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
634    #[xml(rename = "ReorderTracksInQueue", ns(SERVICE_TYPE))]
635    pub struct ReorderTracksInQueueRequest {
636        #[xml(rename = "InstanceID", ns(""))]
637        pub instance_id: u32,
638        #[xml(rename = "StartingIndex", ns(""))]
639        pub starting_index: u32,
640        #[xml(rename = "NumberOfTracks", ns(""))]
641        pub number_of_tracks: u32,
642        #[xml(rename = "InsertBefore", ns(""))]
643        pub insert_before: u32,
644        #[xml(rename = "UpdateID", ns(""))]
645        pub update_id: u32,
646    }
647
648    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
649    #[xml(rename = "ReorderTracksInSavedQueue", ns(SERVICE_TYPE))]
650    pub struct ReorderTracksInSavedQueueRequest {
651        #[xml(rename = "InstanceID", ns(""))]
652        pub instance_id: u32,
653        #[xml(rename = "ObjectID", ns(""))]
654        pub object_id: String,
655        #[xml(rename = "UpdateID", ns(""))]
656        pub update_id: u32,
657        #[xml(rename = "TrackList", ns(""))]
658        pub track_list: String,
659        #[xml(rename = "NewPositionList", ns(""))]
660        pub new_position_list: String,
661    }
662
663    #[derive(FromXml, Debug, Clone, PartialEq)]
664    #[xml(rename = "ReorderTracksInSavedQueueResponse", ns(SERVICE_TYPE))]
665    pub struct ReorderTracksInSavedQueueResponse {
666        #[xml(rename = "QueueLengthChange", ns(""))]
667        pub queue_length_change: Option<i32>,
668        #[xml(rename = "NewQueueLength", ns(""))]
669        pub new_queue_length: Option<u32>,
670        #[xml(rename = "NewUpdateID", ns(""))]
671        pub new_update_id: Option<u32>,
672    }
673
674    impl crate::DecodeSoapResponse for ReorderTracksInSavedQueueResponse {
675        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
676            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
677            Ok(envelope.body.payload)
678        }
679    }
680
681    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
682    #[xml(rename = "RunAlarm", ns(SERVICE_TYPE))]
683    pub struct RunAlarmRequest {
684        #[xml(rename = "InstanceID", ns(""))]
685        pub instance_id: u32,
686        #[xml(rename = "AlarmID", ns(""))]
687        pub alarm_id: u32,
688        #[xml(rename = "LoggedStartTime", ns(""))]
689        pub logged_start_time: String,
690        #[xml(rename = "Duration", ns(""))]
691        pub duration: String,
692        #[xml(rename = "ProgramURI", ns(""))]
693        pub program_uri: String,
694        #[xml(rename = "ProgramMetaData", ns(""))]
695        pub program_meta_data: DecodeXmlString<crate::TrackMetaData>,
696        #[xml(rename = "PlayMode", ns(""))]
697        pub play_mode: super::CurrentPlayMode,
698        #[xml(rename = "Volume", ns(""))]
699        pub volume: u16,
700        #[xml(rename = "IncludeLinkedZones", ns(""))]
701        pub include_linked_zones: bool,
702    }
703
704    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
705    #[xml(rename = "SaveQueue", ns(SERVICE_TYPE))]
706    pub struct SaveQueueRequest {
707        #[xml(rename = "InstanceID", ns(""))]
708        pub instance_id: u32,
709        /// SONOS playlist title
710        #[xml(rename = "Title", ns(""))]
711        pub title: String,
712        /// Leave blank
713        #[xml(rename = "ObjectID", ns(""))]
714        pub object_id: String,
715    }
716
717    #[derive(FromXml, Debug, Clone, PartialEq)]
718    #[xml(rename = "SaveQueueResponse", ns(SERVICE_TYPE))]
719    pub struct SaveQueueResponse {
720        #[xml(rename = "AssignedObjectID", ns(""))]
721        pub assigned_object_id: Option<String>,
722    }
723
724    impl crate::DecodeSoapResponse for SaveQueueResponse {
725        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
726            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
727            Ok(envelope.body.payload)
728        }
729    }
730
731    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
732    #[xml(rename = "Seek", ns(SERVICE_TYPE))]
733    pub struct SeekRequest {
734        #[xml(rename = "InstanceID", ns(""))]
735        pub instance_id: u32,
736        /// What to seek
737        #[xml(rename = "Unit", ns(""))]
738        pub unit: super::SeekMode,
739        /// Position of track in queue (start at 1) or `hh:mm:ss` for `REL_TIME` or `+/-hh:mm:ss` for `TIME_DELTA`
740        #[xml(rename = "Target", ns(""))]
741        pub target: String,
742    }
743
744    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
745    #[xml(rename = "SetAVTransportURI", ns(SERVICE_TYPE))]
746    pub struct SetAvTransportUriRequest {
747        #[xml(rename = "InstanceID", ns(""))]
748        pub instance_id: u32,
749        /// The new TransportURI - its a special SONOS format
750        #[xml(rename = "CurrentURI", ns(""))]
751        pub current_uri: String,
752        /// Track Metadata, see MetadataHelper.GuessTrack to guess based on track uri
753        #[xml(rename = "CurrentURIMetaData", ns(""))]
754        pub current_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
755    }
756
757    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
758    #[xml(rename = "SetCrossfadeMode", ns(SERVICE_TYPE))]
759    pub struct SetCrossfadeModeRequest {
760        #[xml(rename = "InstanceID", ns(""))]
761        pub instance_id: u32,
762        #[xml(rename = "CrossfadeMode", ns(""))]
763        pub crossfade_mode: bool,
764    }
765
766    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
767    #[xml(rename = "SetNextAVTransportURI", ns(SERVICE_TYPE))]
768    pub struct SetNextAvTransportUriRequest {
769        #[xml(rename = "InstanceID", ns(""))]
770        pub instance_id: u32,
771        #[xml(rename = "NextURI", ns(""))]
772        pub next_uri: String,
773        #[xml(rename = "NextURIMetaData", ns(""))]
774        pub next_uri_meta_data: String,
775    }
776
777    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
778    #[xml(rename = "SetPlayMode", ns(SERVICE_TYPE))]
779    pub struct SetPlayModeRequest {
780        #[xml(rename = "InstanceID", ns(""))]
781        pub instance_id: u32,
782        /// New playmode
783        #[xml(rename = "NewPlayMode", ns(""))]
784        pub new_play_mode: super::CurrentPlayMode,
785    }
786
787    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
788    #[xml(rename = "SnoozeAlarm", ns(SERVICE_TYPE))]
789    pub struct SnoozeAlarmRequest {
790        #[xml(rename = "InstanceID", ns(""))]
791        pub instance_id: u32,
792        /// Snooze time as `hh:mm:ss`, 10 minutes = 00:10:00
793        #[xml(rename = "Duration", ns(""))]
794        pub duration: String,
795    }
796
797    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
798    #[xml(rename = "StartAutoplay", ns(SERVICE_TYPE))]
799    pub struct StartAutoplayRequest {
800        #[xml(rename = "InstanceID", ns(""))]
801        pub instance_id: u32,
802        #[xml(rename = "ProgramURI", ns(""))]
803        pub program_uri: String,
804        #[xml(rename = "ProgramMetaData", ns(""))]
805        pub program_meta_data: DecodeXmlString<crate::TrackMetaData>,
806        #[xml(rename = "Volume", ns(""))]
807        pub volume: u16,
808        #[xml(rename = "IncludeLinkedZones", ns(""))]
809        pub include_linked_zones: bool,
810        #[xml(rename = "ResetVolumeAfter", ns(""))]
811        pub reset_volume_after: bool,
812    }
813
814    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
815    #[xml(rename = "Stop", ns(SERVICE_TYPE))]
816    pub struct StopRequest {
817        #[xml(rename = "InstanceID", ns(""))]
818        pub instance_id: u32,
819    }
820
821    /// A parsed event produced by the `AVTransport` service.
822    /// Use `SonosDevice::subscribe_av_transport()` to obtain an event
823    /// stream that produces these.
824    #[derive(Debug, Clone, PartialEq, Default)]
825    pub struct AVTransportEvent {
826        pub last_change: Option<DecodeXmlString<AVTransportLastChangeMap>>,
827    }
828
829    #[derive(FromXml, Debug, Clone, PartialEq)]
830    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
831    struct AVTransportPropertySet {
832        pub properties: Vec<AVTransportProperty>,
833    }
834
835    #[derive(FromXml, Debug, Clone, PartialEq)]
836    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
837    struct AVTransportProperty {
838        #[xml(rename = "LastChange", ns(""))]
839        pub last_change: Option<DecodeXmlString<AVTransportLastChangeMap>>,
840    }
841
842    impl DecodeXml for AVTransportEvent {
843        fn decode_xml(xml: &str) -> crate::Result<Self> {
844            let mut result = Self::default();
845            let set: AVTransportPropertySet = instant_xml::from_str(xml)?;
846            for prop in set.properties {
847                if let Some(v) = prop.last_change {
848                    result.last_change.replace(v);
849                }
850            }
851            Ok(result)
852        }
853    }
854
855    impl crate::SonosDevice {
856        /// Subscribe to events from the `AVTransport` service on this device
857        pub async fn subscribe_av_transport(
858            &self,
859        ) -> crate::Result<crate::upnp::EventStream<AVTransportEvent>> {
860            self.subscribe_helper(&SERVICE_TYPE).await
861        }
862    }
863
864    #[derive(Debug, Clone, PartialEq, Default)]
865    pub struct AVTransportLastChange {
866        pub av_transport_uri: Option<String>,
867        pub av_transport_uri_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
868        pub alarm_include_linked_zones: Option<bool>,
869        pub alarm_state: Option<String>,
870        pub alarm_volume: Option<u16>,
871        pub current_av_transport_uri: Option<String>,
872        pub enqueue_as_next: Option<bool>,
873        pub group_id: Option<String>,
874        pub iso8601_time: Option<String>,
875        pub instance_id: Option<u32>,
876        pub list_uri: Option<String>,
877        pub list_uri_meta_data: Option<String>,
878        pub member_id: Option<String>,
879        pub member_list: Option<String>,
880        pub num_tracks: Option<u32>,
881        pub num_tracks_change: Option<i32>,
882        pub object_id: Option<String>,
883        pub player_id: Option<String>,
884        pub queue: Option<String>,
885        pub rejoin_group: Option<bool>,
886        pub reset_volume_after: Option<bool>,
887        pub resume_playback: Option<bool>,
888        pub saved_queue_title: Option<String>,
889        pub seek_mode: Option<super::SeekMode>,
890        pub seek_target: Option<String>,
891        pub sleep_timer_state: Option<String>,
892        pub source_state: Option<String>,
893        pub stream_restart_state: Option<String>,
894        pub track_list: Option<String>,
895        pub track_number: Option<u32>,
896        pub transport_settings: Option<String>,
897        pub uri: Option<String>,
898        pub uri_meta_data: Option<String>,
899        pub vli_state: Option<String>,
900        pub absolute_counter_position: Option<i32>,
901        pub absolute_time_position: Option<String>,
902        pub alarm_id_running: Option<u32>,
903        pub alarm_logged_start_time: Option<String>,
904        pub alarm_running: Option<bool>,
905        pub current_crossfade_mode: Option<bool>,
906        pub current_media_duration: Option<String>,
907        pub current_play_mode: Option<super::CurrentPlayMode>,
908        pub current_record_quality_mode: Option<String>,
909        pub current_section: Option<u32>,
910        pub current_track: Option<u32>,
911        pub current_track_duration: Option<String>,
912        pub current_track_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
913        pub current_track_uri: Option<String>,
914        pub current_transport_actions: Option<String>,
915        pub current_valid_play_modes: Option<String>,
916        pub direct_control_account_id: Option<String>,
917        pub direct_control_client_id: Option<String>,
918        pub direct_control_is_suspended: Option<bool>,
919        pub enqueued_transport_uri: Option<String>,
920        pub enqueued_transport_uri_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
921        pub muse_sessions: Option<String>,
922        pub next_av_transport_uri: Option<String>,
923        pub next_av_transport_uri_meta_data: Option<String>,
924        pub next_track_meta_data: Option<String>,
925        pub next_track_uri: Option<String>,
926        pub number_of_tracks: Option<u32>,
927        pub playback_storage_medium: Option<super::PlaybackStorageMedium>,
928        pub possible_playback_storage_media: Option<String>,
929        pub possible_record_quality_modes: Option<String>,
930        pub possible_record_storage_media: Option<String>,
931        pub queue_update_id: Option<u32>,
932        pub record_medium_write_status: Option<String>,
933        pub record_storage_medium: Option<String>,
934        pub relative_counter_position: Option<i32>,
935        pub relative_time_position: Option<String>,
936        pub restart_pending: Option<bool>,
937        pub sleep_timer_generation: Option<u32>,
938        pub snooze_running: Option<bool>,
939        pub transport_error_description: Option<String>,
940        pub transport_error_http_code: Option<String>,
941        pub transport_error_http_headers: Option<String>,
942        pub transport_error_uri: Option<String>,
943        pub transport_play_speed: Option<String>,
944        pub transport_state: Option<super::TransportState>,
945        pub transport_status: Option<String>,
946    }
947
948    #[derive(FromXml)]
949    #[xml(rename = "AVTransportURI", ns(LAST_CHANGE_NS))]
950    #[allow(non_camel_case_types)]
951    struct AVTransportLastChangeAVTransportURI {
952        #[xml(attribute)]
953        val: Option<String>,
954    }
955
956    #[derive(FromXml)]
957    #[xml(rename = "AVTransportURIMetaData", ns(LAST_CHANGE_NS))]
958    #[allow(non_camel_case_types)]
959    struct AVTransportLastChangeAVTransportURIMetaData {
960        #[xml(attribute)]
961        val: Option<DecodeXmlString<crate::TrackMetaData>>,
962    }
963
964    #[derive(FromXml)]
965    #[xml(rename = "AlarmIncludeLinkedZones", ns(LAST_CHANGE_NS))]
966    #[allow(non_camel_case_types)]
967    struct AVTransportLastChangeAlarmIncludeLinkedZones {
968        #[xml(attribute)]
969        val: Option<bool>,
970    }
971
972    #[derive(FromXml)]
973    #[xml(rename = "AlarmState", ns(LAST_CHANGE_NS))]
974    #[allow(non_camel_case_types)]
975    struct AVTransportLastChangeAlarmState {
976        #[xml(attribute)]
977        val: Option<String>,
978    }
979
980    #[derive(FromXml)]
981    #[xml(rename = "AlarmVolume", ns(LAST_CHANGE_NS))]
982    #[allow(non_camel_case_types)]
983    struct AVTransportLastChangeAlarmVolume {
984        #[xml(attribute)]
985        val: Option<u16>,
986    }
987
988    #[derive(FromXml)]
989    #[xml(rename = "CurrentAVTransportURI", ns(LAST_CHANGE_NS))]
990    #[allow(non_camel_case_types)]
991    struct AVTransportLastChangeCurrentAVTransportURI {
992        #[xml(attribute)]
993        val: Option<String>,
994    }
995
996    #[derive(FromXml)]
997    #[xml(rename = "EnqueueAsNext", ns(LAST_CHANGE_NS))]
998    #[allow(non_camel_case_types)]
999    struct AVTransportLastChangeEnqueueAsNext {
1000        #[xml(attribute)]
1001        val: Option<bool>,
1002    }
1003
1004    #[derive(FromXml)]
1005    #[xml(rename = "GroupID", ns(LAST_CHANGE_NS))]
1006    #[allow(non_camel_case_types)]
1007    struct AVTransportLastChangeGroupID {
1008        #[xml(attribute)]
1009        val: Option<String>,
1010    }
1011
1012    #[derive(FromXml)]
1013    #[xml(rename = "ISO8601Time", ns(LAST_CHANGE_NS))]
1014    #[allow(non_camel_case_types)]
1015    struct AVTransportLastChangeISO8601Time {
1016        #[xml(attribute)]
1017        val: Option<String>,
1018    }
1019
1020    #[derive(FromXml)]
1021    #[xml(rename = "InstanceID", ns(LAST_CHANGE_NS))]
1022    #[allow(non_camel_case_types)]
1023    struct AVTransportLastChangeInstanceID {
1024        #[xml(attribute)]
1025        val: Option<u32>,
1026    }
1027
1028    #[derive(FromXml)]
1029    #[xml(rename = "LIST_URI", ns(LAST_CHANGE_NS))]
1030    #[allow(non_camel_case_types)]
1031    struct AVTransportLastChangeLIST_URI {
1032        #[xml(attribute)]
1033        val: Option<String>,
1034    }
1035
1036    #[derive(FromXml)]
1037    #[xml(rename = "LIST_URIMetaData", ns(LAST_CHANGE_NS))]
1038    #[allow(non_camel_case_types)]
1039    struct AVTransportLastChangeLIST_URIMetaData {
1040        #[xml(attribute)]
1041        val: Option<String>,
1042    }
1043
1044    #[derive(FromXml)]
1045    #[xml(rename = "MemberID", ns(LAST_CHANGE_NS))]
1046    #[allow(non_camel_case_types)]
1047    struct AVTransportLastChangeMemberID {
1048        #[xml(attribute)]
1049        val: Option<String>,
1050    }
1051
1052    #[derive(FromXml)]
1053    #[xml(rename = "MemberList", ns(LAST_CHANGE_NS))]
1054    #[allow(non_camel_case_types)]
1055    struct AVTransportLastChangeMemberList {
1056        #[xml(attribute)]
1057        val: Option<String>,
1058    }
1059
1060    #[derive(FromXml)]
1061    #[xml(rename = "NumTracks", ns(LAST_CHANGE_NS))]
1062    #[allow(non_camel_case_types)]
1063    struct AVTransportLastChangeNumTracks {
1064        #[xml(attribute)]
1065        val: Option<u32>,
1066    }
1067
1068    #[derive(FromXml)]
1069    #[xml(rename = "NumTracksChange", ns(LAST_CHANGE_NS))]
1070    #[allow(non_camel_case_types)]
1071    struct AVTransportLastChangeNumTracksChange {
1072        #[xml(attribute)]
1073        val: Option<i32>,
1074    }
1075
1076    #[derive(FromXml)]
1077    #[xml(rename = "ObjectID", ns(LAST_CHANGE_NS))]
1078    #[allow(non_camel_case_types)]
1079    struct AVTransportLastChangeObjectID {
1080        #[xml(attribute)]
1081        val: Option<String>,
1082    }
1083
1084    #[derive(FromXml)]
1085    #[xml(rename = "PlayerID", ns(LAST_CHANGE_NS))]
1086    #[allow(non_camel_case_types)]
1087    struct AVTransportLastChangePlayerID {
1088        #[xml(attribute)]
1089        val: Option<String>,
1090    }
1091
1092    #[derive(FromXml)]
1093    #[xml(rename = "Queue", ns(LAST_CHANGE_NS))]
1094    #[allow(non_camel_case_types)]
1095    struct AVTransportLastChangeQueue {
1096        #[xml(attribute)]
1097        val: Option<String>,
1098    }
1099
1100    #[derive(FromXml)]
1101    #[xml(rename = "RejoinGroup", ns(LAST_CHANGE_NS))]
1102    #[allow(non_camel_case_types)]
1103    struct AVTransportLastChangeRejoinGroup {
1104        #[xml(attribute)]
1105        val: Option<bool>,
1106    }
1107
1108    #[derive(FromXml)]
1109    #[xml(rename = "ResetVolumeAfter", ns(LAST_CHANGE_NS))]
1110    #[allow(non_camel_case_types)]
1111    struct AVTransportLastChangeResetVolumeAfter {
1112        #[xml(attribute)]
1113        val: Option<bool>,
1114    }
1115
1116    #[derive(FromXml)]
1117    #[xml(rename = "ResumePlayback", ns(LAST_CHANGE_NS))]
1118    #[allow(non_camel_case_types)]
1119    struct AVTransportLastChangeResumePlayback {
1120        #[xml(attribute)]
1121        val: Option<bool>,
1122    }
1123
1124    #[derive(FromXml)]
1125    #[xml(rename = "SavedQueueTitle", ns(LAST_CHANGE_NS))]
1126    #[allow(non_camel_case_types)]
1127    struct AVTransportLastChangeSavedQueueTitle {
1128        #[xml(attribute)]
1129        val: Option<String>,
1130    }
1131
1132    #[derive(FromXml)]
1133    #[xml(rename = "SeekMode", ns(LAST_CHANGE_NS))]
1134    #[allow(non_camel_case_types)]
1135    struct AVTransportLastChangeSeekMode {
1136        #[xml(attribute)]
1137        val: Option<super::SeekMode>,
1138    }
1139
1140    #[derive(FromXml)]
1141    #[xml(rename = "SeekTarget", ns(LAST_CHANGE_NS))]
1142    #[allow(non_camel_case_types)]
1143    struct AVTransportLastChangeSeekTarget {
1144        #[xml(attribute)]
1145        val: Option<String>,
1146    }
1147
1148    #[derive(FromXml)]
1149    #[xml(rename = "SleepTimerState", ns(LAST_CHANGE_NS))]
1150    #[allow(non_camel_case_types)]
1151    struct AVTransportLastChangeSleepTimerState {
1152        #[xml(attribute)]
1153        val: Option<String>,
1154    }
1155
1156    #[derive(FromXml)]
1157    #[xml(rename = "SourceState", ns(LAST_CHANGE_NS))]
1158    #[allow(non_camel_case_types)]
1159    struct AVTransportLastChangeSourceState {
1160        #[xml(attribute)]
1161        val: Option<String>,
1162    }
1163
1164    #[derive(FromXml)]
1165    #[xml(rename = "StreamRestartState", ns(LAST_CHANGE_NS))]
1166    #[allow(non_camel_case_types)]
1167    struct AVTransportLastChangeStreamRestartState {
1168        #[xml(attribute)]
1169        val: Option<String>,
1170    }
1171
1172    #[derive(FromXml)]
1173    #[xml(rename = "TrackList", ns(LAST_CHANGE_NS))]
1174    #[allow(non_camel_case_types)]
1175    struct AVTransportLastChangeTrackList {
1176        #[xml(attribute)]
1177        val: Option<String>,
1178    }
1179
1180    #[derive(FromXml)]
1181    #[xml(rename = "TrackNumber", ns(LAST_CHANGE_NS))]
1182    #[allow(non_camel_case_types)]
1183    struct AVTransportLastChangeTrackNumber {
1184        #[xml(attribute)]
1185        val: Option<u32>,
1186    }
1187
1188    #[derive(FromXml)]
1189    #[xml(rename = "TransportSettings", ns(LAST_CHANGE_NS))]
1190    #[allow(non_camel_case_types)]
1191    struct AVTransportLastChangeTransportSettings {
1192        #[xml(attribute)]
1193        val: Option<String>,
1194    }
1195
1196    #[derive(FromXml)]
1197    #[xml(rename = "URI", ns(LAST_CHANGE_NS))]
1198    #[allow(non_camel_case_types)]
1199    struct AVTransportLastChangeURI {
1200        #[xml(attribute)]
1201        val: Option<String>,
1202    }
1203
1204    #[derive(FromXml)]
1205    #[xml(rename = "URIMetaData", ns(LAST_CHANGE_NS))]
1206    #[allow(non_camel_case_types)]
1207    struct AVTransportLastChangeURIMetaData {
1208        #[xml(attribute)]
1209        val: Option<String>,
1210    }
1211
1212    #[derive(FromXml)]
1213    #[xml(rename = "VLIState", ns(LAST_CHANGE_NS))]
1214    #[allow(non_camel_case_types)]
1215    struct AVTransportLastChangeVLIState {
1216        #[xml(attribute)]
1217        val: Option<String>,
1218    }
1219
1220    #[derive(FromXml)]
1221    #[xml(rename = "AbsoluteCounterPosition", ns(LAST_CHANGE_NS))]
1222    #[allow(non_camel_case_types)]
1223    struct AVTransportLastChangeAbsoluteCounterPosition {
1224        #[xml(attribute)]
1225        val: Option<i32>,
1226    }
1227
1228    #[derive(FromXml)]
1229    #[xml(rename = "AbsoluteTimePosition", ns(LAST_CHANGE_NS))]
1230    #[allow(non_camel_case_types)]
1231    struct AVTransportLastChangeAbsoluteTimePosition {
1232        #[xml(attribute)]
1233        val: Option<String>,
1234    }
1235
1236    #[derive(FromXml)]
1237    #[xml(rename = "AlarmIDRunning", ns(LAST_CHANGE_NS))]
1238    #[allow(non_camel_case_types)]
1239    struct AVTransportLastChangeAlarmIDRunning {
1240        #[xml(attribute)]
1241        val: Option<u32>,
1242    }
1243
1244    #[derive(FromXml)]
1245    #[xml(rename = "AlarmLoggedStartTime", ns(LAST_CHANGE_NS))]
1246    #[allow(non_camel_case_types)]
1247    struct AVTransportLastChangeAlarmLoggedStartTime {
1248        #[xml(attribute)]
1249        val: Option<String>,
1250    }
1251
1252    #[derive(FromXml)]
1253    #[xml(
1254        rename = "AlarmRunning",
1255        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1256    )]
1257    #[allow(non_camel_case_types)]
1258    struct AVTransportLastChangeAlarmRunning {
1259        #[xml(attribute)]
1260        val: Option<bool>,
1261    }
1262
1263    #[derive(FromXml)]
1264    #[xml(rename = "CurrentCrossfadeMode", ns(LAST_CHANGE_NS))]
1265    #[allow(non_camel_case_types)]
1266    struct AVTransportLastChangeCurrentCrossfadeMode {
1267        #[xml(attribute)]
1268        val: Option<bool>,
1269    }
1270
1271    #[derive(FromXml)]
1272    #[xml(rename = "CurrentMediaDuration", ns(LAST_CHANGE_NS))]
1273    #[allow(non_camel_case_types)]
1274    struct AVTransportLastChangeCurrentMediaDuration {
1275        #[xml(attribute)]
1276        val: Option<String>,
1277    }
1278
1279    #[derive(FromXml)]
1280    #[xml(rename = "CurrentPlayMode", ns(LAST_CHANGE_NS))]
1281    #[allow(non_camel_case_types)]
1282    struct AVTransportLastChangeCurrentPlayMode {
1283        #[xml(attribute)]
1284        val: Option<super::CurrentPlayMode>,
1285    }
1286
1287    #[derive(FromXml)]
1288    #[xml(rename = "CurrentRecordQualityMode", ns(LAST_CHANGE_NS))]
1289    #[allow(non_camel_case_types)]
1290    struct AVTransportLastChangeCurrentRecordQualityMode {
1291        #[xml(attribute)]
1292        val: Option<String>,
1293    }
1294
1295    #[derive(FromXml)]
1296    #[xml(rename = "CurrentSection", ns(LAST_CHANGE_NS))]
1297    #[allow(non_camel_case_types)]
1298    struct AVTransportLastChangeCurrentSection {
1299        #[xml(attribute)]
1300        val: Option<u32>,
1301    }
1302
1303    #[derive(FromXml)]
1304    #[xml(rename = "CurrentTrack", ns(LAST_CHANGE_NS))]
1305    #[allow(non_camel_case_types)]
1306    struct AVTransportLastChangeCurrentTrack {
1307        #[xml(attribute)]
1308        val: Option<u32>,
1309    }
1310
1311    #[derive(FromXml)]
1312    #[xml(rename = "CurrentTrackDuration", ns(LAST_CHANGE_NS))]
1313    #[allow(non_camel_case_types)]
1314    struct AVTransportLastChangeCurrentTrackDuration {
1315        #[xml(attribute)]
1316        val: Option<String>,
1317    }
1318
1319    #[derive(FromXml)]
1320    #[xml(rename = "CurrentTrackMetaData", ns(LAST_CHANGE_NS))]
1321    #[allow(non_camel_case_types)]
1322    struct AVTransportLastChangeCurrentTrackMetaData {
1323        #[xml(attribute)]
1324        val: Option<DecodeXmlString<crate::TrackMetaData>>,
1325    }
1326
1327    #[derive(FromXml)]
1328    #[xml(rename = "CurrentTrackURI", ns(LAST_CHANGE_NS))]
1329    #[allow(non_camel_case_types)]
1330    struct AVTransportLastChangeCurrentTrackURI {
1331        #[xml(attribute)]
1332        val: Option<String>,
1333    }
1334
1335    #[derive(FromXml)]
1336    #[xml(rename = "CurrentTransportActions", ns(LAST_CHANGE_NS))]
1337    #[allow(non_camel_case_types)]
1338    struct AVTransportLastChangeCurrentTransportActions {
1339        #[xml(attribute)]
1340        val: Option<String>,
1341    }
1342
1343    #[derive(FromXml)]
1344    #[xml(
1345        rename = "CurrentValidPlayModes",
1346        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1347    )]
1348    #[allow(non_camel_case_types)]
1349    struct AVTransportLastChangeCurrentValidPlayModes {
1350        #[xml(attribute)]
1351        val: Option<String>,
1352    }
1353
1354    #[derive(FromXml)]
1355    #[xml(
1356        rename = "DirectControlAccountID",
1357        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1358    )]
1359    #[allow(non_camel_case_types)]
1360    struct AVTransportLastChangeDirectControlAccountID {
1361        #[xml(attribute)]
1362        val: Option<String>,
1363    }
1364
1365    #[derive(FromXml)]
1366    #[xml(
1367        rename = "DirectControlClientID",
1368        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1369    )]
1370    #[allow(non_camel_case_types)]
1371    struct AVTransportLastChangeDirectControlClientID {
1372        #[xml(attribute)]
1373        val: Option<String>,
1374    }
1375
1376    #[derive(FromXml)]
1377    #[xml(
1378        rename = "DirectControlIsSuspended",
1379        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1380    )]
1381    #[allow(non_camel_case_types)]
1382    struct AVTransportLastChangeDirectControlIsSuspended {
1383        #[xml(attribute)]
1384        val: Option<bool>,
1385    }
1386
1387    #[derive(FromXml)]
1388    #[xml(
1389        rename = "EnqueuedTransportURI",
1390        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1391    )]
1392    #[allow(non_camel_case_types)]
1393    struct AVTransportLastChangeEnqueuedTransportURI {
1394        #[xml(attribute)]
1395        val: Option<String>,
1396    }
1397
1398    #[derive(FromXml)]
1399    #[xml(
1400        rename = "EnqueuedTransportURIMetaData",
1401        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1402    )]
1403    #[allow(non_camel_case_types)]
1404    struct AVTransportLastChangeEnqueuedTransportURIMetaData {
1405        #[xml(attribute)]
1406        val: Option<DecodeXmlString<crate::TrackMetaData>>,
1407    }
1408
1409    #[derive(FromXml)]
1410    #[xml(rename = "MuseSessions", ns(LAST_CHANGE_NS))]
1411    #[allow(non_camel_case_types)]
1412    struct AVTransportLastChangeMuseSessions {
1413        #[xml(attribute)]
1414        val: Option<String>,
1415    }
1416
1417    #[derive(FromXml)]
1418    #[xml(rename = "NextAVTransportURI", ns(LAST_CHANGE_NS))]
1419    #[allow(non_camel_case_types)]
1420    struct AVTransportLastChangeNextAVTransportURI {
1421        #[xml(attribute)]
1422        val: Option<String>,
1423    }
1424
1425    #[derive(FromXml)]
1426    #[xml(rename = "NextAVTransportURIMetaData", ns(LAST_CHANGE_NS))]
1427    #[allow(non_camel_case_types)]
1428    struct AVTransportLastChangeNextAVTransportURIMetaData {
1429        #[xml(attribute)]
1430        val: Option<String>,
1431    }
1432
1433    #[derive(FromXml)]
1434    #[xml(
1435        rename = "NextTrackMetaData",
1436        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1437    )]
1438    #[allow(non_camel_case_types)]
1439    struct AVTransportLastChangeNextTrackMetaData {
1440        #[xml(attribute)]
1441        val: Option<String>,
1442    }
1443
1444    #[derive(FromXml)]
1445    #[xml(
1446        rename = "NextTrackURI",
1447        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1448    )]
1449    #[allow(non_camel_case_types)]
1450    struct AVTransportLastChangeNextTrackURI {
1451        #[xml(attribute)]
1452        val: Option<String>,
1453    }
1454
1455    #[derive(FromXml)]
1456    #[xml(rename = "NumberOfTracks", ns(LAST_CHANGE_NS))]
1457    #[allow(non_camel_case_types)]
1458    struct AVTransportLastChangeNumberOfTracks {
1459        #[xml(attribute)]
1460        val: Option<u32>,
1461    }
1462
1463    #[derive(FromXml)]
1464    #[xml(rename = "PlaybackStorageMedium", ns(LAST_CHANGE_NS))]
1465    #[allow(non_camel_case_types)]
1466    struct AVTransportLastChangePlaybackStorageMedium {
1467        #[xml(attribute)]
1468        val: Option<super::PlaybackStorageMedium>,
1469    }
1470
1471    #[derive(FromXml)]
1472    #[xml(rename = "PossiblePlaybackStorageMedia", ns(LAST_CHANGE_NS))]
1473    #[allow(non_camel_case_types)]
1474    struct AVTransportLastChangePossiblePlaybackStorageMedia {
1475        #[xml(attribute)]
1476        val: Option<String>,
1477    }
1478
1479    #[derive(FromXml)]
1480    #[xml(rename = "PossibleRecordQualityModes", ns(LAST_CHANGE_NS))]
1481    #[allow(non_camel_case_types)]
1482    struct AVTransportLastChangePossibleRecordQualityModes {
1483        #[xml(attribute)]
1484        val: Option<String>,
1485    }
1486
1487    #[derive(FromXml)]
1488    #[xml(rename = "PossibleRecordStorageMedia", ns(LAST_CHANGE_NS))]
1489    #[allow(non_camel_case_types)]
1490    struct AVTransportLastChangePossibleRecordStorageMedia {
1491        #[xml(attribute)]
1492        val: Option<String>,
1493    }
1494
1495    #[derive(FromXml)]
1496    #[xml(rename = "QueueUpdateID", ns(LAST_CHANGE_NS))]
1497    #[allow(non_camel_case_types)]
1498    struct AVTransportLastChangeQueueUpdateID {
1499        #[xml(attribute)]
1500        val: Option<u32>,
1501    }
1502
1503    #[derive(FromXml)]
1504    #[xml(rename = "RecordMediumWriteStatus", ns(LAST_CHANGE_NS))]
1505    #[allow(non_camel_case_types)]
1506    struct AVTransportLastChangeRecordMediumWriteStatus {
1507        #[xml(attribute)]
1508        val: Option<String>,
1509    }
1510
1511    #[derive(FromXml)]
1512    #[xml(rename = "RecordStorageMedium", ns(LAST_CHANGE_NS))]
1513    #[allow(non_camel_case_types)]
1514    struct AVTransportLastChangeRecordStorageMedium {
1515        #[xml(attribute)]
1516        val: Option<String>,
1517    }
1518
1519    #[derive(FromXml)]
1520    #[xml(rename = "RelativeCounterPosition", ns(LAST_CHANGE_NS))]
1521    #[allow(non_camel_case_types)]
1522    struct AVTransportLastChangeRelativeCounterPosition {
1523        #[xml(attribute)]
1524        val: Option<i32>,
1525    }
1526
1527    #[derive(FromXml)]
1528    #[xml(rename = "RelativeTimePosition", ns(LAST_CHANGE_NS))]
1529    #[allow(non_camel_case_types)]
1530    struct AVTransportLastChangeRelativeTimePosition {
1531        #[xml(attribute)]
1532        val: Option<String>,
1533    }
1534
1535    #[derive(FromXml)]
1536    #[xml(
1537        rename = "RestartPending",
1538        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1539    )]
1540    #[allow(non_camel_case_types)]
1541    struct AVTransportLastChangeRestartPending {
1542        #[xml(attribute)]
1543        val: Option<bool>,
1544    }
1545
1546    #[derive(FromXml)]
1547    #[xml(
1548        rename = "SleepTimerGeneration",
1549        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1550    )]
1551    #[allow(non_camel_case_types)]
1552    struct AVTransportLastChangeSleepTimerGeneration {
1553        #[xml(attribute)]
1554        val: Option<u32>,
1555    }
1556
1557    #[derive(FromXml)]
1558    #[xml(
1559        rename = "SnoozeRunning",
1560        ns("urn:schemas-rinconnetworks-com:metadata-1-0/")
1561    )]
1562    #[allow(non_camel_case_types)]
1563    struct AVTransportLastChangeSnoozeRunning {
1564        #[xml(attribute)]
1565        val: Option<bool>,
1566    }
1567
1568    #[derive(FromXml)]
1569    #[xml(rename = "TransportErrorDescription", ns(LAST_CHANGE_NS))]
1570    #[allow(non_camel_case_types)]
1571    struct AVTransportLastChangeTransportErrorDescription {
1572        #[xml(attribute)]
1573        val: Option<String>,
1574    }
1575
1576    #[derive(FromXml)]
1577    #[xml(rename = "TransportErrorHttpCode", ns(LAST_CHANGE_NS))]
1578    #[allow(non_camel_case_types)]
1579    struct AVTransportLastChangeTransportErrorHttpCode {
1580        #[xml(attribute)]
1581        val: Option<String>,
1582    }
1583
1584    #[derive(FromXml)]
1585    #[xml(rename = "TransportErrorHttpHeaders", ns(LAST_CHANGE_NS))]
1586    #[allow(non_camel_case_types)]
1587    struct AVTransportLastChangeTransportErrorHttpHeaders {
1588        #[xml(attribute)]
1589        val: Option<String>,
1590    }
1591
1592    #[derive(FromXml)]
1593    #[xml(rename = "TransportErrorURI", ns(LAST_CHANGE_NS))]
1594    #[allow(non_camel_case_types)]
1595    struct AVTransportLastChangeTransportErrorURI {
1596        #[xml(attribute)]
1597        val: Option<String>,
1598    }
1599
1600    #[derive(FromXml)]
1601    #[xml(rename = "TransportPlaySpeed", ns(LAST_CHANGE_NS))]
1602    #[allow(non_camel_case_types)]
1603    struct AVTransportLastChangeTransportPlaySpeed {
1604        #[xml(attribute)]
1605        val: Option<String>,
1606    }
1607
1608    #[derive(FromXml)]
1609    #[xml(rename = "TransportState", ns(LAST_CHANGE_NS))]
1610    #[allow(non_camel_case_types)]
1611    struct AVTransportLastChangeTransportState {
1612        #[xml(attribute)]
1613        val: Option<super::TransportState>,
1614    }
1615
1616    #[derive(FromXml)]
1617    #[xml(rename = "TransportStatus", ns(LAST_CHANGE_NS))]
1618    #[allow(non_camel_case_types)]
1619    struct AVTransportLastChangeTransportStatus {
1620        #[xml(attribute)]
1621        val: Option<String>,
1622    }
1623
1624    const LAST_CHANGE_NS: &str = "urn:schemas-upnp-org:metadata-1-0/AVT/";
1625
1626    #[derive(FromXml)]
1627    #[xml(rename = "InstanceID", ns(LAST_CHANGE_NS))]
1628    struct AVTransportLastChangeRootObject {
1629        #[xml(rename = "val", attribute)]
1630        object_instance_id_: u32,
1631
1632        av_transport_uri: Option<AVTransportLastChangeAVTransportURI>,
1633        av_transport_uri_meta_data: Option<AVTransportLastChangeAVTransportURIMetaData>,
1634        alarm_include_linked_zones: Option<AVTransportLastChangeAlarmIncludeLinkedZones>,
1635        alarm_state: Option<AVTransportLastChangeAlarmState>,
1636        alarm_volume: Option<AVTransportLastChangeAlarmVolume>,
1637        current_av_transport_uri: Option<AVTransportLastChangeCurrentAVTransportURI>,
1638        enqueue_as_next: Option<AVTransportLastChangeEnqueueAsNext>,
1639        group_id: Option<AVTransportLastChangeGroupID>,
1640        iso8601_time: Option<AVTransportLastChangeISO8601Time>,
1641        instance_id: Option<AVTransportLastChangeInstanceID>,
1642        list_uri: Option<AVTransportLastChangeLIST_URI>,
1643        list_uri_meta_data: Option<AVTransportLastChangeLIST_URIMetaData>,
1644        member_id: Option<AVTransportLastChangeMemberID>,
1645        member_list: Option<AVTransportLastChangeMemberList>,
1646        num_tracks: Option<AVTransportLastChangeNumTracks>,
1647        num_tracks_change: Option<AVTransportLastChangeNumTracksChange>,
1648        object_id: Option<AVTransportLastChangeObjectID>,
1649        player_id: Option<AVTransportLastChangePlayerID>,
1650        queue: Option<AVTransportLastChangeQueue>,
1651        rejoin_group: Option<AVTransportLastChangeRejoinGroup>,
1652        reset_volume_after: Option<AVTransportLastChangeResetVolumeAfter>,
1653        resume_playback: Option<AVTransportLastChangeResumePlayback>,
1654        saved_queue_title: Option<AVTransportLastChangeSavedQueueTitle>,
1655        seek_mode: Option<AVTransportLastChangeSeekMode>,
1656        seek_target: Option<AVTransportLastChangeSeekTarget>,
1657        sleep_timer_state: Option<AVTransportLastChangeSleepTimerState>,
1658        source_state: Option<AVTransportLastChangeSourceState>,
1659        stream_restart_state: Option<AVTransportLastChangeStreamRestartState>,
1660        track_list: Option<AVTransportLastChangeTrackList>,
1661        track_number: Option<AVTransportLastChangeTrackNumber>,
1662        transport_settings: Option<AVTransportLastChangeTransportSettings>,
1663        uri: Option<AVTransportLastChangeURI>,
1664        uri_meta_data: Option<AVTransportLastChangeURIMetaData>,
1665        vli_state: Option<AVTransportLastChangeVLIState>,
1666        absolute_counter_position: Option<AVTransportLastChangeAbsoluteCounterPosition>,
1667        absolute_time_position: Option<AVTransportLastChangeAbsoluteTimePosition>,
1668        alarm_id_running: Option<AVTransportLastChangeAlarmIDRunning>,
1669        alarm_logged_start_time: Option<AVTransportLastChangeAlarmLoggedStartTime>,
1670        alarm_running: Option<AVTransportLastChangeAlarmRunning>,
1671        current_crossfade_mode: Option<AVTransportLastChangeCurrentCrossfadeMode>,
1672        current_media_duration: Option<AVTransportLastChangeCurrentMediaDuration>,
1673        current_play_mode: Option<AVTransportLastChangeCurrentPlayMode>,
1674        current_record_quality_mode: Option<AVTransportLastChangeCurrentRecordQualityMode>,
1675        current_section: Option<AVTransportLastChangeCurrentSection>,
1676        current_track: Option<AVTransportLastChangeCurrentTrack>,
1677        current_track_duration: Option<AVTransportLastChangeCurrentTrackDuration>,
1678        current_track_meta_data: Option<AVTransportLastChangeCurrentTrackMetaData>,
1679        current_track_uri: Option<AVTransportLastChangeCurrentTrackURI>,
1680        current_transport_actions: Option<AVTransportLastChangeCurrentTransportActions>,
1681        current_valid_play_modes: Option<AVTransportLastChangeCurrentValidPlayModes>,
1682        direct_control_account_id: Option<AVTransportLastChangeDirectControlAccountID>,
1683        direct_control_client_id: Option<AVTransportLastChangeDirectControlClientID>,
1684        direct_control_is_suspended: Option<AVTransportLastChangeDirectControlIsSuspended>,
1685        enqueued_transport_uri: Option<AVTransportLastChangeEnqueuedTransportURI>,
1686        enqueued_transport_uri_meta_data: Option<AVTransportLastChangeEnqueuedTransportURIMetaData>,
1687        muse_sessions: Option<AVTransportLastChangeMuseSessions>,
1688        next_av_transport_uri: Option<AVTransportLastChangeNextAVTransportURI>,
1689        next_av_transport_uri_meta_data: Option<AVTransportLastChangeNextAVTransportURIMetaData>,
1690        next_track_meta_data: Option<AVTransportLastChangeNextTrackMetaData>,
1691        next_track_uri: Option<AVTransportLastChangeNextTrackURI>,
1692        number_of_tracks: Option<AVTransportLastChangeNumberOfTracks>,
1693        playback_storage_medium: Option<AVTransportLastChangePlaybackStorageMedium>,
1694        possible_playback_storage_media: Option<AVTransportLastChangePossiblePlaybackStorageMedia>,
1695        possible_record_quality_modes: Option<AVTransportLastChangePossibleRecordQualityModes>,
1696        possible_record_storage_media: Option<AVTransportLastChangePossibleRecordStorageMedia>,
1697        queue_update_id: Option<AVTransportLastChangeQueueUpdateID>,
1698        record_medium_write_status: Option<AVTransportLastChangeRecordMediumWriteStatus>,
1699        record_storage_medium: Option<AVTransportLastChangeRecordStorageMedium>,
1700        relative_counter_position: Option<AVTransportLastChangeRelativeCounterPosition>,
1701        relative_time_position: Option<AVTransportLastChangeRelativeTimePosition>,
1702        restart_pending: Option<AVTransportLastChangeRestartPending>,
1703        sleep_timer_generation: Option<AVTransportLastChangeSleepTimerGeneration>,
1704        snooze_running: Option<AVTransportLastChangeSnoozeRunning>,
1705        transport_error_description: Option<AVTransportLastChangeTransportErrorDescription>,
1706        transport_error_http_code: Option<AVTransportLastChangeTransportErrorHttpCode>,
1707        transport_error_http_headers: Option<AVTransportLastChangeTransportErrorHttpHeaders>,
1708        transport_error_uri: Option<AVTransportLastChangeTransportErrorURI>,
1709        transport_play_speed: Option<AVTransportLastChangeTransportPlaySpeed>,
1710        transport_state: Option<AVTransportLastChangeTransportState>,
1711        transport_status: Option<AVTransportLastChangeTransportStatus>,
1712    }
1713
1714    #[derive(Debug, Clone, PartialEq, Default)]
1715    pub struct AVTransportLastChangeMap {
1716        pub map: std::collections::BTreeMap<u32, AVTransportLastChange>,
1717    }
1718
1719    impl DecodeXml for AVTransportLastChangeMap {
1720        fn decode_xml(xml: &str) -> crate::Result<Self> {
1721            #[derive(FromXml)]
1722            #[xml(ns(LAST_CHANGE_NS, r = "urn:schemas-rinconnetworks-com:metadata-1-0/"))]
1723            struct Event {
1724                instance: Vec<AVTransportLastChangeRootObject>,
1725            }
1726
1727            let last_change: Event = instant_xml::from_str(xml)?;
1728            let mut map = std::collections::BTreeMap::new();
1729
1730            for item in last_change.instance {
1731                let mut result = AVTransportLastChange::default();
1732
1733                result.av_transport_uri = item.av_transport_uri.and_then(|v| v.val);
1734
1735                result.av_transport_uri_meta_data =
1736                    item.av_transport_uri_meta_data.and_then(|v| v.val);
1737
1738                result.alarm_include_linked_zones =
1739                    item.alarm_include_linked_zones.and_then(|v| v.val);
1740
1741                result.alarm_state = item.alarm_state.and_then(|v| v.val);
1742
1743                result.alarm_volume = item.alarm_volume.and_then(|v| v.val);
1744
1745                result.current_av_transport_uri = item.current_av_transport_uri.and_then(|v| v.val);
1746
1747                result.enqueue_as_next = item.enqueue_as_next.and_then(|v| v.val);
1748
1749                result.group_id = item.group_id.and_then(|v| v.val);
1750
1751                result.iso8601_time = item.iso8601_time.and_then(|v| v.val);
1752
1753                result.instance_id = item.instance_id.and_then(|v| v.val);
1754
1755                result.list_uri = item.list_uri.and_then(|v| v.val);
1756
1757                result.list_uri_meta_data = item.list_uri_meta_data.and_then(|v| v.val);
1758
1759                result.member_id = item.member_id.and_then(|v| v.val);
1760
1761                result.member_list = item.member_list.and_then(|v| v.val);
1762
1763                result.num_tracks = item.num_tracks.and_then(|v| v.val);
1764
1765                result.num_tracks_change = item.num_tracks_change.and_then(|v| v.val);
1766
1767                result.object_id = item.object_id.and_then(|v| v.val);
1768
1769                result.player_id = item.player_id.and_then(|v| v.val);
1770
1771                result.queue = item.queue.and_then(|v| v.val);
1772
1773                result.rejoin_group = item.rejoin_group.and_then(|v| v.val);
1774
1775                result.reset_volume_after = item.reset_volume_after.and_then(|v| v.val);
1776
1777                result.resume_playback = item.resume_playback.and_then(|v| v.val);
1778
1779                result.saved_queue_title = item.saved_queue_title.and_then(|v| v.val);
1780
1781                result.seek_mode = item.seek_mode.and_then(|v| v.val);
1782
1783                result.seek_target = item.seek_target.and_then(|v| v.val);
1784
1785                result.sleep_timer_state = item.sleep_timer_state.and_then(|v| v.val);
1786
1787                result.source_state = item.source_state.and_then(|v| v.val);
1788
1789                result.stream_restart_state = item.stream_restart_state.and_then(|v| v.val);
1790
1791                result.track_list = item.track_list.and_then(|v| v.val);
1792
1793                result.track_number = item.track_number.and_then(|v| v.val);
1794
1795                result.transport_settings = item.transport_settings.and_then(|v| v.val);
1796
1797                result.uri = item.uri.and_then(|v| v.val);
1798
1799                result.uri_meta_data = item.uri_meta_data.and_then(|v| v.val);
1800
1801                result.vli_state = item.vli_state.and_then(|v| v.val);
1802
1803                result.absolute_counter_position =
1804                    item.absolute_counter_position.and_then(|v| v.val);
1805
1806                result.absolute_time_position = item.absolute_time_position.and_then(|v| v.val);
1807
1808                result.alarm_id_running = item.alarm_id_running.and_then(|v| v.val);
1809
1810                result.alarm_logged_start_time = item.alarm_logged_start_time.and_then(|v| v.val);
1811
1812                result.alarm_running = item.alarm_running.and_then(|v| v.val);
1813
1814                result.current_crossfade_mode = item.current_crossfade_mode.and_then(|v| v.val);
1815
1816                result.current_media_duration = item.current_media_duration.and_then(|v| v.val);
1817
1818                result.current_play_mode = item.current_play_mode.and_then(|v| v.val);
1819
1820                result.current_record_quality_mode =
1821                    item.current_record_quality_mode.and_then(|v| v.val);
1822
1823                result.current_section = item.current_section.and_then(|v| v.val);
1824
1825                result.current_track = item.current_track.and_then(|v| v.val);
1826
1827                result.current_track_duration = item.current_track_duration.and_then(|v| v.val);
1828
1829                result.current_track_meta_data = item.current_track_meta_data.and_then(|v| v.val);
1830
1831                result.current_track_uri = item.current_track_uri.and_then(|v| v.val);
1832
1833                result.current_transport_actions =
1834                    item.current_transport_actions.and_then(|v| v.val);
1835
1836                result.current_valid_play_modes = item.current_valid_play_modes.and_then(|v| v.val);
1837
1838                result.direct_control_account_id =
1839                    item.direct_control_account_id.and_then(|v| v.val);
1840
1841                result.direct_control_client_id = item.direct_control_client_id.and_then(|v| v.val);
1842
1843                result.direct_control_is_suspended =
1844                    item.direct_control_is_suspended.and_then(|v| v.val);
1845
1846                result.enqueued_transport_uri = item.enqueued_transport_uri.and_then(|v| v.val);
1847
1848                result.enqueued_transport_uri_meta_data =
1849                    item.enqueued_transport_uri_meta_data.and_then(|v| v.val);
1850
1851                result.muse_sessions = item.muse_sessions.and_then(|v| v.val);
1852
1853                result.next_av_transport_uri = item.next_av_transport_uri.and_then(|v| v.val);
1854
1855                result.next_av_transport_uri_meta_data =
1856                    item.next_av_transport_uri_meta_data.and_then(|v| v.val);
1857
1858                result.next_track_meta_data = item.next_track_meta_data.and_then(|v| v.val);
1859
1860                result.next_track_uri = item.next_track_uri.and_then(|v| v.val);
1861
1862                result.number_of_tracks = item.number_of_tracks.and_then(|v| v.val);
1863
1864                result.playback_storage_medium = item.playback_storage_medium.and_then(|v| v.val);
1865
1866                result.possible_playback_storage_media =
1867                    item.possible_playback_storage_media.and_then(|v| v.val);
1868
1869                result.possible_record_quality_modes =
1870                    item.possible_record_quality_modes.and_then(|v| v.val);
1871
1872                result.possible_record_storage_media =
1873                    item.possible_record_storage_media.and_then(|v| v.val);
1874
1875                result.queue_update_id = item.queue_update_id.and_then(|v| v.val);
1876
1877                result.record_medium_write_status =
1878                    item.record_medium_write_status.and_then(|v| v.val);
1879
1880                result.record_storage_medium = item.record_storage_medium.and_then(|v| v.val);
1881
1882                result.relative_counter_position =
1883                    item.relative_counter_position.and_then(|v| v.val);
1884
1885                result.relative_time_position = item.relative_time_position.and_then(|v| v.val);
1886
1887                result.restart_pending = item.restart_pending.and_then(|v| v.val);
1888
1889                result.sleep_timer_generation = item.sleep_timer_generation.and_then(|v| v.val);
1890
1891                result.snooze_running = item.snooze_running.and_then(|v| v.val);
1892
1893                result.transport_error_description =
1894                    item.transport_error_description.and_then(|v| v.val);
1895
1896                result.transport_error_http_code =
1897                    item.transport_error_http_code.and_then(|v| v.val);
1898
1899                result.transport_error_http_headers =
1900                    item.transport_error_http_headers.and_then(|v| v.val);
1901
1902                result.transport_error_uri = item.transport_error_uri.and_then(|v| v.val);
1903
1904                result.transport_play_speed = item.transport_play_speed.and_then(|v| v.val);
1905
1906                result.transport_state = item.transport_state.and_then(|v| v.val);
1907
1908                result.transport_status = item.transport_status.and_then(|v| v.val);
1909
1910                map.insert(item.object_instance_id_, result);
1911            }
1912
1913            Ok(AVTransportLastChangeMap { map })
1914        }
1915    }
1916}
1917
1918#[derive(PartialEq, Debug, Clone, Eq, Default)]
1919pub enum SeekMode {
1920    #[default]
1921    TrackNr,
1922    RelTime,
1923    TimeDelta,
1924
1925    /// Allows passing a value that was not known at the
1926    /// time that this crate was generated from the available
1927    /// device descriptions
1928    Unspecified(String),
1929}
1930
1931impl ToString for SeekMode {
1932    fn to_string(&self) -> String {
1933        match self {
1934            SeekMode::TrackNr => "TRACK_NR".to_string(),
1935            SeekMode::RelTime => "REL_TIME".to_string(),
1936            SeekMode::TimeDelta => "TIME_DELTA".to_string(),
1937            SeekMode::Unspecified(s) => s.to_string(),
1938        }
1939    }
1940}
1941
1942impl FromStr for SeekMode {
1943    type Err = crate::Error;
1944    fn from_str(s: &str) -> Result<SeekMode> {
1945        match s {
1946            "TRACK_NR" => Ok(SeekMode::TrackNr),
1947            "REL_TIME" => Ok(SeekMode::RelTime),
1948            "TIME_DELTA" => Ok(SeekMode::TimeDelta),
1949            s => Ok(SeekMode::Unspecified(s.to_string())),
1950        }
1951    }
1952}
1953
1954impl instant_xml::ToXml for SeekMode {
1955    fn serialize<W: std::fmt::Write + ?Sized>(
1956        &self,
1957        field: Option<instant_xml::Id<'_>>,
1958        serializer: &mut instant_xml::Serializer<W>,
1959    ) -> std::result::Result<(), instant_xml::Error> {
1960        self.to_string().serialize(field, serializer)
1961    }
1962
1963    fn present(&self) -> bool {
1964        true
1965    }
1966}
1967
1968impl<'xml> instant_xml::FromXml<'xml> for SeekMode {
1969    #[inline]
1970    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
1971        match field {
1972            Some(field) => id == field,
1973            None => false,
1974        }
1975    }
1976
1977    fn deserialize<'cx>(
1978        into: &mut Self::Accumulator,
1979        field: &'static str,
1980        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
1981    ) -> std::result::Result<(), instant_xml::Error> {
1982        if into.is_some() {
1983            return Err(instant_xml::Error::DuplicateValue(field));
1984        }
1985
1986        match deserializer.take_str()? {
1987            Some(value) => {
1988                let parsed: SeekMode = value.parse().map_err(|err| {
1989                    instant_xml::Error::Other(format!(
1990                        "invalid value for field {field}: {value}: {err:#}"
1991                    ))
1992                })?;
1993                *into = Some(parsed);
1994                Ok(())
1995            }
1996            None => Err(instant_xml::Error::MissingValue(field)),
1997        }
1998    }
1999
2000    type Accumulator = Option<SeekMode>;
2001    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2002}
2003
2004#[derive(PartialEq, Debug, Clone, Eq, Default)]
2005pub enum CurrentPlayMode {
2006    #[default]
2007    Normal,
2008    RepeatAll,
2009    RepeatOne,
2010    ShuffleNorepeat,
2011    Shuffle,
2012    ShuffleRepeatOne,
2013
2014    /// Allows passing a value that was not known at the
2015    /// time that this crate was generated from the available
2016    /// device descriptions
2017    Unspecified(String),
2018}
2019
2020impl ToString for CurrentPlayMode {
2021    fn to_string(&self) -> String {
2022        match self {
2023            CurrentPlayMode::Normal => "NORMAL".to_string(),
2024            CurrentPlayMode::RepeatAll => "REPEAT_ALL".to_string(),
2025            CurrentPlayMode::RepeatOne => "REPEAT_ONE".to_string(),
2026            CurrentPlayMode::ShuffleNorepeat => "SHUFFLE_NOREPEAT".to_string(),
2027            CurrentPlayMode::Shuffle => "SHUFFLE".to_string(),
2028            CurrentPlayMode::ShuffleRepeatOne => "SHUFFLE_REPEAT_ONE".to_string(),
2029            CurrentPlayMode::Unspecified(s) => s.to_string(),
2030        }
2031    }
2032}
2033
2034impl FromStr for CurrentPlayMode {
2035    type Err = crate::Error;
2036    fn from_str(s: &str) -> Result<CurrentPlayMode> {
2037        match s {
2038            "NORMAL" => Ok(CurrentPlayMode::Normal),
2039            "REPEAT_ALL" => Ok(CurrentPlayMode::RepeatAll),
2040            "REPEAT_ONE" => Ok(CurrentPlayMode::RepeatOne),
2041            "SHUFFLE_NOREPEAT" => Ok(CurrentPlayMode::ShuffleNorepeat),
2042            "SHUFFLE" => Ok(CurrentPlayMode::Shuffle),
2043            "SHUFFLE_REPEAT_ONE" => Ok(CurrentPlayMode::ShuffleRepeatOne),
2044            s => Ok(CurrentPlayMode::Unspecified(s.to_string())),
2045        }
2046    }
2047}
2048
2049impl instant_xml::ToXml for CurrentPlayMode {
2050    fn serialize<W: std::fmt::Write + ?Sized>(
2051        &self,
2052        field: Option<instant_xml::Id<'_>>,
2053        serializer: &mut instant_xml::Serializer<W>,
2054    ) -> std::result::Result<(), instant_xml::Error> {
2055        self.to_string().serialize(field, serializer)
2056    }
2057
2058    fn present(&self) -> bool {
2059        true
2060    }
2061}
2062
2063impl<'xml> instant_xml::FromXml<'xml> for CurrentPlayMode {
2064    #[inline]
2065    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
2066        match field {
2067            Some(field) => id == field,
2068            None => false,
2069        }
2070    }
2071
2072    fn deserialize<'cx>(
2073        into: &mut Self::Accumulator,
2074        field: &'static str,
2075        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
2076    ) -> std::result::Result<(), instant_xml::Error> {
2077        if into.is_some() {
2078            return Err(instant_xml::Error::DuplicateValue(field));
2079        }
2080
2081        match deserializer.take_str()? {
2082            Some(value) => {
2083                let parsed: CurrentPlayMode = value.parse().map_err(|err| {
2084                    instant_xml::Error::Other(format!(
2085                        "invalid value for field {field}: {value}: {err:#}"
2086                    ))
2087                })?;
2088                *into = Some(parsed);
2089                Ok(())
2090            }
2091            None => Err(instant_xml::Error::MissingValue(field)),
2092        }
2093    }
2094
2095    type Accumulator = Option<CurrentPlayMode>;
2096    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2097}
2098
2099#[derive(PartialEq, Debug, Clone, Eq, Default)]
2100pub enum PlaybackStorageMedium {
2101    #[default]
2102    None,
2103    Network,
2104
2105    /// Allows passing a value that was not known at the
2106    /// time that this crate was generated from the available
2107    /// device descriptions
2108    Unspecified(String),
2109}
2110
2111impl ToString for PlaybackStorageMedium {
2112    fn to_string(&self) -> String {
2113        match self {
2114            PlaybackStorageMedium::None => "NONE".to_string(),
2115            PlaybackStorageMedium::Network => "NETWORK".to_string(),
2116            PlaybackStorageMedium::Unspecified(s) => s.to_string(),
2117        }
2118    }
2119}
2120
2121impl FromStr for PlaybackStorageMedium {
2122    type Err = crate::Error;
2123    fn from_str(s: &str) -> Result<PlaybackStorageMedium> {
2124        match s {
2125            "NONE" => Ok(PlaybackStorageMedium::None),
2126            "NETWORK" => Ok(PlaybackStorageMedium::Network),
2127            s => Ok(PlaybackStorageMedium::Unspecified(s.to_string())),
2128        }
2129    }
2130}
2131
2132impl instant_xml::ToXml for PlaybackStorageMedium {
2133    fn serialize<W: std::fmt::Write + ?Sized>(
2134        &self,
2135        field: Option<instant_xml::Id<'_>>,
2136        serializer: &mut instant_xml::Serializer<W>,
2137    ) -> std::result::Result<(), instant_xml::Error> {
2138        self.to_string().serialize(field, serializer)
2139    }
2140
2141    fn present(&self) -> bool {
2142        true
2143    }
2144}
2145
2146impl<'xml> instant_xml::FromXml<'xml> for PlaybackStorageMedium {
2147    #[inline]
2148    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
2149        match field {
2150            Some(field) => id == field,
2151            None => false,
2152        }
2153    }
2154
2155    fn deserialize<'cx>(
2156        into: &mut Self::Accumulator,
2157        field: &'static str,
2158        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
2159    ) -> std::result::Result<(), instant_xml::Error> {
2160        if into.is_some() {
2161            return Err(instant_xml::Error::DuplicateValue(field));
2162        }
2163
2164        match deserializer.take_str()? {
2165            Some(value) => {
2166                let parsed: PlaybackStorageMedium = value.parse().map_err(|err| {
2167                    instant_xml::Error::Other(format!(
2168                        "invalid value for field {field}: {value}: {err:#}"
2169                    ))
2170                })?;
2171                *into = Some(parsed);
2172                Ok(())
2173            }
2174            None => Err(instant_xml::Error::MissingValue(field)),
2175        }
2176    }
2177
2178    type Accumulator = Option<PlaybackStorageMedium>;
2179    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2180}
2181
2182#[derive(PartialEq, Debug, Clone, Eq, Default)]
2183pub enum TransportState {
2184    #[default]
2185    Stopped,
2186    Playing,
2187    PausedPlayback,
2188    Transitioning,
2189
2190    /// Allows passing a value that was not known at the
2191    /// time that this crate was generated from the available
2192    /// device descriptions
2193    Unspecified(String),
2194}
2195
2196impl ToString for TransportState {
2197    fn to_string(&self) -> String {
2198        match self {
2199            TransportState::Stopped => "STOPPED".to_string(),
2200            TransportState::Playing => "PLAYING".to_string(),
2201            TransportState::PausedPlayback => "PAUSED_PLAYBACK".to_string(),
2202            TransportState::Transitioning => "TRANSITIONING".to_string(),
2203            TransportState::Unspecified(s) => s.to_string(),
2204        }
2205    }
2206}
2207
2208impl FromStr for TransportState {
2209    type Err = crate::Error;
2210    fn from_str(s: &str) -> Result<TransportState> {
2211        match s {
2212            "STOPPED" => Ok(TransportState::Stopped),
2213            "PLAYING" => Ok(TransportState::Playing),
2214            "PAUSED_PLAYBACK" => Ok(TransportState::PausedPlayback),
2215            "TRANSITIONING" => Ok(TransportState::Transitioning),
2216            s => Ok(TransportState::Unspecified(s.to_string())),
2217        }
2218    }
2219}
2220
2221impl instant_xml::ToXml for TransportState {
2222    fn serialize<W: std::fmt::Write + ?Sized>(
2223        &self,
2224        field: Option<instant_xml::Id<'_>>,
2225        serializer: &mut instant_xml::Serializer<W>,
2226    ) -> std::result::Result<(), instant_xml::Error> {
2227        self.to_string().serialize(field, serializer)
2228    }
2229
2230    fn present(&self) -> bool {
2231        true
2232    }
2233}
2234
2235impl<'xml> instant_xml::FromXml<'xml> for TransportState {
2236    #[inline]
2237    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
2238        match field {
2239            Some(field) => id == field,
2240            None => false,
2241        }
2242    }
2243
2244    fn deserialize<'cx>(
2245        into: &mut Self::Accumulator,
2246        field: &'static str,
2247        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
2248    ) -> std::result::Result<(), instant_xml::Error> {
2249        if into.is_some() {
2250            return Err(instant_xml::Error::DuplicateValue(field));
2251        }
2252
2253        match deserializer.take_str()? {
2254            Some(value) => {
2255                let parsed: TransportState = value.parse().map_err(|err| {
2256                    instant_xml::Error::Other(format!(
2257                        "invalid value for field {field}: {value}: {err:#}"
2258                    ))
2259                })?;
2260                *into = Some(parsed);
2261                Ok(())
2262            }
2263            None => Err(instant_xml::Error::MissingValue(field)),
2264        }
2265    }
2266
2267    type Accumulator = Option<TransportState>;
2268    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2269}
2270
2271/// Request and Response types for the `AlarmClock` service.
2272pub mod alarm_clock {
2273    use super::*;
2274
2275    /// URN for the `AlarmClock` service.
2276    /// `urn:schemas-upnp-org:service:AlarmClock:1`
2277    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:AlarmClock:1";
2278
2279    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2280    #[xml(rename = "CreateAlarm", ns(SERVICE_TYPE))]
2281    pub struct CreateAlarmRequest {
2282        /// The start time as `hh:mm:ss`
2283        #[xml(rename = "StartLocalTime", ns(""))]
2284        pub start_local_time: String,
2285        /// The duration as `hh:mm:ss`
2286        #[xml(rename = "Duration", ns(""))]
2287        pub duration: String,
2288        /// Repeat this alarm on
2289        #[xml(rename = "Recurrence", ns(""))]
2290        pub recurrence: super::Recurrence,
2291        /// Alarm enabled after creation
2292        #[xml(rename = "Enabled", ns(""))]
2293        pub enabled: bool,
2294        /// The UUID of the speaker you want this alarm for
2295        #[xml(rename = "RoomUUID", ns(""))]
2296        pub room_uuid: String,
2297        /// The sound uri
2298        #[xml(rename = "ProgramURI", ns(""))]
2299        pub program_uri: String,
2300        /// The sound metadata, can be empty string
2301        #[xml(rename = "ProgramMetaData", ns(""))]
2302        pub program_meta_data: String,
2303        /// Alarm play mode
2304        #[xml(rename = "PlayMode", ns(""))]
2305        pub play_mode: super::AlarmPlayMode,
2306        /// Volume between 0 and 100
2307        #[xml(rename = "Volume", ns(""))]
2308        pub volume: u16,
2309        /// Should grouped players also play the alarm?
2310        #[xml(rename = "IncludeLinkedZones", ns(""))]
2311        pub include_linked_zones: bool,
2312    }
2313
2314    #[derive(FromXml, Debug, Clone, PartialEq)]
2315    #[xml(rename = "CreateAlarmResponse", ns(SERVICE_TYPE))]
2316    pub struct CreateAlarmResponse {
2317        #[xml(rename = "AssignedID", ns(""))]
2318        pub assigned_id: Option<u32>,
2319    }
2320
2321    impl crate::DecodeSoapResponse for CreateAlarmResponse {
2322        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2323            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2324            Ok(envelope.body.payload)
2325        }
2326    }
2327
2328    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2329    #[xml(rename = "DestroyAlarm", ns(SERVICE_TYPE))]
2330    pub struct DestroyAlarmRequest {
2331        /// The Alarm ID from ListAlarms
2332        #[xml(rename = "ID", ns(""))]
2333        pub id: u32,
2334    }
2335
2336    #[derive(FromXml, Debug, Clone, PartialEq)]
2337    #[xml(rename = "GetDailyIndexRefreshTimeResponse", ns(SERVICE_TYPE))]
2338    pub struct GetDailyIndexRefreshTimeResponse {
2339        #[xml(rename = "CurrentDailyIndexRefreshTime", ns(""))]
2340        pub current_daily_index_refresh_time: Option<String>,
2341    }
2342
2343    impl crate::DecodeSoapResponse for GetDailyIndexRefreshTimeResponse {
2344        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2345            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2346            Ok(envelope.body.payload)
2347        }
2348    }
2349
2350    #[derive(FromXml, Debug, Clone, PartialEq)]
2351    #[xml(rename = "GetFormatResponse", ns(SERVICE_TYPE))]
2352    pub struct GetFormatResponse {
2353        #[xml(rename = "CurrentTimeFormat", ns(""))]
2354        pub current_time_format: Option<String>,
2355        #[xml(rename = "CurrentDateFormat", ns(""))]
2356        pub current_date_format: Option<String>,
2357    }
2358
2359    impl crate::DecodeSoapResponse for GetFormatResponse {
2360        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2361            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2362            Ok(envelope.body.payload)
2363        }
2364    }
2365
2366    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2367    #[xml(rename = "GetHouseholdTimeAtStamp", ns(SERVICE_TYPE))]
2368    pub struct GetHouseholdTimeAtStampRequest {
2369        #[xml(rename = "TimeStamp", ns(""))]
2370        pub time_stamp: String,
2371    }
2372
2373    #[derive(FromXml, Debug, Clone, PartialEq)]
2374    #[xml(rename = "GetHouseholdTimeAtStampResponse", ns(SERVICE_TYPE))]
2375    pub struct GetHouseholdTimeAtStampResponse {
2376        #[xml(rename = "HouseholdUTCTime", ns(""))]
2377        pub household_utc_time: Option<String>,
2378    }
2379
2380    impl crate::DecodeSoapResponse for GetHouseholdTimeAtStampResponse {
2381        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2382            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2383            Ok(envelope.body.payload)
2384        }
2385    }
2386
2387    #[derive(FromXml, Debug, Clone, PartialEq)]
2388    #[xml(rename = "GetTimeNowResponse", ns(SERVICE_TYPE))]
2389    pub struct GetTimeNowResponse {
2390        #[xml(rename = "CurrentUTCTime", ns(""))]
2391        pub current_utc_time: Option<String>,
2392        #[xml(rename = "CurrentLocalTime", ns(""))]
2393        pub current_local_time: Option<String>,
2394        #[xml(rename = "CurrentTimeZone", ns(""))]
2395        pub current_time_zone: Option<String>,
2396        #[xml(rename = "CurrentTimeGeneration", ns(""))]
2397        pub current_time_generation: Option<u32>,
2398    }
2399
2400    impl crate::DecodeSoapResponse for GetTimeNowResponse {
2401        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2402            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2403            Ok(envelope.body.payload)
2404        }
2405    }
2406
2407    #[derive(FromXml, Debug, Clone, PartialEq)]
2408    #[xml(rename = "GetTimeServerResponse", ns(SERVICE_TYPE))]
2409    pub struct GetTimeServerResponse {
2410        #[xml(rename = "CurrentTimeServer", ns(""))]
2411        pub current_time_server: Option<String>,
2412    }
2413
2414    impl crate::DecodeSoapResponse for GetTimeServerResponse {
2415        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2416            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2417            Ok(envelope.body.payload)
2418        }
2419    }
2420
2421    #[derive(FromXml, Debug, Clone, PartialEq)]
2422    #[xml(rename = "GetTimeZoneResponse", ns(SERVICE_TYPE))]
2423    pub struct GetTimeZoneResponse {
2424        #[xml(rename = "Index", ns(""))]
2425        pub index: Option<i32>,
2426        #[xml(rename = "AutoAdjustDst", ns(""))]
2427        pub auto_adjust_dst: Option<bool>,
2428    }
2429
2430    impl crate::DecodeSoapResponse for GetTimeZoneResponse {
2431        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2432            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2433            Ok(envelope.body.payload)
2434        }
2435    }
2436
2437    #[derive(FromXml, Debug, Clone, PartialEq)]
2438    #[xml(rename = "GetTimeZoneAndRuleResponse", ns(SERVICE_TYPE))]
2439    pub struct GetTimeZoneAndRuleResponse {
2440        #[xml(rename = "Index", ns(""))]
2441        pub index: Option<i32>,
2442        #[xml(rename = "AutoAdjustDst", ns(""))]
2443        pub auto_adjust_dst: Option<bool>,
2444        #[xml(rename = "CurrentTimeZone", ns(""))]
2445        pub current_time_zone: Option<String>,
2446    }
2447
2448    impl crate::DecodeSoapResponse for GetTimeZoneAndRuleResponse {
2449        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2450            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2451            Ok(envelope.body.payload)
2452        }
2453    }
2454
2455    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2456    #[xml(rename = "GetTimeZoneRule", ns(SERVICE_TYPE))]
2457    pub struct GetTimeZoneRuleRequest {
2458        #[xml(rename = "Index", ns(""))]
2459        pub index: i32,
2460    }
2461
2462    #[derive(FromXml, Debug, Clone, PartialEq)]
2463    #[xml(rename = "GetTimeZoneRuleResponse", ns(SERVICE_TYPE))]
2464    pub struct GetTimeZoneRuleResponse {
2465        #[xml(rename = "TimeZone", ns(""))]
2466        pub time_zone: Option<String>,
2467    }
2468
2469    impl crate::DecodeSoapResponse for GetTimeZoneRuleResponse {
2470        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2471            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2472            Ok(envelope.body.payload)
2473        }
2474    }
2475
2476    #[derive(FromXml, Debug, Clone, PartialEq)]
2477    #[xml(rename = "ListAlarmsResponse", ns(SERVICE_TYPE))]
2478    pub struct ListAlarmsResponse {
2479        #[xml(rename = "CurrentAlarmList", ns(""))]
2480        pub current_alarm_list: Option<String>,
2481        #[xml(rename = "CurrentAlarmListVersion", ns(""))]
2482        pub current_alarm_list_version: Option<String>,
2483    }
2484
2485    impl crate::DecodeSoapResponse for ListAlarmsResponse {
2486        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2487            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2488            Ok(envelope.body.payload)
2489        }
2490    }
2491
2492    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2493    #[xml(rename = "SetDailyIndexRefreshTime", ns(SERVICE_TYPE))]
2494    pub struct SetDailyIndexRefreshTimeRequest {
2495        #[xml(rename = "DesiredDailyIndexRefreshTime", ns(""))]
2496        pub desired_daily_index_refresh_time: String,
2497    }
2498
2499    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2500    #[xml(rename = "SetFormat", ns(SERVICE_TYPE))]
2501    pub struct SetFormatRequest {
2502        #[xml(rename = "DesiredTimeFormat", ns(""))]
2503        pub desired_time_format: String,
2504        #[xml(rename = "DesiredDateFormat", ns(""))]
2505        pub desired_date_format: String,
2506    }
2507
2508    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2509    #[xml(rename = "SetTimeNow", ns(SERVICE_TYPE))]
2510    pub struct SetTimeNowRequest {
2511        #[xml(rename = "DesiredTime", ns(""))]
2512        pub desired_time: String,
2513        #[xml(rename = "TimeZoneForDesiredTime", ns(""))]
2514        pub time_zone_for_desired_time: String,
2515    }
2516
2517    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2518    #[xml(rename = "SetTimeServer", ns(SERVICE_TYPE))]
2519    pub struct SetTimeServerRequest {
2520        #[xml(rename = "DesiredTimeServer", ns(""))]
2521        pub desired_time_server: String,
2522    }
2523
2524    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2525    #[xml(rename = "SetTimeZone", ns(SERVICE_TYPE))]
2526    pub struct SetTimeZoneRequest {
2527        #[xml(rename = "Index", ns(""))]
2528        pub index: i32,
2529        #[xml(rename = "AutoAdjustDst", ns(""))]
2530        pub auto_adjust_dst: bool,
2531    }
2532
2533    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2534    #[xml(rename = "UpdateAlarm", ns(SERVICE_TYPE))]
2535    pub struct UpdateAlarmRequest {
2536        /// The ID of the alarm see ListAlarms
2537        #[xml(rename = "ID", ns(""))]
2538        pub id: u32,
2539        /// The start time as `hh:mm:ss`
2540        #[xml(rename = "StartLocalTime", ns(""))]
2541        pub start_local_time: String,
2542        /// The duration as `hh:mm:ss`
2543        #[xml(rename = "Duration", ns(""))]
2544        pub duration: String,
2545        /// Repeat this alarm on
2546        #[xml(rename = "Recurrence", ns(""))]
2547        pub recurrence: super::Recurrence,
2548        /// Alarm enabled after creation
2549        #[xml(rename = "Enabled", ns(""))]
2550        pub enabled: bool,
2551        /// The UUID of the speaker you want this alarm for
2552        #[xml(rename = "RoomUUID", ns(""))]
2553        pub room_uuid: String,
2554        /// The sound uri
2555        #[xml(rename = "ProgramURI", ns(""))]
2556        pub program_uri: String,
2557        /// The sound metadata, can be empty string
2558        #[xml(rename = "ProgramMetaData", ns(""))]
2559        pub program_meta_data: String,
2560        /// Alarm play mode
2561        #[xml(rename = "PlayMode", ns(""))]
2562        pub play_mode: super::AlarmPlayMode,
2563        /// Volume between 0 and 100
2564        #[xml(rename = "Volume", ns(""))]
2565        pub volume: u16,
2566        /// Should grouped players also play the alarm?
2567        #[xml(rename = "IncludeLinkedZones", ns(""))]
2568        pub include_linked_zones: bool,
2569    }
2570
2571    /// A parsed event produced by the `AlarmClock` service.
2572    /// Use `SonosDevice::subscribe_alarm_clock()` to obtain an event
2573    /// stream that produces these.
2574    #[derive(Debug, Clone, PartialEq, Default)]
2575    pub struct AlarmClockEvent {
2576        pub alarm_list_version: Option<String>,
2577        pub daily_index_refresh_time: Option<String>,
2578        pub date_format: Option<String>,
2579        pub time_format: Option<String>,
2580        pub time_generation: Option<u32>,
2581        pub time_server: Option<String>,
2582        pub time_zone: Option<String>,
2583    }
2584
2585    #[derive(FromXml, Debug, Clone, PartialEq)]
2586    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
2587    struct AlarmClockPropertySet {
2588        pub properties: Vec<AlarmClockProperty>,
2589    }
2590
2591    #[derive(FromXml, Debug, Clone, PartialEq)]
2592    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
2593    struct AlarmClockProperty {
2594        #[xml(rename = "AlarmListVersion", ns(""))]
2595        pub alarm_list_version: Option<String>,
2596        #[xml(rename = "DailyIndexRefreshTime", ns(""))]
2597        pub daily_index_refresh_time: Option<String>,
2598        #[xml(rename = "DateFormat", ns(""))]
2599        pub date_format: Option<String>,
2600        #[xml(rename = "TimeFormat", ns(""))]
2601        pub time_format: Option<String>,
2602        #[xml(rename = "TimeGeneration", ns(""))]
2603        pub time_generation: Option<u32>,
2604        #[xml(rename = "TimeServer", ns(""))]
2605        pub time_server: Option<String>,
2606        #[xml(rename = "TimeZone", ns(""))]
2607        pub time_zone: Option<String>,
2608    }
2609
2610    impl DecodeXml for AlarmClockEvent {
2611        fn decode_xml(xml: &str) -> crate::Result<Self> {
2612            let mut result = Self::default();
2613            let set: AlarmClockPropertySet = instant_xml::from_str(xml)?;
2614            for prop in set.properties {
2615                if let Some(v) = prop.alarm_list_version {
2616                    result.alarm_list_version.replace(v);
2617                }
2618
2619                if let Some(v) = prop.daily_index_refresh_time {
2620                    result.daily_index_refresh_time.replace(v);
2621                }
2622
2623                if let Some(v) = prop.date_format {
2624                    result.date_format.replace(v);
2625                }
2626
2627                if let Some(v) = prop.time_format {
2628                    result.time_format.replace(v);
2629                }
2630
2631                if let Some(v) = prop.time_generation {
2632                    result.time_generation.replace(v);
2633                }
2634
2635                if let Some(v) = prop.time_server {
2636                    result.time_server.replace(v);
2637                }
2638
2639                if let Some(v) = prop.time_zone {
2640                    result.time_zone.replace(v);
2641                }
2642            }
2643            Ok(result)
2644        }
2645    }
2646
2647    impl crate::SonosDevice {
2648        /// Subscribe to events from the `AlarmClock` service on this device
2649        pub async fn subscribe_alarm_clock(
2650            &self,
2651        ) -> crate::Result<crate::upnp::EventStream<AlarmClockEvent>> {
2652            self.subscribe_helper(&SERVICE_TYPE).await
2653        }
2654    }
2655}
2656
2657#[derive(PartialEq, Debug, Clone, Eq, Default)]
2658pub enum AlarmPlayMode {
2659    #[default]
2660    Normal,
2661    RepeatAll,
2662    ShuffleNorepeat,
2663    Shuffle,
2664
2665    /// Allows passing a value that was not known at the
2666    /// time that this crate was generated from the available
2667    /// device descriptions
2668    Unspecified(String),
2669}
2670
2671impl ToString for AlarmPlayMode {
2672    fn to_string(&self) -> String {
2673        match self {
2674            AlarmPlayMode::Normal => "NORMAL".to_string(),
2675            AlarmPlayMode::RepeatAll => "REPEAT_ALL".to_string(),
2676            AlarmPlayMode::ShuffleNorepeat => "SHUFFLE_NOREPEAT".to_string(),
2677            AlarmPlayMode::Shuffle => "SHUFFLE".to_string(),
2678            AlarmPlayMode::Unspecified(s) => s.to_string(),
2679        }
2680    }
2681}
2682
2683impl FromStr for AlarmPlayMode {
2684    type Err = crate::Error;
2685    fn from_str(s: &str) -> Result<AlarmPlayMode> {
2686        match s {
2687            "NORMAL" => Ok(AlarmPlayMode::Normal),
2688            "REPEAT_ALL" => Ok(AlarmPlayMode::RepeatAll),
2689            "SHUFFLE_NOREPEAT" => Ok(AlarmPlayMode::ShuffleNorepeat),
2690            "SHUFFLE" => Ok(AlarmPlayMode::Shuffle),
2691            s => Ok(AlarmPlayMode::Unspecified(s.to_string())),
2692        }
2693    }
2694}
2695
2696impl instant_xml::ToXml for AlarmPlayMode {
2697    fn serialize<W: std::fmt::Write + ?Sized>(
2698        &self,
2699        field: Option<instant_xml::Id<'_>>,
2700        serializer: &mut instant_xml::Serializer<W>,
2701    ) -> std::result::Result<(), instant_xml::Error> {
2702        self.to_string().serialize(field, serializer)
2703    }
2704
2705    fn present(&self) -> bool {
2706        true
2707    }
2708}
2709
2710impl<'xml> instant_xml::FromXml<'xml> for AlarmPlayMode {
2711    #[inline]
2712    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
2713        match field {
2714            Some(field) => id == field,
2715            None => false,
2716        }
2717    }
2718
2719    fn deserialize<'cx>(
2720        into: &mut Self::Accumulator,
2721        field: &'static str,
2722        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
2723    ) -> std::result::Result<(), instant_xml::Error> {
2724        if into.is_some() {
2725            return Err(instant_xml::Error::DuplicateValue(field));
2726        }
2727
2728        match deserializer.take_str()? {
2729            Some(value) => {
2730                let parsed: AlarmPlayMode = value.parse().map_err(|err| {
2731                    instant_xml::Error::Other(format!(
2732                        "invalid value for field {field}: {value}: {err:#}"
2733                    ))
2734                })?;
2735                *into = Some(parsed);
2736                Ok(())
2737            }
2738            None => Err(instant_xml::Error::MissingValue(field)),
2739        }
2740    }
2741
2742    type Accumulator = Option<AlarmPlayMode>;
2743    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2744}
2745
2746#[derive(PartialEq, Debug, Clone, Eq, Default)]
2747pub enum Recurrence {
2748    #[default]
2749    Once,
2750    Weekdays,
2751    Weekends,
2752    Daily,
2753
2754    /// Allows passing a value that was not known at the
2755    /// time that this crate was generated from the available
2756    /// device descriptions
2757    Unspecified(String),
2758}
2759
2760impl ToString for Recurrence {
2761    fn to_string(&self) -> String {
2762        match self {
2763            Recurrence::Once => "ONCE".to_string(),
2764            Recurrence::Weekdays => "WEEKDAYS".to_string(),
2765            Recurrence::Weekends => "WEEKENDS".to_string(),
2766            Recurrence::Daily => "DAILY".to_string(),
2767            Recurrence::Unspecified(s) => s.to_string(),
2768        }
2769    }
2770}
2771
2772impl FromStr for Recurrence {
2773    type Err = crate::Error;
2774    fn from_str(s: &str) -> Result<Recurrence> {
2775        match s {
2776            "ONCE" => Ok(Recurrence::Once),
2777            "WEEKDAYS" => Ok(Recurrence::Weekdays),
2778            "WEEKENDS" => Ok(Recurrence::Weekends),
2779            "DAILY" => Ok(Recurrence::Daily),
2780            s => Ok(Recurrence::Unspecified(s.to_string())),
2781        }
2782    }
2783}
2784
2785impl instant_xml::ToXml for Recurrence {
2786    fn serialize<W: std::fmt::Write + ?Sized>(
2787        &self,
2788        field: Option<instant_xml::Id<'_>>,
2789        serializer: &mut instant_xml::Serializer<W>,
2790    ) -> std::result::Result<(), instant_xml::Error> {
2791        self.to_string().serialize(field, serializer)
2792    }
2793
2794    fn present(&self) -> bool {
2795        true
2796    }
2797}
2798
2799impl<'xml> instant_xml::FromXml<'xml> for Recurrence {
2800    #[inline]
2801    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
2802        match field {
2803            Some(field) => id == field,
2804            None => false,
2805        }
2806    }
2807
2808    fn deserialize<'cx>(
2809        into: &mut Self::Accumulator,
2810        field: &'static str,
2811        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
2812    ) -> std::result::Result<(), instant_xml::Error> {
2813        if into.is_some() {
2814            return Err(instant_xml::Error::DuplicateValue(field));
2815        }
2816
2817        match deserializer.take_str()? {
2818            Some(value) => {
2819                let parsed: Recurrence = value.parse().map_err(|err| {
2820                    instant_xml::Error::Other(format!(
2821                        "invalid value for field {field}: {value}: {err:#}"
2822                    ))
2823                })?;
2824                *into = Some(parsed);
2825                Ok(())
2826            }
2827            None => Err(instant_xml::Error::MissingValue(field)),
2828        }
2829    }
2830
2831    type Accumulator = Option<Recurrence>;
2832    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
2833}
2834
2835/// Request and Response types for the `AudioIn` service.
2836pub mod audio_in {
2837    use super::*;
2838
2839    /// URN for the `AudioIn` service.
2840    /// `urn:schemas-upnp-org:service:AudioIn:1`
2841    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:AudioIn:1";
2842
2843    #[derive(FromXml, Debug, Clone, PartialEq)]
2844    #[xml(rename = "GetAudioInputAttributesResponse", ns(SERVICE_TYPE))]
2845    pub struct GetAudioInputAttributesResponse {
2846        #[xml(rename = "CurrentName", ns(""))]
2847        pub current_name: Option<String>,
2848        #[xml(rename = "CurrentIcon", ns(""))]
2849        pub current_icon: Option<String>,
2850    }
2851
2852    impl crate::DecodeSoapResponse for GetAudioInputAttributesResponse {
2853        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2854            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2855            Ok(envelope.body.payload)
2856        }
2857    }
2858
2859    #[derive(FromXml, Debug, Clone, PartialEq)]
2860    #[xml(rename = "GetLineInLevelResponse", ns(SERVICE_TYPE))]
2861    pub struct GetLineInLevelResponse {
2862        #[xml(rename = "CurrentLeftLineInLevel", ns(""))]
2863        pub current_left_line_in_level: Option<i32>,
2864        #[xml(rename = "CurrentRightLineInLevel", ns(""))]
2865        pub current_right_line_in_level: Option<i32>,
2866    }
2867
2868    impl crate::DecodeSoapResponse for GetLineInLevelResponse {
2869        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2870            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2871            Ok(envelope.body.payload)
2872        }
2873    }
2874
2875    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2876    #[xml(rename = "SelectAudio", ns(SERVICE_TYPE))]
2877    pub struct SelectAudioRequest {
2878        #[xml(rename = "ObjectID", ns(""))]
2879        pub object_id: String,
2880    }
2881
2882    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2883    #[xml(rename = "SetAudioInputAttributes", ns(SERVICE_TYPE))]
2884    pub struct SetAudioInputAttributesRequest {
2885        #[xml(rename = "DesiredName", ns(""))]
2886        pub desired_name: String,
2887        #[xml(rename = "DesiredIcon", ns(""))]
2888        pub desired_icon: String,
2889    }
2890
2891    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2892    #[xml(rename = "SetLineInLevel", ns(SERVICE_TYPE))]
2893    pub struct SetLineInLevelRequest {
2894        #[xml(rename = "DesiredLeftLineInLevel", ns(""))]
2895        pub desired_left_line_in_level: i32,
2896        #[xml(rename = "DesiredRightLineInLevel", ns(""))]
2897        pub desired_right_line_in_level: i32,
2898    }
2899
2900    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2901    #[xml(rename = "StartTransmissionToGroup", ns(SERVICE_TYPE))]
2902    pub struct StartTransmissionToGroupRequest {
2903        #[xml(rename = "CoordinatorID", ns(""))]
2904        pub coordinator_id: String,
2905    }
2906
2907    #[derive(FromXml, Debug, Clone, PartialEq)]
2908    #[xml(rename = "StartTransmissionToGroupResponse", ns(SERVICE_TYPE))]
2909    pub struct StartTransmissionToGroupResponse {
2910        #[xml(rename = "CurrentTransportSettings", ns(""))]
2911        pub current_transport_settings: Option<String>,
2912    }
2913
2914    impl crate::DecodeSoapResponse for StartTransmissionToGroupResponse {
2915        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
2916            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
2917            Ok(envelope.body.payload)
2918        }
2919    }
2920
2921    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
2922    #[xml(rename = "StopTransmissionToGroup", ns(SERVICE_TYPE))]
2923    pub struct StopTransmissionToGroupRequest {
2924        #[xml(rename = "CoordinatorID", ns(""))]
2925        pub coordinator_id: String,
2926    }
2927
2928    /// A parsed event produced by the `AudioIn` service.
2929    /// Use `SonosDevice::subscribe_audio_in()` to obtain an event
2930    /// stream that produces these.
2931    #[derive(Debug, Clone, PartialEq, Default)]
2932    pub struct AudioInEvent {
2933        pub audio_input_name: Option<String>,
2934        pub icon: Option<String>,
2935        pub left_line_in_level: Option<i32>,
2936        pub line_in_connected: Option<bool>,
2937        pub playing: Option<bool>,
2938        pub right_line_in_level: Option<i32>,
2939    }
2940
2941    #[derive(FromXml, Debug, Clone, PartialEq)]
2942    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
2943    struct AudioInPropertySet {
2944        pub properties: Vec<AudioInProperty>,
2945    }
2946
2947    #[derive(FromXml, Debug, Clone, PartialEq)]
2948    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
2949    struct AudioInProperty {
2950        #[xml(rename = "AudioInputName", ns(""))]
2951        pub audio_input_name: Option<String>,
2952        #[xml(rename = "Icon", ns(""))]
2953        pub icon: Option<String>,
2954        #[xml(rename = "LeftLineInLevel", ns(""))]
2955        pub left_line_in_level: Option<i32>,
2956        #[xml(rename = "LineInConnected", ns(""))]
2957        pub line_in_connected: Option<bool>,
2958        #[xml(rename = "Playing", ns(""))]
2959        pub playing: Option<bool>,
2960        #[xml(rename = "RightLineInLevel", ns(""))]
2961        pub right_line_in_level: Option<i32>,
2962    }
2963
2964    impl DecodeXml for AudioInEvent {
2965        fn decode_xml(xml: &str) -> crate::Result<Self> {
2966            let mut result = Self::default();
2967            let set: AudioInPropertySet = instant_xml::from_str(xml)?;
2968            for prop in set.properties {
2969                if let Some(v) = prop.audio_input_name {
2970                    result.audio_input_name.replace(v);
2971                }
2972
2973                if let Some(v) = prop.icon {
2974                    result.icon.replace(v);
2975                }
2976
2977                if let Some(v) = prop.left_line_in_level {
2978                    result.left_line_in_level.replace(v);
2979                }
2980
2981                if let Some(v) = prop.line_in_connected {
2982                    result.line_in_connected.replace(v);
2983                }
2984
2985                if let Some(v) = prop.playing {
2986                    result.playing.replace(v);
2987                }
2988
2989                if let Some(v) = prop.right_line_in_level {
2990                    result.right_line_in_level.replace(v);
2991                }
2992            }
2993            Ok(result)
2994        }
2995    }
2996
2997    impl crate::SonosDevice {
2998        /// Subscribe to events from the `AudioIn` service on this device
2999        pub async fn subscribe_audio_in(
3000            &self,
3001        ) -> crate::Result<crate::upnp::EventStream<AudioInEvent>> {
3002            self.subscribe_helper(&SERVICE_TYPE).await
3003        }
3004    }
3005}
3006
3007/// Request and Response types for the `ConnectionManager` service.
3008pub mod connection_manager {
3009    use super::*;
3010
3011    /// URN for the `ConnectionManager` service.
3012    /// `urn:schemas-upnp-org:service:ConnectionManager:1`
3013    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:ConnectionManager:1";
3014
3015    #[derive(FromXml, Debug, Clone, PartialEq)]
3016    #[xml(rename = "GetCurrentConnectionIDsResponse", ns(SERVICE_TYPE))]
3017    pub struct GetCurrentConnectionIdsResponse {
3018        #[xml(rename = "ConnectionIDs", ns(""))]
3019        pub connection_ids: Option<String>,
3020    }
3021
3022    impl crate::DecodeSoapResponse for GetCurrentConnectionIdsResponse {
3023        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3024            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3025            Ok(envelope.body.payload)
3026        }
3027    }
3028
3029    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3030    #[xml(rename = "GetCurrentConnectionInfo", ns(SERVICE_TYPE))]
3031    pub struct GetCurrentConnectionInfoRequest {
3032        #[xml(rename = "ConnectionID", ns(""))]
3033        pub connection_id: i32,
3034    }
3035
3036    #[derive(FromXml, Debug, Clone, PartialEq)]
3037    #[xml(rename = "GetCurrentConnectionInfoResponse", ns(SERVICE_TYPE))]
3038    pub struct GetCurrentConnectionInfoResponse {
3039        #[xml(rename = "RcsID", ns(""))]
3040        pub rcs_id: Option<i32>,
3041        #[xml(rename = "AVTransportID", ns(""))]
3042        pub av_transport_id: Option<i32>,
3043        #[xml(rename = "ProtocolInfo", ns(""))]
3044        pub protocol_info: Option<String>,
3045        #[xml(rename = "PeerConnectionManager", ns(""))]
3046        pub peer_connection_manager: Option<String>,
3047        #[xml(rename = "PeerConnectionID", ns(""))]
3048        pub peer_connection_id: Option<i32>,
3049        #[xml(rename = "Direction", ns(""))]
3050        pub direction: Option<super::Direction>,
3051        #[xml(rename = "Status", ns(""))]
3052        pub status: Option<super::ConnectionStatus>,
3053    }
3054
3055    impl crate::DecodeSoapResponse for GetCurrentConnectionInfoResponse {
3056        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3057            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3058            Ok(envelope.body.payload)
3059        }
3060    }
3061
3062    #[derive(FromXml, Debug, Clone, PartialEq)]
3063    #[xml(rename = "GetProtocolInfoResponse", ns(SERVICE_TYPE))]
3064    pub struct GetProtocolInfoResponse {
3065        #[xml(rename = "Source", ns(""))]
3066        pub source: Option<String>,
3067        #[xml(rename = "Sink", ns(""))]
3068        pub sink: Option<String>,
3069    }
3070
3071    impl crate::DecodeSoapResponse for GetProtocolInfoResponse {
3072        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3073            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3074            Ok(envelope.body.payload)
3075        }
3076    }
3077
3078    /// A parsed event produced by the `ConnectionManager` service.
3079    /// Use `SonosDevice::subscribe_connection_manager()` to obtain an event
3080    /// stream that produces these.
3081    #[derive(Debug, Clone, PartialEq, Default)]
3082    pub struct ConnectionManagerEvent {
3083        pub current_connection_ids: Option<String>,
3084        pub sink_protocol_info: Option<String>,
3085        pub source_protocol_info: Option<String>,
3086    }
3087
3088    #[derive(FromXml, Debug, Clone, PartialEq)]
3089    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
3090    struct ConnectionManagerPropertySet {
3091        pub properties: Vec<ConnectionManagerProperty>,
3092    }
3093
3094    #[derive(FromXml, Debug, Clone, PartialEq)]
3095    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
3096    struct ConnectionManagerProperty {
3097        #[xml(rename = "CurrentConnectionIDs", ns(""))]
3098        pub current_connection_ids: Option<String>,
3099        #[xml(rename = "SinkProtocolInfo", ns(""))]
3100        pub sink_protocol_info: Option<String>,
3101        #[xml(rename = "SourceProtocolInfo", ns(""))]
3102        pub source_protocol_info: Option<String>,
3103    }
3104
3105    impl DecodeXml for ConnectionManagerEvent {
3106        fn decode_xml(xml: &str) -> crate::Result<Self> {
3107            let mut result = Self::default();
3108            let set: ConnectionManagerPropertySet = instant_xml::from_str(xml)?;
3109            for prop in set.properties {
3110                if let Some(v) = prop.current_connection_ids {
3111                    result.current_connection_ids.replace(v);
3112                }
3113
3114                if let Some(v) = prop.sink_protocol_info {
3115                    result.sink_protocol_info.replace(v);
3116                }
3117
3118                if let Some(v) = prop.source_protocol_info {
3119                    result.source_protocol_info.replace(v);
3120                }
3121            }
3122            Ok(result)
3123        }
3124    }
3125
3126    impl crate::SonosDevice {
3127        /// Subscribe to events from the `ConnectionManager` service on this device
3128        pub async fn subscribe_connection_manager(
3129            &self,
3130        ) -> crate::Result<crate::upnp::EventStream<ConnectionManagerEvent>> {
3131            self.subscribe_helper(&SERVICE_TYPE).await
3132        }
3133    }
3134}
3135
3136#[derive(PartialEq, Debug, Clone, Eq, Default)]
3137pub enum ConnectionStatus {
3138    #[default]
3139    Ok,
3140    ContentFormatMismatch,
3141    InsufficientBandwidth,
3142    UnreliableChannel,
3143    Unknown,
3144
3145    /// Allows passing a value that was not known at the
3146    /// time that this crate was generated from the available
3147    /// device descriptions
3148    Unspecified(String),
3149}
3150
3151impl ToString for ConnectionStatus {
3152    fn to_string(&self) -> String {
3153        match self {
3154            ConnectionStatus::Ok => "OK".to_string(),
3155            ConnectionStatus::ContentFormatMismatch => "ContentFormatMismatch".to_string(),
3156            ConnectionStatus::InsufficientBandwidth => "InsufficientBandwidth".to_string(),
3157            ConnectionStatus::UnreliableChannel => "UnreliableChannel".to_string(),
3158            ConnectionStatus::Unknown => "Unknown".to_string(),
3159            ConnectionStatus::Unspecified(s) => s.to_string(),
3160        }
3161    }
3162}
3163
3164impl FromStr for ConnectionStatus {
3165    type Err = crate::Error;
3166    fn from_str(s: &str) -> Result<ConnectionStatus> {
3167        match s {
3168            "OK" => Ok(ConnectionStatus::Ok),
3169            "ContentFormatMismatch" => Ok(ConnectionStatus::ContentFormatMismatch),
3170            "InsufficientBandwidth" => Ok(ConnectionStatus::InsufficientBandwidth),
3171            "UnreliableChannel" => Ok(ConnectionStatus::UnreliableChannel),
3172            "Unknown" => Ok(ConnectionStatus::Unknown),
3173            s => Ok(ConnectionStatus::Unspecified(s.to_string())),
3174        }
3175    }
3176}
3177
3178impl instant_xml::ToXml for ConnectionStatus {
3179    fn serialize<W: std::fmt::Write + ?Sized>(
3180        &self,
3181        field: Option<instant_xml::Id<'_>>,
3182        serializer: &mut instant_xml::Serializer<W>,
3183    ) -> std::result::Result<(), instant_xml::Error> {
3184        self.to_string().serialize(field, serializer)
3185    }
3186
3187    fn present(&self) -> bool {
3188        true
3189    }
3190}
3191
3192impl<'xml> instant_xml::FromXml<'xml> for ConnectionStatus {
3193    #[inline]
3194    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
3195        match field {
3196            Some(field) => id == field,
3197            None => false,
3198        }
3199    }
3200
3201    fn deserialize<'cx>(
3202        into: &mut Self::Accumulator,
3203        field: &'static str,
3204        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
3205    ) -> std::result::Result<(), instant_xml::Error> {
3206        if into.is_some() {
3207            return Err(instant_xml::Error::DuplicateValue(field));
3208        }
3209
3210        match deserializer.take_str()? {
3211            Some(value) => {
3212                let parsed: ConnectionStatus = value.parse().map_err(|err| {
3213                    instant_xml::Error::Other(format!(
3214                        "invalid value for field {field}: {value}: {err:#}"
3215                    ))
3216                })?;
3217                *into = Some(parsed);
3218                Ok(())
3219            }
3220            None => Err(instant_xml::Error::MissingValue(field)),
3221        }
3222    }
3223
3224    type Accumulator = Option<ConnectionStatus>;
3225    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
3226}
3227
3228#[derive(PartialEq, Debug, Clone, Eq, Default)]
3229pub enum Direction {
3230    #[default]
3231    Input,
3232    Output,
3233
3234    /// Allows passing a value that was not known at the
3235    /// time that this crate was generated from the available
3236    /// device descriptions
3237    Unspecified(String),
3238}
3239
3240impl ToString for Direction {
3241    fn to_string(&self) -> String {
3242        match self {
3243            Direction::Input => "Input".to_string(),
3244            Direction::Output => "Output".to_string(),
3245            Direction::Unspecified(s) => s.to_string(),
3246        }
3247    }
3248}
3249
3250impl FromStr for Direction {
3251    type Err = crate::Error;
3252    fn from_str(s: &str) -> Result<Direction> {
3253        match s {
3254            "Input" => Ok(Direction::Input),
3255            "Output" => Ok(Direction::Output),
3256            s => Ok(Direction::Unspecified(s.to_string())),
3257        }
3258    }
3259}
3260
3261impl instant_xml::ToXml for Direction {
3262    fn serialize<W: std::fmt::Write + ?Sized>(
3263        &self,
3264        field: Option<instant_xml::Id<'_>>,
3265        serializer: &mut instant_xml::Serializer<W>,
3266    ) -> std::result::Result<(), instant_xml::Error> {
3267        self.to_string().serialize(field, serializer)
3268    }
3269
3270    fn present(&self) -> bool {
3271        true
3272    }
3273}
3274
3275impl<'xml> instant_xml::FromXml<'xml> for Direction {
3276    #[inline]
3277    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
3278        match field {
3279            Some(field) => id == field,
3280            None => false,
3281        }
3282    }
3283
3284    fn deserialize<'cx>(
3285        into: &mut Self::Accumulator,
3286        field: &'static str,
3287        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
3288    ) -> std::result::Result<(), instant_xml::Error> {
3289        if into.is_some() {
3290            return Err(instant_xml::Error::DuplicateValue(field));
3291        }
3292
3293        match deserializer.take_str()? {
3294            Some(value) => {
3295                let parsed: Direction = value.parse().map_err(|err| {
3296                    instant_xml::Error::Other(format!(
3297                        "invalid value for field {field}: {value}: {err:#}"
3298                    ))
3299                })?;
3300                *into = Some(parsed);
3301                Ok(())
3302            }
3303            None => Err(instant_xml::Error::MissingValue(field)),
3304        }
3305    }
3306
3307    type Accumulator = Option<Direction>;
3308    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
3309}
3310
3311/// Request and Response types for the `ContentDirectory` service.
3312pub mod content_directory {
3313    use super::*;
3314
3315    /// URN for the `ContentDirectory` service.
3316    /// `urn:schemas-upnp-org:service:ContentDirectory:1`
3317    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:ContentDirectory:1";
3318
3319    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3320    #[xml(rename = "Browse", ns(SERVICE_TYPE))]
3321    pub struct BrowseRequest {
3322        /// The search query, (`A:ARTIST` / `A:ALBUMARTIST` / `A:ALBUM` / `A:GENRE` / `A:COMPOSER` / `A:TRACKS` / `A:PLAYLISTS` / `FV:2` / `Q:`/ `R:0/0` / `R:0/1` / `S:` / `SQ:`) with optionally `:search+query` behind it.
3323        #[xml(rename = "ObjectID", ns(""))]
3324        pub object_id: String,
3325        /// How to browse
3326        #[xml(rename = "BrowseFlag", ns(""))]
3327        pub browse_flag: super::BrowseFlag,
3328        /// Which fields should be returned `*` for all.
3329        #[xml(rename = "Filter", ns(""))]
3330        pub filter: String,
3331        /// Paging, where to start, usually 0
3332        #[xml(rename = "StartingIndex", ns(""))]
3333        pub starting_index: u32,
3334        /// Paging, number of items, maximum is 1,000. This parameter does NOT restrict the number of items being searched (filter) but only the number being returned. Using 0 is equivalent to 1,000
3335        #[xml(rename = "RequestedCount", ns(""))]
3336        pub requested_count: u32,
3337        /// Sort the results based on metadata fields. `+upnp:artist,+dc:title` for sorting on artist then on title.
3338        #[xml(rename = "SortCriteria", ns(""))]
3339        pub sort_criteria: String,
3340    }
3341
3342    #[derive(FromXml, Debug, Clone, PartialEq)]
3343    #[xml(rename = "BrowseResponse", ns(SERVICE_TYPE))]
3344    pub struct BrowseResponse {
3345        #[xml(rename = "Result", ns(""))]
3346        pub result: Option<DecodeXmlString<crate::TrackMetaDataList>>,
3347        #[xml(rename = "NumberReturned", ns(""))]
3348        pub number_returned: Option<u32>,
3349        #[xml(rename = "TotalMatches", ns(""))]
3350        pub total_matches: Option<u32>,
3351        #[xml(rename = "UpdateID", ns(""))]
3352        pub update_id: Option<u32>,
3353    }
3354
3355    impl crate::DecodeSoapResponse for BrowseResponse {
3356        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3357            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3358            Ok(envelope.body.payload)
3359        }
3360    }
3361
3362    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3363    #[xml(rename = "CreateObject", ns(SERVICE_TYPE))]
3364    pub struct CreateObjectRequest {
3365        #[xml(rename = "ContainerID", ns(""))]
3366        pub container_id: String,
3367        #[xml(rename = "Elements", ns(""))]
3368        pub elements: String,
3369    }
3370
3371    #[derive(FromXml, Debug, Clone, PartialEq)]
3372    #[xml(rename = "CreateObjectResponse", ns(SERVICE_TYPE))]
3373    pub struct CreateObjectResponse {
3374        #[xml(rename = "ObjectID", ns(""))]
3375        pub object_id: Option<String>,
3376        #[xml(rename = "Result", ns(""))]
3377        pub result: Option<String>,
3378    }
3379
3380    impl crate::DecodeSoapResponse for CreateObjectResponse {
3381        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3382            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3383            Ok(envelope.body.payload)
3384        }
3385    }
3386
3387    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3388    #[xml(rename = "DestroyObject", ns(SERVICE_TYPE))]
3389    pub struct DestroyObjectRequest {
3390        #[xml(rename = "ObjectID", ns(""))]
3391        pub object_id: String,
3392    }
3393
3394    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3395    #[xml(rename = "FindPrefix", ns(SERVICE_TYPE))]
3396    pub struct FindPrefixRequest {
3397        #[xml(rename = "ObjectID", ns(""))]
3398        pub object_id: String,
3399        #[xml(rename = "Prefix", ns(""))]
3400        pub prefix: String,
3401    }
3402
3403    #[derive(FromXml, Debug, Clone, PartialEq)]
3404    #[xml(rename = "FindPrefixResponse", ns(SERVICE_TYPE))]
3405    pub struct FindPrefixResponse {
3406        #[xml(rename = "StartingIndex", ns(""))]
3407        pub starting_index: Option<u32>,
3408        #[xml(rename = "UpdateID", ns(""))]
3409        pub update_id: Option<u32>,
3410    }
3411
3412    impl crate::DecodeSoapResponse for FindPrefixResponse {
3413        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3414            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3415            Ok(envelope.body.payload)
3416        }
3417    }
3418
3419    #[derive(FromXml, Debug, Clone, PartialEq)]
3420    #[xml(rename = "GetAlbumArtistDisplayOptionResponse", ns(SERVICE_TYPE))]
3421    pub struct GetAlbumArtistDisplayOptionResponse {
3422        #[xml(rename = "AlbumArtistDisplayOption", ns(""))]
3423        pub album_artist_display_option: Option<String>,
3424    }
3425
3426    impl crate::DecodeSoapResponse for GetAlbumArtistDisplayOptionResponse {
3427        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3428            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3429            Ok(envelope.body.payload)
3430        }
3431    }
3432
3433    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3434    #[xml(rename = "GetAllPrefixLocations", ns(SERVICE_TYPE))]
3435    pub struct GetAllPrefixLocationsRequest {
3436        #[xml(rename = "ObjectID", ns(""))]
3437        pub object_id: String,
3438    }
3439
3440    #[derive(FromXml, Debug, Clone, PartialEq)]
3441    #[xml(rename = "GetAllPrefixLocationsResponse", ns(SERVICE_TYPE))]
3442    pub struct GetAllPrefixLocationsResponse {
3443        #[xml(rename = "TotalPrefixes", ns(""))]
3444        pub total_prefixes: Option<u32>,
3445        #[xml(rename = "PrefixAndIndexCSV", ns(""))]
3446        pub prefix_and_index_csv: Option<String>,
3447        #[xml(rename = "UpdateID", ns(""))]
3448        pub update_id: Option<u32>,
3449    }
3450
3451    impl crate::DecodeSoapResponse for GetAllPrefixLocationsResponse {
3452        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3453            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3454            Ok(envelope.body.payload)
3455        }
3456    }
3457
3458    #[derive(FromXml, Debug, Clone, PartialEq)]
3459    #[xml(rename = "GetBrowseableResponse", ns(SERVICE_TYPE))]
3460    pub struct GetBrowseableResponse {
3461        #[xml(rename = "IsBrowseable", ns(""))]
3462        pub is_browseable: Option<bool>,
3463    }
3464
3465    impl crate::DecodeSoapResponse for GetBrowseableResponse {
3466        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3467            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3468            Ok(envelope.body.payload)
3469        }
3470    }
3471
3472    #[derive(FromXml, Debug, Clone, PartialEq)]
3473    #[xml(rename = "GetLastIndexChangeResponse", ns(SERVICE_TYPE))]
3474    pub struct GetLastIndexChangeResponse {
3475        #[xml(rename = "LastIndexChange", ns(""))]
3476        pub last_index_change: Option<String>,
3477    }
3478
3479    impl crate::DecodeSoapResponse for GetLastIndexChangeResponse {
3480        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3481            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3482            Ok(envelope.body.payload)
3483        }
3484    }
3485
3486    #[derive(FromXml, Debug, Clone, PartialEq)]
3487    #[xml(rename = "GetSearchCapabilitiesResponse", ns(SERVICE_TYPE))]
3488    pub struct GetSearchCapabilitiesResponse {
3489        #[xml(rename = "SearchCaps", ns(""))]
3490        pub search_caps: Option<String>,
3491    }
3492
3493    impl crate::DecodeSoapResponse for GetSearchCapabilitiesResponse {
3494        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3495            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3496            Ok(envelope.body.payload)
3497        }
3498    }
3499
3500    #[derive(FromXml, Debug, Clone, PartialEq)]
3501    #[xml(rename = "GetShareIndexInProgressResponse", ns(SERVICE_TYPE))]
3502    pub struct GetShareIndexInProgressResponse {
3503        #[xml(rename = "IsIndexing", ns(""))]
3504        pub is_indexing: Option<bool>,
3505    }
3506
3507    impl crate::DecodeSoapResponse for GetShareIndexInProgressResponse {
3508        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3509            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3510            Ok(envelope.body.payload)
3511        }
3512    }
3513
3514    #[derive(FromXml, Debug, Clone, PartialEq)]
3515    #[xml(rename = "GetSortCapabilitiesResponse", ns(SERVICE_TYPE))]
3516    pub struct GetSortCapabilitiesResponse {
3517        #[xml(rename = "SortCaps", ns(""))]
3518        pub sort_caps: Option<String>,
3519    }
3520
3521    impl crate::DecodeSoapResponse for GetSortCapabilitiesResponse {
3522        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3523            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3524            Ok(envelope.body.payload)
3525        }
3526    }
3527
3528    #[derive(FromXml, Debug, Clone, PartialEq)]
3529    #[xml(rename = "GetSystemUpdateIDResponse", ns(SERVICE_TYPE))]
3530    pub struct GetSystemUpdateIdResponse {
3531        #[xml(rename = "Id", ns(""))]
3532        pub id: Option<u32>,
3533    }
3534
3535    impl crate::DecodeSoapResponse for GetSystemUpdateIdResponse {
3536        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3537            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3538            Ok(envelope.body.payload)
3539        }
3540    }
3541
3542    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3543    #[xml(rename = "RefreshShareIndex", ns(SERVICE_TYPE))]
3544    pub struct RefreshShareIndexRequest {
3545        /// `WMP`, `ITUNES` or `NONE`
3546        #[xml(rename = "AlbumArtistDisplayOption", ns(""))]
3547        pub album_artist_display_option: String,
3548    }
3549
3550    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3551    #[xml(rename = "RequestResort", ns(SERVICE_TYPE))]
3552    pub struct RequestResortRequest {
3553        #[xml(rename = "SortOrder", ns(""))]
3554        pub sort_order: String,
3555    }
3556
3557    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3558    #[xml(rename = "SetBrowseable", ns(SERVICE_TYPE))]
3559    pub struct SetBrowseableRequest {
3560        #[xml(rename = "Browseable", ns(""))]
3561        pub browseable: bool,
3562    }
3563
3564    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3565    #[xml(rename = "UpdateObject", ns(SERVICE_TYPE))]
3566    pub struct UpdateObjectRequest {
3567        #[xml(rename = "ObjectID", ns(""))]
3568        pub object_id: String,
3569        #[xml(rename = "CurrentTagValue", ns(""))]
3570        pub current_tag_value: String,
3571        #[xml(rename = "NewTagValue", ns(""))]
3572        pub new_tag_value: String,
3573    }
3574
3575    /// A parsed event produced by the `ContentDirectory` service.
3576    /// Use `SonosDevice::subscribe_content_directory()` to obtain an event
3577    /// stream that produces these.
3578    #[derive(Debug, Clone, PartialEq, Default)]
3579    pub struct ContentDirectoryEvent {
3580        pub browseable: Option<bool>,
3581        pub container_update_ids: Option<String>,
3582        pub favorite_presets_update_id: Option<String>,
3583        pub favorites_update_id: Option<String>,
3584        pub radio_favorites_update_id: Option<u32>,
3585        pub radio_location_update_id: Option<u32>,
3586        pub recently_played_update_id: Option<String>,
3587        pub saved_queues_update_id: Option<String>,
3588        pub share_index_in_progress: Option<bool>,
3589        pub share_index_last_error: Option<String>,
3590        pub share_list_update_id: Option<String>,
3591        pub system_update_id: Option<u32>,
3592        pub user_radio_update_id: Option<String>,
3593    }
3594
3595    #[derive(FromXml, Debug, Clone, PartialEq)]
3596    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
3597    struct ContentDirectoryPropertySet {
3598        pub properties: Vec<ContentDirectoryProperty>,
3599    }
3600
3601    #[derive(FromXml, Debug, Clone, PartialEq)]
3602    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
3603    struct ContentDirectoryProperty {
3604        #[xml(rename = "Browseable", ns(""))]
3605        pub browseable: Option<bool>,
3606        #[xml(rename = "ContainerUpdateIDs", ns(""))]
3607        pub container_update_ids: Option<String>,
3608        #[xml(rename = "FavoritePresetsUpdateID", ns(""))]
3609        pub favorite_presets_update_id: Option<String>,
3610        #[xml(rename = "FavoritesUpdateID", ns(""))]
3611        pub favorites_update_id: Option<String>,
3612        #[xml(rename = "RadioFavoritesUpdateID", ns(""))]
3613        pub radio_favorites_update_id: Option<u32>,
3614        #[xml(rename = "RadioLocationUpdateID", ns(""))]
3615        pub radio_location_update_id: Option<u32>,
3616        #[xml(rename = "RecentlyPlayedUpdateID", ns(""))]
3617        pub recently_played_update_id: Option<String>,
3618        #[xml(rename = "SavedQueuesUpdateID", ns(""))]
3619        pub saved_queues_update_id: Option<String>,
3620        #[xml(rename = "ShareIndexInProgress", ns(""))]
3621        pub share_index_in_progress: Option<bool>,
3622        #[xml(rename = "ShareIndexLastError", ns(""))]
3623        pub share_index_last_error: Option<String>,
3624        #[xml(rename = "ShareListUpdateID", ns(""))]
3625        pub share_list_update_id: Option<String>,
3626        #[xml(rename = "SystemUpdateID", ns(""))]
3627        pub system_update_id: Option<u32>,
3628        #[xml(rename = "UserRadioUpdateID", ns(""))]
3629        pub user_radio_update_id: Option<String>,
3630    }
3631
3632    impl DecodeXml for ContentDirectoryEvent {
3633        fn decode_xml(xml: &str) -> crate::Result<Self> {
3634            let mut result = Self::default();
3635            let set: ContentDirectoryPropertySet = instant_xml::from_str(xml)?;
3636            for prop in set.properties {
3637                if let Some(v) = prop.browseable {
3638                    result.browseable.replace(v);
3639                }
3640
3641                if let Some(v) = prop.container_update_ids {
3642                    result.container_update_ids.replace(v);
3643                }
3644
3645                if let Some(v) = prop.favorite_presets_update_id {
3646                    result.favorite_presets_update_id.replace(v);
3647                }
3648
3649                if let Some(v) = prop.favorites_update_id {
3650                    result.favorites_update_id.replace(v);
3651                }
3652
3653                if let Some(v) = prop.radio_favorites_update_id {
3654                    result.radio_favorites_update_id.replace(v);
3655                }
3656
3657                if let Some(v) = prop.radio_location_update_id {
3658                    result.radio_location_update_id.replace(v);
3659                }
3660
3661                if let Some(v) = prop.recently_played_update_id {
3662                    result.recently_played_update_id.replace(v);
3663                }
3664
3665                if let Some(v) = prop.saved_queues_update_id {
3666                    result.saved_queues_update_id.replace(v);
3667                }
3668
3669                if let Some(v) = prop.share_index_in_progress {
3670                    result.share_index_in_progress.replace(v);
3671                }
3672
3673                if let Some(v) = prop.share_index_last_error {
3674                    result.share_index_last_error.replace(v);
3675                }
3676
3677                if let Some(v) = prop.share_list_update_id {
3678                    result.share_list_update_id.replace(v);
3679                }
3680
3681                if let Some(v) = prop.system_update_id {
3682                    result.system_update_id.replace(v);
3683                }
3684
3685                if let Some(v) = prop.user_radio_update_id {
3686                    result.user_radio_update_id.replace(v);
3687                }
3688            }
3689            Ok(result)
3690        }
3691    }
3692
3693    impl crate::SonosDevice {
3694        /// Subscribe to events from the `ContentDirectory` service on this device
3695        pub async fn subscribe_content_directory(
3696            &self,
3697        ) -> crate::Result<crate::upnp::EventStream<ContentDirectoryEvent>> {
3698            self.subscribe_helper(&SERVICE_TYPE).await
3699        }
3700    }
3701}
3702
3703#[derive(PartialEq, Debug, Clone, Eq, Default)]
3704pub enum BrowseFlag {
3705    #[default]
3706    BrowseMetadata,
3707    BrowseDirectChildren,
3708
3709    /// Allows passing a value that was not known at the
3710    /// time that this crate was generated from the available
3711    /// device descriptions
3712    Unspecified(String),
3713}
3714
3715impl ToString for BrowseFlag {
3716    fn to_string(&self) -> String {
3717        match self {
3718            BrowseFlag::BrowseMetadata => "BrowseMetadata".to_string(),
3719            BrowseFlag::BrowseDirectChildren => "BrowseDirectChildren".to_string(),
3720            BrowseFlag::Unspecified(s) => s.to_string(),
3721        }
3722    }
3723}
3724
3725impl FromStr for BrowseFlag {
3726    type Err = crate::Error;
3727    fn from_str(s: &str) -> Result<BrowseFlag> {
3728        match s {
3729            "BrowseMetadata" => Ok(BrowseFlag::BrowseMetadata),
3730            "BrowseDirectChildren" => Ok(BrowseFlag::BrowseDirectChildren),
3731            s => Ok(BrowseFlag::Unspecified(s.to_string())),
3732        }
3733    }
3734}
3735
3736impl instant_xml::ToXml for BrowseFlag {
3737    fn serialize<W: std::fmt::Write + ?Sized>(
3738        &self,
3739        field: Option<instant_xml::Id<'_>>,
3740        serializer: &mut instant_xml::Serializer<W>,
3741    ) -> std::result::Result<(), instant_xml::Error> {
3742        self.to_string().serialize(field, serializer)
3743    }
3744
3745    fn present(&self) -> bool {
3746        true
3747    }
3748}
3749
3750impl<'xml> instant_xml::FromXml<'xml> for BrowseFlag {
3751    #[inline]
3752    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
3753        match field {
3754            Some(field) => id == field,
3755            None => false,
3756        }
3757    }
3758
3759    fn deserialize<'cx>(
3760        into: &mut Self::Accumulator,
3761        field: &'static str,
3762        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
3763    ) -> std::result::Result<(), instant_xml::Error> {
3764        if into.is_some() {
3765            return Err(instant_xml::Error::DuplicateValue(field));
3766        }
3767
3768        match deserializer.take_str()? {
3769            Some(value) => {
3770                let parsed: BrowseFlag = value.parse().map_err(|err| {
3771                    instant_xml::Error::Other(format!(
3772                        "invalid value for field {field}: {value}: {err:#}"
3773                    ))
3774                })?;
3775                *into = Some(parsed);
3776                Ok(())
3777            }
3778            None => Err(instant_xml::Error::MissingValue(field)),
3779        }
3780    }
3781
3782    type Accumulator = Option<BrowseFlag>;
3783    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
3784}
3785
3786/// Request and Response types for the `DeviceProperties` service.
3787pub mod device_properties {
3788    use super::*;
3789
3790    /// URN for the `DeviceProperties` service.
3791    /// `urn:schemas-upnp-org:service:DeviceProperties:1`
3792    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:DeviceProperties:1";
3793
3794    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3795    #[xml(rename = "AddBondedZones", ns(SERVICE_TYPE))]
3796    pub struct AddBondedZonesRequest {
3797        #[xml(rename = "ChannelMapSet", ns(""))]
3798        pub channel_map_set: String,
3799    }
3800
3801    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3802    #[xml(rename = "AddHTSatellite", ns(SERVICE_TYPE))]
3803    pub struct AddHtSatelliteRequest {
3804        /// example: `RINCON_000PPP1400:LF,RF;RINCON_000RRR1400:RR;RINCON_000SSS1400:LR;RINCON_000QQQ1400:SW`
3805        #[xml(rename = "HTSatChanMapSet", ns(""))]
3806        pub ht_sat_chan_map_set: String,
3807    }
3808
3809    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3810    #[xml(rename = "CreateStereoPair", ns(SERVICE_TYPE))]
3811    pub struct CreateStereoPairRequest {
3812        /// example: `RINCON_B8E9375831C001400:LF,LF;RINCON_000E58FE3AEA01400:RF,RF`
3813        #[xml(rename = "ChannelMapSet", ns(""))]
3814        pub channel_map_set: String,
3815    }
3816
3817    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3818    #[xml(rename = "EnterConfigMode", ns(SERVICE_TYPE))]
3819    pub struct EnterConfigModeRequest {
3820        #[xml(rename = "Mode", ns(""))]
3821        pub mode: String,
3822        #[xml(rename = "Options", ns(""))]
3823        pub options: String,
3824    }
3825
3826    #[derive(FromXml, Debug, Clone, PartialEq)]
3827    #[xml(rename = "EnterConfigModeResponse", ns(SERVICE_TYPE))]
3828    pub struct EnterConfigModeResponse {
3829        #[xml(rename = "State", ns(""))]
3830        pub state: Option<String>,
3831    }
3832
3833    impl crate::DecodeSoapResponse for EnterConfigModeResponse {
3834        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3835            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3836            Ok(envelope.body.payload)
3837        }
3838    }
3839
3840    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3841    #[xml(rename = "ExitConfigMode", ns(SERVICE_TYPE))]
3842    pub struct ExitConfigModeRequest {
3843        #[xml(rename = "Options", ns(""))]
3844        pub options: String,
3845    }
3846
3847    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3848    #[xml(rename = "GetAutoplayLinkedZones", ns(SERVICE_TYPE))]
3849    pub struct GetAutoplayLinkedZonesRequest {
3850        #[xml(rename = "Source", ns(""))]
3851        pub source: String,
3852    }
3853
3854    #[derive(FromXml, Debug, Clone, PartialEq)]
3855    #[xml(rename = "GetAutoplayLinkedZonesResponse", ns(SERVICE_TYPE))]
3856    pub struct GetAutoplayLinkedZonesResponse {
3857        #[xml(rename = "IncludeLinkedZones", ns(""))]
3858        pub include_linked_zones: Option<bool>,
3859    }
3860
3861    impl crate::DecodeSoapResponse for GetAutoplayLinkedZonesResponse {
3862        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3863            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3864            Ok(envelope.body.payload)
3865        }
3866    }
3867
3868    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3869    #[xml(rename = "GetAutoplayRoomUUID", ns(SERVICE_TYPE))]
3870    pub struct GetAutoplayRoomUuidRequest {
3871        #[xml(rename = "Source", ns(""))]
3872        pub source: String,
3873    }
3874
3875    #[derive(FromXml, Debug, Clone, PartialEq)]
3876    #[xml(rename = "GetAutoplayRoomUUIDResponse", ns(SERVICE_TYPE))]
3877    pub struct GetAutoplayRoomUuidResponse {
3878        #[xml(rename = "RoomUUID", ns(""))]
3879        pub room_uuid: Option<String>,
3880    }
3881
3882    impl crate::DecodeSoapResponse for GetAutoplayRoomUuidResponse {
3883        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3884            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3885            Ok(envelope.body.payload)
3886        }
3887    }
3888
3889    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3890    #[xml(rename = "GetAutoplayVolume", ns(SERVICE_TYPE))]
3891    pub struct GetAutoplayVolumeRequest {
3892        #[xml(rename = "Source", ns(""))]
3893        pub source: String,
3894    }
3895
3896    #[derive(FromXml, Debug, Clone, PartialEq)]
3897    #[xml(rename = "GetAutoplayVolumeResponse", ns(SERVICE_TYPE))]
3898    pub struct GetAutoplayVolumeResponse {
3899        #[xml(rename = "CurrentVolume", ns(""))]
3900        pub current_volume: Option<u16>,
3901    }
3902
3903    impl crate::DecodeSoapResponse for GetAutoplayVolumeResponse {
3904        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3905            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3906            Ok(envelope.body.payload)
3907        }
3908    }
3909
3910    #[derive(FromXml, Debug, Clone, PartialEq)]
3911    #[xml(rename = "GetButtonLockStateResponse", ns(SERVICE_TYPE))]
3912    pub struct GetButtonLockStateResponse {
3913        #[xml(rename = "CurrentButtonLockState", ns(""))]
3914        pub current_button_lock_state: Option<super::ButtonLockState>,
3915    }
3916
3917    impl crate::DecodeSoapResponse for GetButtonLockStateResponse {
3918        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3919            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3920            Ok(envelope.body.payload)
3921        }
3922    }
3923
3924    #[derive(FromXml, Debug, Clone, PartialEq)]
3925    #[xml(rename = "GetButtonStateResponse", ns(SERVICE_TYPE))]
3926    pub struct GetButtonStateResponse {
3927        #[xml(rename = "State", ns(""))]
3928        pub state: Option<String>,
3929    }
3930
3931    impl crate::DecodeSoapResponse for GetButtonStateResponse {
3932        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3933            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3934            Ok(envelope.body.payload)
3935        }
3936    }
3937
3938    #[derive(FromXml, Debug, Clone, PartialEq)]
3939    #[xml(rename = "GetHTForwardStateResponse", ns(SERVICE_TYPE))]
3940    pub struct GetHtForwardStateResponse {
3941        #[xml(rename = "IsHTForwardEnabled", ns(""))]
3942        pub is_ht_forward_enabled: Option<bool>,
3943    }
3944
3945    impl crate::DecodeSoapResponse for GetHtForwardStateResponse {
3946        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3947            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3948            Ok(envelope.body.payload)
3949        }
3950    }
3951
3952    #[derive(FromXml, Debug, Clone, PartialEq)]
3953    #[xml(rename = "GetHouseholdIDResponse", ns(SERVICE_TYPE))]
3954    pub struct GetHouseholdIdResponse {
3955        #[xml(rename = "CurrentHouseholdID", ns(""))]
3956        pub current_household_id: Option<String>,
3957    }
3958
3959    impl crate::DecodeSoapResponse for GetHouseholdIdResponse {
3960        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3961            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3962            Ok(envelope.body.payload)
3963        }
3964    }
3965
3966    #[derive(FromXml, Debug, Clone, PartialEq)]
3967    #[xml(rename = "GetLEDStateResponse", ns(SERVICE_TYPE))]
3968    pub struct GetLedStateResponse {
3969        #[xml(rename = "CurrentLEDState", ns(""))]
3970        pub current_led_state: Option<super::LEDState>,
3971    }
3972
3973    impl crate::DecodeSoapResponse for GetLedStateResponse {
3974        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3975            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3976            Ok(envelope.body.payload)
3977        }
3978    }
3979
3980    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
3981    #[xml(rename = "GetUseAutoplayVolume", ns(SERVICE_TYPE))]
3982    pub struct GetUseAutoplayVolumeRequest {
3983        #[xml(rename = "Source", ns(""))]
3984        pub source: String,
3985    }
3986
3987    #[derive(FromXml, Debug, Clone, PartialEq)]
3988    #[xml(rename = "GetUseAutoplayVolumeResponse", ns(SERVICE_TYPE))]
3989    pub struct GetUseAutoplayVolumeResponse {
3990        #[xml(rename = "UseVolume", ns(""))]
3991        pub use_volume: Option<bool>,
3992    }
3993
3994    impl crate::DecodeSoapResponse for GetUseAutoplayVolumeResponse {
3995        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
3996            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
3997            Ok(envelope.body.payload)
3998        }
3999    }
4000
4001    #[derive(FromXml, Debug, Clone, PartialEq)]
4002    #[xml(rename = "GetZoneAttributesResponse", ns(SERVICE_TYPE))]
4003    pub struct GetZoneAttributesResponse {
4004        #[xml(rename = "CurrentZoneName", ns(""))]
4005        pub current_zone_name: Option<String>,
4006        #[xml(rename = "CurrentIcon", ns(""))]
4007        pub current_icon: Option<String>,
4008        #[xml(rename = "CurrentConfiguration", ns(""))]
4009        pub current_configuration: Option<String>,
4010        #[xml(rename = "CurrentTargetRoomName", ns(""))]
4011        pub current_target_room_name: Option<String>,
4012    }
4013
4014    impl crate::DecodeSoapResponse for GetZoneAttributesResponse {
4015        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4016            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4017            Ok(envelope.body.payload)
4018        }
4019    }
4020
4021    #[derive(FromXml, Debug, Clone, PartialEq)]
4022    #[xml(rename = "GetZoneInfoResponse", ns(SERVICE_TYPE))]
4023    pub struct GetZoneInfoResponse {
4024        #[xml(rename = "SerialNumber", ns(""))]
4025        pub serial_number: Option<String>,
4026        #[xml(rename = "SoftwareVersion", ns(""))]
4027        pub software_version: Option<String>,
4028        #[xml(rename = "DisplaySoftwareVersion", ns(""))]
4029        pub display_software_version: Option<String>,
4030        #[xml(rename = "HardwareVersion", ns(""))]
4031        pub hardware_version: Option<String>,
4032        #[xml(rename = "IPAddress", ns(""))]
4033        pub ip_address: Option<String>,
4034        #[xml(rename = "MACAddress", ns(""))]
4035        pub mac_address: Option<String>,
4036        #[xml(rename = "CopyrightInfo", ns(""))]
4037        pub copyright_info: Option<String>,
4038        #[xml(rename = "ExtraInfo", ns(""))]
4039        pub extra_info: Option<String>,
4040        #[xml(rename = "HTAudioIn", ns(""))]
4041        pub ht_audio_in: Option<u32>,
4042        #[xml(rename = "Flags", ns(""))]
4043        pub flags: Option<u32>,
4044    }
4045
4046    impl crate::DecodeSoapResponse for GetZoneInfoResponse {
4047        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4048            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4049            Ok(envelope.body.payload)
4050        }
4051    }
4052
4053    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4054    #[xml(rename = "RemoveBondedZones", ns(SERVICE_TYPE))]
4055    pub struct RemoveBondedZonesRequest {
4056        #[xml(rename = "ChannelMapSet", ns(""))]
4057        pub channel_map_set: String,
4058        #[xml(rename = "KeepGrouped", ns(""))]
4059        pub keep_grouped: bool,
4060    }
4061
4062    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4063    #[xml(rename = "RemoveHTSatellite", ns(SERVICE_TYPE))]
4064    pub struct RemoveHtSatelliteRequest {
4065        /// example: `RINCON_000RRR1400`
4066        #[xml(rename = "SatRoomUUID", ns(""))]
4067        pub sat_room_uuid: String,
4068    }
4069
4070    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4071    #[xml(rename = "RoomDetectionStartChirping", ns(SERVICE_TYPE))]
4072    pub struct RoomDetectionStartChirpingRequest {
4073        #[xml(rename = "Channel", ns(""))]
4074        pub channel: u16,
4075        #[xml(rename = "DurationMilliseconds", ns(""))]
4076        pub duration_milliseconds: u32,
4077        #[xml(rename = "ChirpIfPlayingSwappableAudio", ns(""))]
4078        pub chirp_if_playing_swappable_audio: bool,
4079    }
4080
4081    #[derive(FromXml, Debug, Clone, PartialEq)]
4082    #[xml(rename = "RoomDetectionStartChirpingResponse", ns(SERVICE_TYPE))]
4083    pub struct RoomDetectionStartChirpingResponse {
4084        #[xml(rename = "PlayId", ns(""))]
4085        pub play_id: Option<u32>,
4086        #[xml(rename = "ChirpIfPlayingSwappableAudio", ns(""))]
4087        pub chirp_if_playing_swappable_audio: Option<bool>,
4088    }
4089
4090    impl crate::DecodeSoapResponse for RoomDetectionStartChirpingResponse {
4091        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4092            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4093            Ok(envelope.body.payload)
4094        }
4095    }
4096
4097    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4098    #[xml(rename = "RoomDetectionStopChirping", ns(SERVICE_TYPE))]
4099    pub struct RoomDetectionStopChirpingRequest {
4100        #[xml(rename = "PlayId", ns(""))]
4101        pub play_id: u32,
4102    }
4103
4104    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4105    #[xml(rename = "SeparateStereoPair", ns(SERVICE_TYPE))]
4106    pub struct SeparateStereoPairRequest {
4107        /// example: `RINCON_B8E9375831C001400:LF,LF;RINCON_000E58FE3AEA01400:RF,RF`
4108        #[xml(rename = "ChannelMapSet", ns(""))]
4109        pub channel_map_set: String,
4110    }
4111
4112    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4113    #[xml(rename = "SetAutoplayLinkedZones", ns(SERVICE_TYPE))]
4114    pub struct SetAutoplayLinkedZonesRequest {
4115        #[xml(rename = "IncludeLinkedZones", ns(""))]
4116        pub include_linked_zones: bool,
4117        #[xml(rename = "Source", ns(""))]
4118        pub source: String,
4119    }
4120
4121    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4122    #[xml(rename = "SetAutoplayRoomUUID", ns(SERVICE_TYPE))]
4123    pub struct SetAutoplayRoomUuidRequest {
4124        #[xml(rename = "RoomUUID", ns(""))]
4125        pub room_uuid: String,
4126        #[xml(rename = "Source", ns(""))]
4127        pub source: String,
4128    }
4129
4130    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4131    #[xml(rename = "SetAutoplayVolume", ns(SERVICE_TYPE))]
4132    pub struct SetAutoplayVolumeRequest {
4133        #[xml(rename = "Volume", ns(""))]
4134        pub volume: u16,
4135        #[xml(rename = "Source", ns(""))]
4136        pub source: String,
4137    }
4138
4139    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4140    #[xml(rename = "SetButtonLockState", ns(SERVICE_TYPE))]
4141    pub struct SetButtonLockStateRequest {
4142        #[xml(rename = "DesiredButtonLockState", ns(""))]
4143        pub desired_button_lock_state: super::ButtonLockState,
4144    }
4145
4146    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4147    #[xml(rename = "SetLEDState", ns(SERVICE_TYPE))]
4148    pub struct SetLedStateRequest {
4149        #[xml(rename = "DesiredLEDState", ns(""))]
4150        pub desired_led_state: super::LEDState,
4151    }
4152
4153    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4154    #[xml(rename = "SetUseAutoplayVolume", ns(SERVICE_TYPE))]
4155    pub struct SetUseAutoplayVolumeRequest {
4156        #[xml(rename = "UseVolume", ns(""))]
4157        pub use_volume: bool,
4158        #[xml(rename = "Source", ns(""))]
4159        pub source: String,
4160    }
4161
4162    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4163    #[xml(rename = "SetZoneAttributes", ns(SERVICE_TYPE))]
4164    pub struct SetZoneAttributesRequest {
4165        #[xml(rename = "DesiredZoneName", ns(""))]
4166        pub desired_zone_name: String,
4167        #[xml(rename = "DesiredIcon", ns(""))]
4168        pub desired_icon: String,
4169        #[xml(rename = "DesiredConfiguration", ns(""))]
4170        pub desired_configuration: String,
4171        #[xml(rename = "DesiredTargetRoomName", ns(""))]
4172        pub desired_target_room_name: String,
4173    }
4174
4175    /// A parsed event produced by the `DeviceProperties` service.
4176    /// Use `SonosDevice::subscribe_device_properties()` to obtain an event
4177    /// stream that produces these.
4178    #[derive(Debug, Clone, PartialEq, Default)]
4179    pub struct DevicePropertiesEvent {
4180        pub air_play_enabled: Option<bool>,
4181        pub available_room_calibration: Option<String>,
4182        pub behind_wifi_extender: Option<u32>,
4183        pub channel_freq: Option<u32>,
4184        pub channel_map_set: Option<String>,
4185        pub config_mode: Option<String>,
4186        pub configuration: Option<String>,
4187        pub eth_link: Option<bool>,
4188        pub ht_bonded_zone_commit_state: Option<u32>,
4189        pub ht_freq: Option<u32>,
4190        pub ht_sat_chan_map_set: Option<String>,
4191        pub has_configured_ssid: Option<bool>,
4192        pub hdmi_cec_available: Option<bool>,
4193        pub icon: Option<String>,
4194        pub invisible: Option<bool>,
4195        pub is_idle: Option<bool>,
4196        pub is_zone_bridge: Option<bool>,
4197        pub last_changed_play_state: Option<String>,
4198        pub mic_enabled: Option<u32>,
4199        pub more_info: Option<String>,
4200        pub orientation: Option<i32>,
4201        pub room_calibration_state: Option<i32>,
4202        pub secure_reg_state: Option<u32>,
4203        pub settings_replication_state: Option<String>,
4204        pub supports_audio_clip: Option<bool>,
4205        pub supports_audio_in: Option<bool>,
4206        pub tv_configuration_error: Option<bool>,
4207        pub voice_config_state: Option<u32>,
4208        pub wifi_enabled: Option<bool>,
4209        pub wireless_leaf_only: Option<bool>,
4210        pub wireless_mode: Option<u32>,
4211        pub zone_name: Option<String>,
4212    }
4213
4214    #[derive(FromXml, Debug, Clone, PartialEq)]
4215    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4216    struct DevicePropertiesPropertySet {
4217        pub properties: Vec<DevicePropertiesProperty>,
4218    }
4219
4220    #[derive(FromXml, Debug, Clone, PartialEq)]
4221    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4222    struct DevicePropertiesProperty {
4223        #[xml(rename = "AirPlayEnabled", ns(""))]
4224        pub air_play_enabled: Option<bool>,
4225        #[xml(rename = "AvailableRoomCalibration", ns(""))]
4226        pub available_room_calibration: Option<String>,
4227        #[xml(rename = "BehindWifiExtender", ns(""))]
4228        pub behind_wifi_extender: Option<u32>,
4229        #[xml(rename = "ChannelFreq", ns(""))]
4230        pub channel_freq: Option<u32>,
4231        #[xml(rename = "ChannelMapSet", ns(""))]
4232        pub channel_map_set: Option<String>,
4233        #[xml(rename = "ConfigMode", ns(""))]
4234        pub config_mode: Option<String>,
4235        #[xml(rename = "Configuration", ns(""))]
4236        pub configuration: Option<String>,
4237        #[xml(rename = "EthLink", ns(""))]
4238        pub eth_link: Option<bool>,
4239        #[xml(rename = "HTBondedZoneCommitState", ns(""))]
4240        pub ht_bonded_zone_commit_state: Option<u32>,
4241        #[xml(rename = "HTFreq", ns(""))]
4242        pub ht_freq: Option<u32>,
4243        #[xml(rename = "HTSatChanMapSet", ns(""))]
4244        pub ht_sat_chan_map_set: Option<String>,
4245        #[xml(rename = "HasConfiguredSSID", ns(""))]
4246        pub has_configured_ssid: Option<bool>,
4247        #[xml(rename = "HdmiCecAvailable", ns(""))]
4248        pub hdmi_cec_available: Option<bool>,
4249        #[xml(rename = "Icon", ns(""))]
4250        pub icon: Option<String>,
4251        #[xml(rename = "Invisible", ns(""))]
4252        pub invisible: Option<bool>,
4253        #[xml(rename = "IsIdle", ns(""))]
4254        pub is_idle: Option<bool>,
4255        #[xml(rename = "IsZoneBridge", ns(""))]
4256        pub is_zone_bridge: Option<bool>,
4257        #[xml(rename = "LastChangedPlayState", ns(""))]
4258        pub last_changed_play_state: Option<String>,
4259        #[xml(rename = "MicEnabled", ns(""))]
4260        pub mic_enabled: Option<u32>,
4261        #[xml(rename = "MoreInfo", ns(""))]
4262        pub more_info: Option<String>,
4263        #[xml(rename = "Orientation", ns(""))]
4264        pub orientation: Option<i32>,
4265        #[xml(rename = "RoomCalibrationState", ns(""))]
4266        pub room_calibration_state: Option<i32>,
4267        #[xml(rename = "SecureRegState", ns(""))]
4268        pub secure_reg_state: Option<u32>,
4269        #[xml(rename = "SettingsReplicationState", ns(""))]
4270        pub settings_replication_state: Option<String>,
4271        #[xml(rename = "SupportsAudioClip", ns(""))]
4272        pub supports_audio_clip: Option<bool>,
4273        #[xml(rename = "SupportsAudioIn", ns(""))]
4274        pub supports_audio_in: Option<bool>,
4275        #[xml(rename = "TVConfigurationError", ns(""))]
4276        pub tv_configuration_error: Option<bool>,
4277        #[xml(rename = "VoiceConfigState", ns(""))]
4278        pub voice_config_state: Option<u32>,
4279        #[xml(rename = "WifiEnabled", ns(""))]
4280        pub wifi_enabled: Option<bool>,
4281        #[xml(rename = "WirelessLeafOnly", ns(""))]
4282        pub wireless_leaf_only: Option<bool>,
4283        #[xml(rename = "WirelessMode", ns(""))]
4284        pub wireless_mode: Option<u32>,
4285        #[xml(rename = "ZoneName", ns(""))]
4286        pub zone_name: Option<String>,
4287    }
4288
4289    impl DecodeXml for DevicePropertiesEvent {
4290        fn decode_xml(xml: &str) -> crate::Result<Self> {
4291            let mut result = Self::default();
4292            let set: DevicePropertiesPropertySet = instant_xml::from_str(xml)?;
4293            for prop in set.properties {
4294                if let Some(v) = prop.air_play_enabled {
4295                    result.air_play_enabled.replace(v);
4296                }
4297
4298                if let Some(v) = prop.available_room_calibration {
4299                    result.available_room_calibration.replace(v);
4300                }
4301
4302                if let Some(v) = prop.behind_wifi_extender {
4303                    result.behind_wifi_extender.replace(v);
4304                }
4305
4306                if let Some(v) = prop.channel_freq {
4307                    result.channel_freq.replace(v);
4308                }
4309
4310                if let Some(v) = prop.channel_map_set {
4311                    result.channel_map_set.replace(v);
4312                }
4313
4314                if let Some(v) = prop.config_mode {
4315                    result.config_mode.replace(v);
4316                }
4317
4318                if let Some(v) = prop.configuration {
4319                    result.configuration.replace(v);
4320                }
4321
4322                if let Some(v) = prop.eth_link {
4323                    result.eth_link.replace(v);
4324                }
4325
4326                if let Some(v) = prop.ht_bonded_zone_commit_state {
4327                    result.ht_bonded_zone_commit_state.replace(v);
4328                }
4329
4330                if let Some(v) = prop.ht_freq {
4331                    result.ht_freq.replace(v);
4332                }
4333
4334                if let Some(v) = prop.ht_sat_chan_map_set {
4335                    result.ht_sat_chan_map_set.replace(v);
4336                }
4337
4338                if let Some(v) = prop.has_configured_ssid {
4339                    result.has_configured_ssid.replace(v);
4340                }
4341
4342                if let Some(v) = prop.hdmi_cec_available {
4343                    result.hdmi_cec_available.replace(v);
4344                }
4345
4346                if let Some(v) = prop.icon {
4347                    result.icon.replace(v);
4348                }
4349
4350                if let Some(v) = prop.invisible {
4351                    result.invisible.replace(v);
4352                }
4353
4354                if let Some(v) = prop.is_idle {
4355                    result.is_idle.replace(v);
4356                }
4357
4358                if let Some(v) = prop.is_zone_bridge {
4359                    result.is_zone_bridge.replace(v);
4360                }
4361
4362                if let Some(v) = prop.last_changed_play_state {
4363                    result.last_changed_play_state.replace(v);
4364                }
4365
4366                if let Some(v) = prop.mic_enabled {
4367                    result.mic_enabled.replace(v);
4368                }
4369
4370                if let Some(v) = prop.more_info {
4371                    result.more_info.replace(v);
4372                }
4373
4374                if let Some(v) = prop.orientation {
4375                    result.orientation.replace(v);
4376                }
4377
4378                if let Some(v) = prop.room_calibration_state {
4379                    result.room_calibration_state.replace(v);
4380                }
4381
4382                if let Some(v) = prop.secure_reg_state {
4383                    result.secure_reg_state.replace(v);
4384                }
4385
4386                if let Some(v) = prop.settings_replication_state {
4387                    result.settings_replication_state.replace(v);
4388                }
4389
4390                if let Some(v) = prop.supports_audio_clip {
4391                    result.supports_audio_clip.replace(v);
4392                }
4393
4394                if let Some(v) = prop.supports_audio_in {
4395                    result.supports_audio_in.replace(v);
4396                }
4397
4398                if let Some(v) = prop.tv_configuration_error {
4399                    result.tv_configuration_error.replace(v);
4400                }
4401
4402                if let Some(v) = prop.voice_config_state {
4403                    result.voice_config_state.replace(v);
4404                }
4405
4406                if let Some(v) = prop.wifi_enabled {
4407                    result.wifi_enabled.replace(v);
4408                }
4409
4410                if let Some(v) = prop.wireless_leaf_only {
4411                    result.wireless_leaf_only.replace(v);
4412                }
4413
4414                if let Some(v) = prop.wireless_mode {
4415                    result.wireless_mode.replace(v);
4416                }
4417
4418                if let Some(v) = prop.zone_name {
4419                    result.zone_name.replace(v);
4420                }
4421            }
4422            Ok(result)
4423        }
4424    }
4425
4426    impl crate::SonosDevice {
4427        /// Subscribe to events from the `DeviceProperties` service on this device
4428        pub async fn subscribe_device_properties(
4429            &self,
4430        ) -> crate::Result<crate::upnp::EventStream<DevicePropertiesEvent>> {
4431            self.subscribe_helper(&SERVICE_TYPE).await
4432        }
4433    }
4434}
4435
4436#[derive(PartialEq, Debug, Clone, Eq, Default)]
4437pub enum ButtonLockState {
4438    #[default]
4439    On,
4440    Off,
4441
4442    /// Allows passing a value that was not known at the
4443    /// time that this crate was generated from the available
4444    /// device descriptions
4445    Unspecified(String),
4446}
4447
4448impl ToString for ButtonLockState {
4449    fn to_string(&self) -> String {
4450        match self {
4451            ButtonLockState::On => "On".to_string(),
4452            ButtonLockState::Off => "Off".to_string(),
4453            ButtonLockState::Unspecified(s) => s.to_string(),
4454        }
4455    }
4456}
4457
4458impl FromStr for ButtonLockState {
4459    type Err = crate::Error;
4460    fn from_str(s: &str) -> Result<ButtonLockState> {
4461        match s {
4462            "On" => Ok(ButtonLockState::On),
4463            "Off" => Ok(ButtonLockState::Off),
4464            s => Ok(ButtonLockState::Unspecified(s.to_string())),
4465        }
4466    }
4467}
4468
4469impl instant_xml::ToXml for ButtonLockState {
4470    fn serialize<W: std::fmt::Write + ?Sized>(
4471        &self,
4472        field: Option<instant_xml::Id<'_>>,
4473        serializer: &mut instant_xml::Serializer<W>,
4474    ) -> std::result::Result<(), instant_xml::Error> {
4475        self.to_string().serialize(field, serializer)
4476    }
4477
4478    fn present(&self) -> bool {
4479        true
4480    }
4481}
4482
4483impl<'xml> instant_xml::FromXml<'xml> for ButtonLockState {
4484    #[inline]
4485    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
4486        match field {
4487            Some(field) => id == field,
4488            None => false,
4489        }
4490    }
4491
4492    fn deserialize<'cx>(
4493        into: &mut Self::Accumulator,
4494        field: &'static str,
4495        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
4496    ) -> std::result::Result<(), instant_xml::Error> {
4497        if into.is_some() {
4498            return Err(instant_xml::Error::DuplicateValue(field));
4499        }
4500
4501        match deserializer.take_str()? {
4502            Some(value) => {
4503                let parsed: ButtonLockState = value.parse().map_err(|err| {
4504                    instant_xml::Error::Other(format!(
4505                        "invalid value for field {field}: {value}: {err:#}"
4506                    ))
4507                })?;
4508                *into = Some(parsed);
4509                Ok(())
4510            }
4511            None => Err(instant_xml::Error::MissingValue(field)),
4512        }
4513    }
4514
4515    type Accumulator = Option<ButtonLockState>;
4516    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
4517}
4518
4519#[derive(PartialEq, Debug, Clone, Eq, Default)]
4520pub enum LEDState {
4521    #[default]
4522    On,
4523    Off,
4524
4525    /// Allows passing a value that was not known at the
4526    /// time that this crate was generated from the available
4527    /// device descriptions
4528    Unspecified(String),
4529}
4530
4531impl ToString for LEDState {
4532    fn to_string(&self) -> String {
4533        match self {
4534            LEDState::On => "On".to_string(),
4535            LEDState::Off => "Off".to_string(),
4536            LEDState::Unspecified(s) => s.to_string(),
4537        }
4538    }
4539}
4540
4541impl FromStr for LEDState {
4542    type Err = crate::Error;
4543    fn from_str(s: &str) -> Result<LEDState> {
4544        match s {
4545            "On" => Ok(LEDState::On),
4546            "Off" => Ok(LEDState::Off),
4547            s => Ok(LEDState::Unspecified(s.to_string())),
4548        }
4549    }
4550}
4551
4552impl instant_xml::ToXml for LEDState {
4553    fn serialize<W: std::fmt::Write + ?Sized>(
4554        &self,
4555        field: Option<instant_xml::Id<'_>>,
4556        serializer: &mut instant_xml::Serializer<W>,
4557    ) -> std::result::Result<(), instant_xml::Error> {
4558        self.to_string().serialize(field, serializer)
4559    }
4560
4561    fn present(&self) -> bool {
4562        true
4563    }
4564}
4565
4566impl<'xml> instant_xml::FromXml<'xml> for LEDState {
4567    #[inline]
4568    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
4569        match field {
4570            Some(field) => id == field,
4571            None => false,
4572        }
4573    }
4574
4575    fn deserialize<'cx>(
4576        into: &mut Self::Accumulator,
4577        field: &'static str,
4578        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
4579    ) -> std::result::Result<(), instant_xml::Error> {
4580        if into.is_some() {
4581            return Err(instant_xml::Error::DuplicateValue(field));
4582        }
4583
4584        match deserializer.take_str()? {
4585            Some(value) => {
4586                let parsed: LEDState = value.parse().map_err(|err| {
4587                    instant_xml::Error::Other(format!(
4588                        "invalid value for field {field}: {value}: {err:#}"
4589                    ))
4590                })?;
4591                *into = Some(parsed);
4592                Ok(())
4593            }
4594            None => Err(instant_xml::Error::MissingValue(field)),
4595        }
4596    }
4597
4598    type Accumulator = Option<LEDState>;
4599    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
4600}
4601
4602/// Request and Response types for the `GroupManagement` service.
4603pub mod group_management {
4604    use super::*;
4605
4606    /// URN for the `GroupManagement` service.
4607    /// `urn:schemas-upnp-org:service:GroupManagement:1`
4608    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:GroupManagement:1";
4609
4610    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4611    #[xml(rename = "AddMember", ns(SERVICE_TYPE))]
4612    pub struct AddMemberRequest {
4613        #[xml(rename = "MemberID", ns(""))]
4614        pub member_id: String,
4615        #[xml(rename = "BootSeq", ns(""))]
4616        pub boot_seq: u32,
4617    }
4618
4619    #[derive(FromXml, Debug, Clone, PartialEq)]
4620    #[xml(rename = "AddMemberResponse", ns(SERVICE_TYPE))]
4621    pub struct AddMemberResponse {
4622        #[xml(rename = "CurrentTransportSettings", ns(""))]
4623        pub current_transport_settings: Option<String>,
4624        #[xml(rename = "CurrentURI", ns(""))]
4625        pub current_uri: Option<String>,
4626        #[xml(rename = "GroupUUIDJoined", ns(""))]
4627        pub group_uuid_joined: Option<String>,
4628        #[xml(rename = "ResetVolumeAfter", ns(""))]
4629        pub reset_volume_after: Option<bool>,
4630        #[xml(rename = "VolumeAVTransportURI", ns(""))]
4631        pub volume_av_transport_uri: Option<String>,
4632    }
4633
4634    impl crate::DecodeSoapResponse for AddMemberResponse {
4635        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4636            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4637            Ok(envelope.body.payload)
4638        }
4639    }
4640
4641    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4642    #[xml(rename = "RemoveMember", ns(SERVICE_TYPE))]
4643    pub struct RemoveMemberRequest {
4644        #[xml(rename = "MemberID", ns(""))]
4645        pub member_id: String,
4646    }
4647
4648    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4649    #[xml(rename = "ReportTrackBufferingResult", ns(SERVICE_TYPE))]
4650    pub struct ReportTrackBufferingResultRequest {
4651        #[xml(rename = "MemberID", ns(""))]
4652        pub member_id: String,
4653        #[xml(rename = "ResultCode", ns(""))]
4654        pub result_code: i32,
4655    }
4656
4657    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4658    #[xml(rename = "SetSourceAreaIds", ns(SERVICE_TYPE))]
4659    pub struct SetSourceAreaIdsRequest {
4660        #[xml(rename = "DesiredSourceAreaIds", ns(""))]
4661        pub desired_source_area_ids: String,
4662    }
4663
4664    /// A parsed event produced by the `GroupManagement` service.
4665    /// Use `SonosDevice::subscribe_group_management()` to obtain an event
4666    /// stream that produces these.
4667    #[derive(Debug, Clone, PartialEq, Default)]
4668    pub struct GroupManagementEvent {
4669        pub group_coordinator_is_local: Option<bool>,
4670        pub local_group_uuid: Option<String>,
4671        pub reset_volume_after: Option<bool>,
4672        pub virtual_line_in_group_id: Option<String>,
4673        pub volume_av_transport_uri: Option<String>,
4674    }
4675
4676    #[derive(FromXml, Debug, Clone, PartialEq)]
4677    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4678    struct GroupManagementPropertySet {
4679        pub properties: Vec<GroupManagementProperty>,
4680    }
4681
4682    #[derive(FromXml, Debug, Clone, PartialEq)]
4683    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4684    struct GroupManagementProperty {
4685        #[xml(rename = "GroupCoordinatorIsLocal", ns(""))]
4686        pub group_coordinator_is_local: Option<bool>,
4687        #[xml(rename = "LocalGroupUUID", ns(""))]
4688        pub local_group_uuid: Option<String>,
4689        #[xml(rename = "ResetVolumeAfter", ns(""))]
4690        pub reset_volume_after: Option<bool>,
4691        #[xml(rename = "VirtualLineInGroupID", ns(""))]
4692        pub virtual_line_in_group_id: Option<String>,
4693        #[xml(rename = "VolumeAVTransportURI", ns(""))]
4694        pub volume_av_transport_uri: Option<String>,
4695    }
4696
4697    impl DecodeXml for GroupManagementEvent {
4698        fn decode_xml(xml: &str) -> crate::Result<Self> {
4699            let mut result = Self::default();
4700            let set: GroupManagementPropertySet = instant_xml::from_str(xml)?;
4701            for prop in set.properties {
4702                if let Some(v) = prop.group_coordinator_is_local {
4703                    result.group_coordinator_is_local.replace(v);
4704                }
4705
4706                if let Some(v) = prop.local_group_uuid {
4707                    result.local_group_uuid.replace(v);
4708                }
4709
4710                if let Some(v) = prop.reset_volume_after {
4711                    result.reset_volume_after.replace(v);
4712                }
4713
4714                if let Some(v) = prop.virtual_line_in_group_id {
4715                    result.virtual_line_in_group_id.replace(v);
4716                }
4717
4718                if let Some(v) = prop.volume_av_transport_uri {
4719                    result.volume_av_transport_uri.replace(v);
4720                }
4721            }
4722            Ok(result)
4723        }
4724    }
4725
4726    impl crate::SonosDevice {
4727        /// Subscribe to events from the `GroupManagement` service on this device
4728        pub async fn subscribe_group_management(
4729            &self,
4730        ) -> crate::Result<crate::upnp::EventStream<GroupManagementEvent>> {
4731            self.subscribe_helper(&SERVICE_TYPE).await
4732        }
4733    }
4734}
4735
4736/// Request and Response types for the `GroupRenderingControl` service.
4737pub mod group_rendering_control {
4738    use super::*;
4739
4740    /// URN for the `GroupRenderingControl` service.
4741    /// `urn:schemas-upnp-org:service:GroupRenderingControl:1`
4742    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:GroupRenderingControl:1";
4743
4744    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4745    #[xml(rename = "GetGroupMute", ns(SERVICE_TYPE))]
4746    pub struct GetGroupMuteRequest {
4747        #[xml(rename = "InstanceID", ns(""))]
4748        pub instance_id: u32,
4749    }
4750
4751    #[derive(FromXml, Debug, Clone, PartialEq)]
4752    #[xml(rename = "GetGroupMuteResponse", ns(SERVICE_TYPE))]
4753    pub struct GetGroupMuteResponse {
4754        #[xml(rename = "CurrentMute", ns(""))]
4755        pub current_mute: Option<bool>,
4756    }
4757
4758    impl crate::DecodeSoapResponse for GetGroupMuteResponse {
4759        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4760            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4761            Ok(envelope.body.payload)
4762        }
4763    }
4764
4765    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4766    #[xml(rename = "GetGroupVolume", ns(SERVICE_TYPE))]
4767    pub struct GetGroupVolumeRequest {
4768        #[xml(rename = "InstanceID", ns(""))]
4769        pub instance_id: u32,
4770    }
4771
4772    #[derive(FromXml, Debug, Clone, PartialEq)]
4773    #[xml(rename = "GetGroupVolumeResponse", ns(SERVICE_TYPE))]
4774    pub struct GetGroupVolumeResponse {
4775        #[xml(rename = "CurrentVolume", ns(""))]
4776        pub current_volume: Option<u16>,
4777    }
4778
4779    impl crate::DecodeSoapResponse for GetGroupVolumeResponse {
4780        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4781            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4782            Ok(envelope.body.payload)
4783        }
4784    }
4785
4786    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4787    #[xml(rename = "SetGroupMute", ns(SERVICE_TYPE))]
4788    pub struct SetGroupMuteRequest {
4789        #[xml(rename = "InstanceID", ns(""))]
4790        pub instance_id: u32,
4791        #[xml(rename = "DesiredMute", ns(""))]
4792        pub desired_mute: bool,
4793    }
4794
4795    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4796    #[xml(rename = "SetGroupVolume", ns(SERVICE_TYPE))]
4797    pub struct SetGroupVolumeRequest {
4798        #[xml(rename = "InstanceID", ns(""))]
4799        pub instance_id: u32,
4800        /// New volume between 0 and 100
4801        #[xml(rename = "DesiredVolume", ns(""))]
4802        pub desired_volume: u16,
4803    }
4804
4805    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4806    #[xml(rename = "SetRelativeGroupVolume", ns(SERVICE_TYPE))]
4807    pub struct SetRelativeGroupVolumeRequest {
4808        #[xml(rename = "InstanceID", ns(""))]
4809        pub instance_id: u32,
4810        /// Number between -100 and +100
4811        #[xml(rename = "Adjustment", ns(""))]
4812        pub adjustment: i32,
4813    }
4814
4815    #[derive(FromXml, Debug, Clone, PartialEq)]
4816    #[xml(rename = "SetRelativeGroupVolumeResponse", ns(SERVICE_TYPE))]
4817    pub struct SetRelativeGroupVolumeResponse {
4818        #[xml(rename = "NewVolume", ns(""))]
4819        pub new_volume: Option<u16>,
4820    }
4821
4822    impl crate::DecodeSoapResponse for SetRelativeGroupVolumeResponse {
4823        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4824            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4825            Ok(envelope.body.payload)
4826        }
4827    }
4828
4829    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4830    #[xml(rename = "SnapshotGroupVolume", ns(SERVICE_TYPE))]
4831    pub struct SnapshotGroupVolumeRequest {
4832        #[xml(rename = "InstanceID", ns(""))]
4833        pub instance_id: u32,
4834    }
4835
4836    /// A parsed event produced by the `GroupRenderingControl` service.
4837    /// Use `SonosDevice::subscribe_group_rendering_control()` to obtain an event
4838    /// stream that produces these.
4839    #[derive(Debug, Clone, PartialEq, Default)]
4840    pub struct GroupRenderingControlEvent {
4841        pub group_mute: Option<bool>,
4842        pub group_volume: Option<u16>,
4843        pub group_volume_changeable: Option<bool>,
4844    }
4845
4846    #[derive(FromXml, Debug, Clone, PartialEq)]
4847    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4848    struct GroupRenderingControlPropertySet {
4849        pub properties: Vec<GroupRenderingControlProperty>,
4850    }
4851
4852    #[derive(FromXml, Debug, Clone, PartialEq)]
4853    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4854    struct GroupRenderingControlProperty {
4855        #[xml(rename = "GroupMute", ns(""))]
4856        pub group_mute: Option<bool>,
4857        #[xml(rename = "GroupVolume", ns(""))]
4858        pub group_volume: Option<u16>,
4859        #[xml(rename = "GroupVolumeChangeable", ns(""))]
4860        pub group_volume_changeable: Option<bool>,
4861    }
4862
4863    impl DecodeXml for GroupRenderingControlEvent {
4864        fn decode_xml(xml: &str) -> crate::Result<Self> {
4865            let mut result = Self::default();
4866            let set: GroupRenderingControlPropertySet = instant_xml::from_str(xml)?;
4867            for prop in set.properties {
4868                if let Some(v) = prop.group_mute {
4869                    result.group_mute.replace(v);
4870                }
4871
4872                if let Some(v) = prop.group_volume {
4873                    result.group_volume.replace(v);
4874                }
4875
4876                if let Some(v) = prop.group_volume_changeable {
4877                    result.group_volume_changeable.replace(v);
4878                }
4879            }
4880            Ok(result)
4881        }
4882    }
4883
4884    impl crate::SonosDevice {
4885        /// Subscribe to events from the `GroupRenderingControl` service on this device
4886        pub async fn subscribe_group_rendering_control(
4887            &self,
4888        ) -> crate::Result<crate::upnp::EventStream<GroupRenderingControlEvent>> {
4889            self.subscribe_helper(&SERVICE_TYPE).await
4890        }
4891    }
4892}
4893
4894/// Request and Response types for the `HTControl` service.
4895pub mod ht_control {
4896    use super::*;
4897
4898    /// URN for the `HTControl` service.
4899    /// `urn:schemas-upnp-org:service:HTControl:1`
4900    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:HTControl:1";
4901
4902    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4903    #[xml(rename = "CommitLearnedIRCodes", ns(SERVICE_TYPE))]
4904    pub struct CommitLearnedIrCodesRequest {
4905        #[xml(rename = "Name", ns(""))]
4906        pub name: String,
4907    }
4908
4909    #[derive(FromXml, Debug, Clone, PartialEq)]
4910    #[xml(rename = "GetIRRepeaterStateResponse", ns(SERVICE_TYPE))]
4911    pub struct GetIrRepeaterStateResponse {
4912        #[xml(rename = "CurrentIRRepeaterState", ns(""))]
4913        pub current_ir_repeater_state: Option<super::IRRepeaterState>,
4914    }
4915
4916    impl crate::DecodeSoapResponse for GetIrRepeaterStateResponse {
4917        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4918            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4919            Ok(envelope.body.payload)
4920        }
4921    }
4922
4923    #[derive(FromXml, Debug, Clone, PartialEq)]
4924    #[xml(rename = "GetLEDFeedbackStateResponse", ns(SERVICE_TYPE))]
4925    pub struct GetLedFeedbackStateResponse {
4926        #[xml(rename = "LEDFeedbackState", ns(""))]
4927        pub led_feedback_state: Option<super::LEDFeedbackState>,
4928    }
4929
4930    impl crate::DecodeSoapResponse for GetLedFeedbackStateResponse {
4931        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4932            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4933            Ok(envelope.body.payload)
4934        }
4935    }
4936
4937    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4938    #[xml(rename = "IdentifyIRRemote", ns(SERVICE_TYPE))]
4939    pub struct IdentifyIrRemoteRequest {
4940        #[xml(rename = "Timeout", ns(""))]
4941        pub timeout: u32,
4942    }
4943
4944    #[derive(FromXml, Debug, Clone, PartialEq)]
4945    #[xml(rename = "IsRemoteConfiguredResponse", ns(SERVICE_TYPE))]
4946    pub struct IsRemoteConfiguredResponse {
4947        #[xml(rename = "RemoteConfigured", ns(""))]
4948        pub remote_configured: Option<bool>,
4949    }
4950
4951    impl crate::DecodeSoapResponse for IsRemoteConfiguredResponse {
4952        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
4953            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
4954            Ok(envelope.body.payload)
4955        }
4956    }
4957
4958    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4959    #[xml(rename = "LearnIRCode", ns(SERVICE_TYPE))]
4960    pub struct LearnIrCodeRequest {
4961        #[xml(rename = "IRCode", ns(""))]
4962        pub ir_code: String,
4963        #[xml(rename = "Timeout", ns(""))]
4964        pub timeout: u32,
4965    }
4966
4967    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4968    #[xml(rename = "SetIRRepeaterState", ns(SERVICE_TYPE))]
4969    pub struct SetIrRepeaterStateRequest {
4970        #[xml(rename = "DesiredIRRepeaterState", ns(""))]
4971        pub desired_ir_repeater_state: super::IRRepeaterState,
4972    }
4973
4974    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
4975    #[xml(rename = "SetLEDFeedbackState", ns(SERVICE_TYPE))]
4976    pub struct SetLedFeedbackStateRequest {
4977        #[xml(rename = "LEDFeedbackState", ns(""))]
4978        pub led_feedback_state: super::LEDFeedbackState,
4979    }
4980
4981    /// A parsed event produced by the `HTControl` service.
4982    /// Use `SonosDevice::subscribe_ht_control()` to obtain an event
4983    /// stream that produces these.
4984    #[derive(Debug, Clone, PartialEq, Default)]
4985    pub struct HTControlEvent {
4986        pub ir_repeater_state: Option<super::IRRepeaterState>,
4987        pub tos_link_connected: Option<bool>,
4988    }
4989
4990    #[derive(FromXml, Debug, Clone, PartialEq)]
4991    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4992    struct HTControlPropertySet {
4993        pub properties: Vec<HTControlProperty>,
4994    }
4995
4996    #[derive(FromXml, Debug, Clone, PartialEq)]
4997    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
4998    struct HTControlProperty {
4999        #[xml(rename = "IRRepeaterState", ns(""))]
5000        pub ir_repeater_state: Option<super::IRRepeaterState>,
5001        #[xml(rename = "TOSLinkConnected", ns(""))]
5002        pub tos_link_connected: Option<bool>,
5003    }
5004
5005    impl DecodeXml for HTControlEvent {
5006        fn decode_xml(xml: &str) -> crate::Result<Self> {
5007            let mut result = Self::default();
5008            let set: HTControlPropertySet = instant_xml::from_str(xml)?;
5009            for prop in set.properties {
5010                if let Some(v) = prop.ir_repeater_state {
5011                    result.ir_repeater_state.replace(v);
5012                }
5013
5014                if let Some(v) = prop.tos_link_connected {
5015                    result.tos_link_connected.replace(v);
5016                }
5017            }
5018            Ok(result)
5019        }
5020    }
5021
5022    impl crate::SonosDevice {
5023        /// Subscribe to events from the `HTControl` service on this device
5024        pub async fn subscribe_ht_control(
5025            &self,
5026        ) -> crate::Result<crate::upnp::EventStream<HTControlEvent>> {
5027            self.subscribe_helper(&SERVICE_TYPE).await
5028        }
5029    }
5030}
5031
5032#[derive(PartialEq, Debug, Clone, Eq, Default)]
5033pub enum IRRepeaterState {
5034    #[default]
5035    On,
5036    Off,
5037    Disabled,
5038
5039    /// Allows passing a value that was not known at the
5040    /// time that this crate was generated from the available
5041    /// device descriptions
5042    Unspecified(String),
5043}
5044
5045impl ToString for IRRepeaterState {
5046    fn to_string(&self) -> String {
5047        match self {
5048            IRRepeaterState::On => "On".to_string(),
5049            IRRepeaterState::Off => "Off".to_string(),
5050            IRRepeaterState::Disabled => "Disabled".to_string(),
5051            IRRepeaterState::Unspecified(s) => s.to_string(),
5052        }
5053    }
5054}
5055
5056impl FromStr for IRRepeaterState {
5057    type Err = crate::Error;
5058    fn from_str(s: &str) -> Result<IRRepeaterState> {
5059        match s {
5060            "On" => Ok(IRRepeaterState::On),
5061            "Off" => Ok(IRRepeaterState::Off),
5062            "Disabled" => Ok(IRRepeaterState::Disabled),
5063            s => Ok(IRRepeaterState::Unspecified(s.to_string())),
5064        }
5065    }
5066}
5067
5068impl instant_xml::ToXml for IRRepeaterState {
5069    fn serialize<W: std::fmt::Write + ?Sized>(
5070        &self,
5071        field: Option<instant_xml::Id<'_>>,
5072        serializer: &mut instant_xml::Serializer<W>,
5073    ) -> std::result::Result<(), instant_xml::Error> {
5074        self.to_string().serialize(field, serializer)
5075    }
5076
5077    fn present(&self) -> bool {
5078        true
5079    }
5080}
5081
5082impl<'xml> instant_xml::FromXml<'xml> for IRRepeaterState {
5083    #[inline]
5084    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
5085        match field {
5086            Some(field) => id == field,
5087            None => false,
5088        }
5089    }
5090
5091    fn deserialize<'cx>(
5092        into: &mut Self::Accumulator,
5093        field: &'static str,
5094        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
5095    ) -> std::result::Result<(), instant_xml::Error> {
5096        if into.is_some() {
5097            return Err(instant_xml::Error::DuplicateValue(field));
5098        }
5099
5100        match deserializer.take_str()? {
5101            Some(value) => {
5102                let parsed: IRRepeaterState = value.parse().map_err(|err| {
5103                    instant_xml::Error::Other(format!(
5104                        "invalid value for field {field}: {value}: {err:#}"
5105                    ))
5106                })?;
5107                *into = Some(parsed);
5108                Ok(())
5109            }
5110            None => Err(instant_xml::Error::MissingValue(field)),
5111        }
5112    }
5113
5114    type Accumulator = Option<IRRepeaterState>;
5115    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
5116}
5117
5118#[derive(PartialEq, Debug, Clone, Eq, Default)]
5119pub enum LEDFeedbackState {
5120    #[default]
5121    On,
5122    Off,
5123
5124    /// Allows passing a value that was not known at the
5125    /// time that this crate was generated from the available
5126    /// device descriptions
5127    Unspecified(String),
5128}
5129
5130impl ToString for LEDFeedbackState {
5131    fn to_string(&self) -> String {
5132        match self {
5133            LEDFeedbackState::On => "On".to_string(),
5134            LEDFeedbackState::Off => "Off".to_string(),
5135            LEDFeedbackState::Unspecified(s) => s.to_string(),
5136        }
5137    }
5138}
5139
5140impl FromStr for LEDFeedbackState {
5141    type Err = crate::Error;
5142    fn from_str(s: &str) -> Result<LEDFeedbackState> {
5143        match s {
5144            "On" => Ok(LEDFeedbackState::On),
5145            "Off" => Ok(LEDFeedbackState::Off),
5146            s => Ok(LEDFeedbackState::Unspecified(s.to_string())),
5147        }
5148    }
5149}
5150
5151impl instant_xml::ToXml for LEDFeedbackState {
5152    fn serialize<W: std::fmt::Write + ?Sized>(
5153        &self,
5154        field: Option<instant_xml::Id<'_>>,
5155        serializer: &mut instant_xml::Serializer<W>,
5156    ) -> std::result::Result<(), instant_xml::Error> {
5157        self.to_string().serialize(field, serializer)
5158    }
5159
5160    fn present(&self) -> bool {
5161        true
5162    }
5163}
5164
5165impl<'xml> instant_xml::FromXml<'xml> for LEDFeedbackState {
5166    #[inline]
5167    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
5168        match field {
5169            Some(field) => id == field,
5170            None => false,
5171        }
5172    }
5173
5174    fn deserialize<'cx>(
5175        into: &mut Self::Accumulator,
5176        field: &'static str,
5177        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
5178    ) -> std::result::Result<(), instant_xml::Error> {
5179        if into.is_some() {
5180            return Err(instant_xml::Error::DuplicateValue(field));
5181        }
5182
5183        match deserializer.take_str()? {
5184            Some(value) => {
5185                let parsed: LEDFeedbackState = value.parse().map_err(|err| {
5186                    instant_xml::Error::Other(format!(
5187                        "invalid value for field {field}: {value}: {err:#}"
5188                    ))
5189                })?;
5190                *into = Some(parsed);
5191                Ok(())
5192            }
5193            None => Err(instant_xml::Error::MissingValue(field)),
5194        }
5195    }
5196
5197    type Accumulator = Option<LEDFeedbackState>;
5198    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
5199}
5200
5201/// Request and Response types for the `MusicServices` service.
5202pub mod music_services {
5203    use super::*;
5204
5205    /// URN for the `MusicServices` service.
5206    /// `urn:schemas-upnp-org:service:MusicServices:1`
5207    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:MusicServices:1";
5208
5209    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5210    #[xml(rename = "GetSessionId", ns(SERVICE_TYPE))]
5211    pub struct GetSessionIdRequest {
5212        #[xml(rename = "ServiceId", ns(""))]
5213        pub service_id: u32,
5214        #[xml(rename = "Username", ns(""))]
5215        pub username: String,
5216    }
5217
5218    #[derive(FromXml, Debug, Clone, PartialEq)]
5219    #[xml(rename = "GetSessionIdResponse", ns(SERVICE_TYPE))]
5220    pub struct GetSessionIdResponse {
5221        #[xml(rename = "SessionId", ns(""))]
5222        pub session_id: Option<String>,
5223    }
5224
5225    impl crate::DecodeSoapResponse for GetSessionIdResponse {
5226        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5227            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5228            Ok(envelope.body.payload)
5229        }
5230    }
5231
5232    #[derive(FromXml, Debug, Clone, PartialEq)]
5233    #[xml(rename = "ListAvailableServicesResponse", ns(SERVICE_TYPE))]
5234    pub struct ListAvailableServicesResponse {
5235        #[xml(rename = "AvailableServiceDescriptorList", ns(""))]
5236        pub available_service_descriptor_list: Option<String>,
5237        #[xml(rename = "AvailableServiceTypeList", ns(""))]
5238        pub available_service_type_list: Option<String>,
5239        #[xml(rename = "AvailableServiceListVersion", ns(""))]
5240        pub available_service_list_version: Option<String>,
5241    }
5242
5243    impl crate::DecodeSoapResponse for ListAvailableServicesResponse {
5244        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5245            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5246            Ok(envelope.body.payload)
5247        }
5248    }
5249
5250    /// A parsed event produced by the `MusicServices` service.
5251    /// Use `SonosDevice::subscribe_music_services()` to obtain an event
5252    /// stream that produces these.
5253    #[derive(Debug, Clone, PartialEq, Default)]
5254    pub struct MusicServicesEvent {
5255        pub service_list_version: Option<String>,
5256    }
5257
5258    #[derive(FromXml, Debug, Clone, PartialEq)]
5259    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
5260    struct MusicServicesPropertySet {
5261        pub properties: Vec<MusicServicesProperty>,
5262    }
5263
5264    #[derive(FromXml, Debug, Clone, PartialEq)]
5265    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
5266    struct MusicServicesProperty {
5267        #[xml(rename = "ServiceListVersion", ns(""))]
5268        pub service_list_version: Option<String>,
5269    }
5270
5271    impl DecodeXml for MusicServicesEvent {
5272        fn decode_xml(xml: &str) -> crate::Result<Self> {
5273            let mut result = Self::default();
5274            let set: MusicServicesPropertySet = instant_xml::from_str(xml)?;
5275            for prop in set.properties {
5276                if let Some(v) = prop.service_list_version {
5277                    result.service_list_version.replace(v);
5278                }
5279            }
5280            Ok(result)
5281        }
5282    }
5283
5284    impl crate::SonosDevice {
5285        /// Subscribe to events from the `MusicServices` service on this device
5286        pub async fn subscribe_music_services(
5287            &self,
5288        ) -> crate::Result<crate::upnp::EventStream<MusicServicesEvent>> {
5289            self.subscribe_helper(&SERVICE_TYPE).await
5290        }
5291    }
5292}
5293
5294/// Request and Response types for the `QPlay` service.
5295pub mod q_play {
5296    use super::*;
5297
5298    /// URN for the `QPlay` service.
5299    /// `urn:schemas-tencent-com:service:QPlay:1`
5300    pub const SERVICE_TYPE: &str = "urn:schemas-tencent-com:service:QPlay:1";
5301
5302    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5303    #[xml(rename = "QPlayAuth", ns(SERVICE_TYPE))]
5304    pub struct QPlayAuthRequest {
5305        #[xml(rename = "Seed", ns(""))]
5306        pub seed: String,
5307    }
5308
5309    #[derive(FromXml, Debug, Clone, PartialEq)]
5310    #[xml(rename = "QPlayAuthResponse", ns(SERVICE_TYPE))]
5311    pub struct QPlayAuthResponse {
5312        #[xml(rename = "Code", ns(""))]
5313        pub code: Option<String>,
5314        #[xml(rename = "MID", ns(""))]
5315        pub mid: Option<String>,
5316        #[xml(rename = "DID", ns(""))]
5317        pub did: Option<String>,
5318    }
5319
5320    impl crate::DecodeSoapResponse for QPlayAuthResponse {
5321        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5322            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5323            Ok(envelope.body.payload)
5324        }
5325    }
5326}
5327
5328/// Request and Response types for the `Queue` service.
5329pub mod queue {
5330    use super::*;
5331
5332    /// URN for the `Queue` service.
5333    /// `urn:schemas-sonos-com:service:Queue:1`
5334    pub const SERVICE_TYPE: &str = "urn:schemas-sonos-com:service:Queue:1";
5335
5336    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5337    #[xml(rename = "AddMultipleURIs", ns(SERVICE_TYPE))]
5338    pub struct AddMultipleUrisRequest {
5339        #[xml(rename = "QueueID", ns(""))]
5340        pub queue_id: u32,
5341        #[xml(rename = "UpdateID", ns(""))]
5342        pub update_id: u32,
5343        #[xml(rename = "ContainerURI", ns(""))]
5344        pub container_uri: String,
5345        #[xml(rename = "ContainerMetaData", ns(""))]
5346        pub container_meta_data: String,
5347        #[xml(rename = "DesiredFirstTrackNumberEnqueued", ns(""))]
5348        pub desired_first_track_number_enqueued: u32,
5349        #[xml(rename = "EnqueueAsNext", ns(""))]
5350        pub enqueue_as_next: bool,
5351        #[xml(rename = "NumberOfURIs", ns(""))]
5352        pub number_of_uris: u32,
5353        #[xml(rename = "EnqueuedURIsAndMetaData", ns(""))]
5354        pub enqueued_uris_and_meta_data: String,
5355    }
5356
5357    #[derive(FromXml, Debug, Clone, PartialEq)]
5358    #[xml(rename = "AddMultipleURIsResponse", ns(SERVICE_TYPE))]
5359    pub struct AddMultipleUrisResponse {
5360        #[xml(rename = "FirstTrackNumberEnqueued", ns(""))]
5361        pub first_track_number_enqueued: Option<u32>,
5362        #[xml(rename = "NumTracksAdded", ns(""))]
5363        pub num_tracks_added: Option<u32>,
5364        #[xml(rename = "NewQueueLength", ns(""))]
5365        pub new_queue_length: Option<u32>,
5366        #[xml(rename = "NewUpdateID", ns(""))]
5367        pub new_update_id: Option<u32>,
5368    }
5369
5370    impl crate::DecodeSoapResponse for AddMultipleUrisResponse {
5371        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5372            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5373            Ok(envelope.body.payload)
5374        }
5375    }
5376
5377    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5378    #[xml(rename = "AddURI", ns(SERVICE_TYPE))]
5379    pub struct AddUriRequest {
5380        #[xml(rename = "QueueID", ns(""))]
5381        pub queue_id: u32,
5382        #[xml(rename = "UpdateID", ns(""))]
5383        pub update_id: u32,
5384        #[xml(rename = "EnqueuedURI", ns(""))]
5385        pub enqueued_uri: String,
5386        #[xml(rename = "EnqueuedURIMetaData", ns(""))]
5387        pub enqueued_uri_meta_data: DecodeXmlString<crate::TrackMetaData>,
5388        #[xml(rename = "DesiredFirstTrackNumberEnqueued", ns(""))]
5389        pub desired_first_track_number_enqueued: u32,
5390        #[xml(rename = "EnqueueAsNext", ns(""))]
5391        pub enqueue_as_next: bool,
5392    }
5393
5394    #[derive(FromXml, Debug, Clone, PartialEq)]
5395    #[xml(rename = "AddURIResponse", ns(SERVICE_TYPE))]
5396    pub struct AddUriResponse {
5397        #[xml(rename = "FirstTrackNumberEnqueued", ns(""))]
5398        pub first_track_number_enqueued: Option<u32>,
5399        #[xml(rename = "NumTracksAdded", ns(""))]
5400        pub num_tracks_added: Option<u32>,
5401        #[xml(rename = "NewQueueLength", ns(""))]
5402        pub new_queue_length: Option<u32>,
5403        #[xml(rename = "NewUpdateID", ns(""))]
5404        pub new_update_id: Option<u32>,
5405    }
5406
5407    impl crate::DecodeSoapResponse for AddUriResponse {
5408        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5409            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5410            Ok(envelope.body.payload)
5411        }
5412    }
5413
5414    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5415    #[xml(rename = "AttachQueue", ns(SERVICE_TYPE))]
5416    pub struct AttachQueueRequest {
5417        #[xml(rename = "QueueOwnerID", ns(""))]
5418        pub queue_owner_id: String,
5419    }
5420
5421    #[derive(FromXml, Debug, Clone, PartialEq)]
5422    #[xml(rename = "AttachQueueResponse", ns(SERVICE_TYPE))]
5423    pub struct AttachQueueResponse {
5424        #[xml(rename = "QueueID", ns(""))]
5425        pub queue_id: Option<u32>,
5426        #[xml(rename = "QueueOwnerContext", ns(""))]
5427        pub queue_owner_context: Option<String>,
5428    }
5429
5430    impl crate::DecodeSoapResponse for AttachQueueResponse {
5431        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5432            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5433            Ok(envelope.body.payload)
5434        }
5435    }
5436
5437    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5438    #[xml(rename = "Browse", ns(SERVICE_TYPE))]
5439    pub struct BrowseRequest {
5440        #[xml(rename = "QueueID", ns(""))]
5441        pub queue_id: u32,
5442        #[xml(rename = "StartingIndex", ns(""))]
5443        pub starting_index: u32,
5444        #[xml(rename = "RequestedCount", ns(""))]
5445        pub requested_count: u32,
5446    }
5447
5448    #[derive(FromXml, Debug, Clone, PartialEq)]
5449    #[xml(rename = "BrowseResponse", ns(SERVICE_TYPE))]
5450    pub struct BrowseResponse {
5451        #[xml(rename = "Result", ns(""))]
5452        pub result: Option<DecodeXmlString<crate::TrackMetaDataList>>,
5453        #[xml(rename = "NumberReturned", ns(""))]
5454        pub number_returned: Option<u32>,
5455        #[xml(rename = "TotalMatches", ns(""))]
5456        pub total_matches: Option<u32>,
5457        #[xml(rename = "UpdateID", ns(""))]
5458        pub update_id: Option<u32>,
5459    }
5460
5461    impl crate::DecodeSoapResponse for BrowseResponse {
5462        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5463            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5464            Ok(envelope.body.payload)
5465        }
5466    }
5467
5468    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5469    #[xml(rename = "CreateQueue", ns(SERVICE_TYPE))]
5470    pub struct CreateQueueRequest {
5471        #[xml(rename = "QueueOwnerID", ns(""))]
5472        pub queue_owner_id: String,
5473        #[xml(rename = "QueueOwnerContext", ns(""))]
5474        pub queue_owner_context: String,
5475        #[xml(rename = "QueuePolicy", ns(""))]
5476        pub queue_policy: String,
5477    }
5478
5479    #[derive(FromXml, Debug, Clone, PartialEq)]
5480    #[xml(rename = "CreateQueueResponse", ns(SERVICE_TYPE))]
5481    pub struct CreateQueueResponse {
5482        #[xml(rename = "QueueID", ns(""))]
5483        pub queue_id: Option<u32>,
5484    }
5485
5486    impl crate::DecodeSoapResponse for CreateQueueResponse {
5487        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5488            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5489            Ok(envelope.body.payload)
5490        }
5491    }
5492
5493    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5494    #[xml(rename = "RemoveAllTracks", ns(SERVICE_TYPE))]
5495    pub struct RemoveAllTracksRequest {
5496        #[xml(rename = "QueueID", ns(""))]
5497        pub queue_id: u32,
5498        #[xml(rename = "UpdateID", ns(""))]
5499        pub update_id: u32,
5500    }
5501
5502    #[derive(FromXml, Debug, Clone, PartialEq)]
5503    #[xml(rename = "RemoveAllTracksResponse", ns(SERVICE_TYPE))]
5504    pub struct RemoveAllTracksResponse {
5505        #[xml(rename = "NewUpdateID", ns(""))]
5506        pub new_update_id: Option<u32>,
5507    }
5508
5509    impl crate::DecodeSoapResponse for RemoveAllTracksResponse {
5510        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5511            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5512            Ok(envelope.body.payload)
5513        }
5514    }
5515
5516    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5517    #[xml(rename = "RemoveTrackRange", ns(SERVICE_TYPE))]
5518    pub struct RemoveTrackRangeRequest {
5519        #[xml(rename = "QueueID", ns(""))]
5520        pub queue_id: u32,
5521        #[xml(rename = "UpdateID", ns(""))]
5522        pub update_id: u32,
5523        #[xml(rename = "StartingIndex", ns(""))]
5524        pub starting_index: u32,
5525        #[xml(rename = "NumberOfTracks", ns(""))]
5526        pub number_of_tracks: u32,
5527    }
5528
5529    #[derive(FromXml, Debug, Clone, PartialEq)]
5530    #[xml(rename = "RemoveTrackRangeResponse", ns(SERVICE_TYPE))]
5531    pub struct RemoveTrackRangeResponse {
5532        #[xml(rename = "NewUpdateID", ns(""))]
5533        pub new_update_id: Option<u32>,
5534    }
5535
5536    impl crate::DecodeSoapResponse for RemoveTrackRangeResponse {
5537        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5538            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5539            Ok(envelope.body.payload)
5540        }
5541    }
5542
5543    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5544    #[xml(rename = "ReorderTracks", ns(SERVICE_TYPE))]
5545    pub struct ReorderTracksRequest {
5546        #[xml(rename = "QueueID", ns(""))]
5547        pub queue_id: u32,
5548        #[xml(rename = "StartingIndex", ns(""))]
5549        pub starting_index: u32,
5550        #[xml(rename = "NumberOfTracks", ns(""))]
5551        pub number_of_tracks: u32,
5552        #[xml(rename = "InsertBefore", ns(""))]
5553        pub insert_before: u32,
5554        #[xml(rename = "UpdateID", ns(""))]
5555        pub update_id: u32,
5556    }
5557
5558    #[derive(FromXml, Debug, Clone, PartialEq)]
5559    #[xml(rename = "ReorderTracksResponse", ns(SERVICE_TYPE))]
5560    pub struct ReorderTracksResponse {
5561        #[xml(rename = "NewUpdateID", ns(""))]
5562        pub new_update_id: Option<u32>,
5563    }
5564
5565    impl crate::DecodeSoapResponse for ReorderTracksResponse {
5566        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5567            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5568            Ok(envelope.body.payload)
5569        }
5570    }
5571
5572    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5573    #[xml(rename = "ReplaceAllTracks", ns(SERVICE_TYPE))]
5574    pub struct ReplaceAllTracksRequest {
5575        #[xml(rename = "QueueID", ns(""))]
5576        pub queue_id: u32,
5577        #[xml(rename = "UpdateID", ns(""))]
5578        pub update_id: u32,
5579        #[xml(rename = "ContainerURI", ns(""))]
5580        pub container_uri: String,
5581        #[xml(rename = "ContainerMetaData", ns(""))]
5582        pub container_meta_data: String,
5583        #[xml(rename = "CurrentTrackIndex", ns(""))]
5584        pub current_track_index: u32,
5585        #[xml(rename = "NewCurrentTrackIndices", ns(""))]
5586        pub new_current_track_indices: String,
5587        #[xml(rename = "NumberOfURIs", ns(""))]
5588        pub number_of_uris: u32,
5589        #[xml(rename = "EnqueuedURIsAndMetaData", ns(""))]
5590        pub enqueued_uris_and_meta_data: String,
5591    }
5592
5593    #[derive(FromXml, Debug, Clone, PartialEq)]
5594    #[xml(rename = "ReplaceAllTracksResponse", ns(SERVICE_TYPE))]
5595    pub struct ReplaceAllTracksResponse {
5596        #[xml(rename = "NewQueueLength", ns(""))]
5597        pub new_queue_length: Option<u32>,
5598        #[xml(rename = "NewUpdateID", ns(""))]
5599        pub new_update_id: Option<u32>,
5600    }
5601
5602    impl crate::DecodeSoapResponse for ReplaceAllTracksResponse {
5603        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5604            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5605            Ok(envelope.body.payload)
5606        }
5607    }
5608
5609    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5610    #[xml(rename = "SaveAsSonosPlaylist", ns(SERVICE_TYPE))]
5611    pub struct SaveAsSonosPlaylistRequest {
5612        #[xml(rename = "QueueID", ns(""))]
5613        pub queue_id: u32,
5614        #[xml(rename = "Title", ns(""))]
5615        pub title: String,
5616        #[xml(rename = "ObjectID", ns(""))]
5617        pub object_id: String,
5618    }
5619
5620    #[derive(FromXml, Debug, Clone, PartialEq)]
5621    #[xml(rename = "SaveAsSonosPlaylistResponse", ns(SERVICE_TYPE))]
5622    pub struct SaveAsSonosPlaylistResponse {
5623        #[xml(rename = "AssignedObjectID", ns(""))]
5624        pub assigned_object_id: Option<String>,
5625    }
5626
5627    impl crate::DecodeSoapResponse for SaveAsSonosPlaylistResponse {
5628        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5629            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5630            Ok(envelope.body.payload)
5631        }
5632    }
5633
5634    /// A parsed event produced by the `Queue` service.
5635    /// Use `SonosDevice::subscribe_queue()` to obtain an event
5636    /// stream that produces these.
5637    #[derive(Debug, Clone, PartialEq, Default)]
5638    pub struct QueueEvent {
5639        pub last_change: Option<DecodeXmlString<QueueLastChangeMap>>,
5640    }
5641
5642    #[derive(FromXml, Debug, Clone, PartialEq)]
5643    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
5644    struct QueuePropertySet {
5645        pub properties: Vec<QueueProperty>,
5646    }
5647
5648    #[derive(FromXml, Debug, Clone, PartialEq)]
5649    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
5650    struct QueueProperty {
5651        #[xml(rename = "LastChange", ns(""))]
5652        pub last_change: Option<DecodeXmlString<QueueLastChangeMap>>,
5653    }
5654
5655    impl DecodeXml for QueueEvent {
5656        fn decode_xml(xml: &str) -> crate::Result<Self> {
5657            let mut result = Self::default();
5658            let set: QueuePropertySet = instant_xml::from_str(xml)?;
5659            for prop in set.properties {
5660                if let Some(v) = prop.last_change {
5661                    result.last_change.replace(v);
5662                }
5663            }
5664            Ok(result)
5665        }
5666    }
5667
5668    impl crate::SonosDevice {
5669        /// Subscribe to events from the `Queue` service on this device
5670        pub async fn subscribe_queue(&self) -> crate::Result<crate::upnp::EventStream<QueueEvent>> {
5671            self.subscribe_helper(&SERVICE_TYPE).await
5672        }
5673    }
5674
5675    #[derive(Debug, Clone, PartialEq, Default)]
5676    pub struct QueueLastChange {
5677        pub count: Option<u32>,
5678        pub enqueue_as_next: Option<bool>,
5679        pub index: Option<u32>,
5680        pub list_uri: Option<String>,
5681        pub list_uri_and_metadata: Option<String>,
5682        pub num_tracks: Option<u32>,
5683        pub object_id: Option<String>,
5684        pub queue_id: Option<u32>,
5685        pub queue_owner_context: Option<String>,
5686        pub queue_owner_id: Option<String>,
5687        pub queue_policy: Option<String>,
5688        pub result: Option<String>,
5689        pub saved_queue_title: Option<String>,
5690        pub track_number: Option<u32>,
5691        pub track_numbers_csv: Option<String>,
5692        pub uri: Option<String>,
5693        pub uri_meta_data: Option<String>,
5694        pub update_id: Option<u32>,
5695        pub curated: Option<bool>,
5696    }
5697
5698    #[derive(FromXml)]
5699    #[xml(rename = "Count", ns(LAST_CHANGE_NS))]
5700    #[allow(non_camel_case_types)]
5701    struct QueueLastChangeCount {
5702        #[xml(attribute)]
5703        val: Option<u32>,
5704    }
5705
5706    #[derive(FromXml)]
5707    #[xml(rename = "EnqueueAsNext", ns(LAST_CHANGE_NS))]
5708    #[allow(non_camel_case_types)]
5709    struct QueueLastChangeEnqueueAsNext {
5710        #[xml(attribute)]
5711        val: Option<bool>,
5712    }
5713
5714    #[derive(FromXml)]
5715    #[xml(rename = "Index", ns(LAST_CHANGE_NS))]
5716    #[allow(non_camel_case_types)]
5717    struct QueueLastChangeIndex {
5718        #[xml(attribute)]
5719        val: Option<u32>,
5720    }
5721
5722    #[derive(FromXml)]
5723    #[xml(rename = "LIST_URI", ns(LAST_CHANGE_NS))]
5724    #[allow(non_camel_case_types)]
5725    struct QueueLastChangeLIST_URI {
5726        #[xml(attribute)]
5727        val: Option<String>,
5728    }
5729
5730    #[derive(FromXml)]
5731    #[xml(rename = "LIST_URI_AND_METADATA", ns(LAST_CHANGE_NS))]
5732    #[allow(non_camel_case_types)]
5733    struct QueueLastChangeLIST_URI_AND_METADATA {
5734        #[xml(attribute)]
5735        val: Option<String>,
5736    }
5737
5738    #[derive(FromXml)]
5739    #[xml(rename = "NumTracks", ns(LAST_CHANGE_NS))]
5740    #[allow(non_camel_case_types)]
5741    struct QueueLastChangeNumTracks {
5742        #[xml(attribute)]
5743        val: Option<u32>,
5744    }
5745
5746    #[derive(FromXml)]
5747    #[xml(rename = "ObjectID", ns(LAST_CHANGE_NS))]
5748    #[allow(non_camel_case_types)]
5749    struct QueueLastChangeObjectID {
5750        #[xml(attribute)]
5751        val: Option<String>,
5752    }
5753
5754    #[derive(FromXml)]
5755    #[xml(rename = "QueueID", ns(LAST_CHANGE_NS))]
5756    #[allow(non_camel_case_types)]
5757    struct QueueLastChangeQueueID {
5758        #[xml(attribute)]
5759        val: Option<u32>,
5760    }
5761
5762    #[derive(FromXml)]
5763    #[xml(rename = "QueueOwnerContext", ns(LAST_CHANGE_NS))]
5764    #[allow(non_camel_case_types)]
5765    struct QueueLastChangeQueueOwnerContext {
5766        #[xml(attribute)]
5767        val: Option<String>,
5768    }
5769
5770    #[derive(FromXml)]
5771    #[xml(rename = "QueueOwnerID", ns(LAST_CHANGE_NS))]
5772    #[allow(non_camel_case_types)]
5773    struct QueueLastChangeQueueOwnerID {
5774        #[xml(attribute)]
5775        val: Option<String>,
5776    }
5777
5778    #[derive(FromXml)]
5779    #[xml(rename = "QueuePolicy", ns(LAST_CHANGE_NS))]
5780    #[allow(non_camel_case_types)]
5781    struct QueueLastChangeQueuePolicy {
5782        #[xml(attribute)]
5783        val: Option<String>,
5784    }
5785
5786    #[derive(FromXml)]
5787    #[xml(rename = "Result", ns(LAST_CHANGE_NS))]
5788    #[allow(non_camel_case_types)]
5789    struct QueueLastChangeResult {
5790        #[xml(attribute)]
5791        val: Option<String>,
5792    }
5793
5794    #[derive(FromXml)]
5795    #[xml(rename = "SavedQueueTitle", ns(LAST_CHANGE_NS))]
5796    #[allow(non_camel_case_types)]
5797    struct QueueLastChangeSavedQueueTitle {
5798        #[xml(attribute)]
5799        val: Option<String>,
5800    }
5801
5802    #[derive(FromXml)]
5803    #[xml(rename = "TrackNumber", ns(LAST_CHANGE_NS))]
5804    #[allow(non_camel_case_types)]
5805    struct QueueLastChangeTrackNumber {
5806        #[xml(attribute)]
5807        val: Option<u32>,
5808    }
5809
5810    #[derive(FromXml)]
5811    #[xml(rename = "TrackNumbersCSV", ns(LAST_CHANGE_NS))]
5812    #[allow(non_camel_case_types)]
5813    struct QueueLastChangeTrackNumbersCSV {
5814        #[xml(attribute)]
5815        val: Option<String>,
5816    }
5817
5818    #[derive(FromXml)]
5819    #[xml(rename = "URI", ns(LAST_CHANGE_NS))]
5820    #[allow(non_camel_case_types)]
5821    struct QueueLastChangeURI {
5822        #[xml(attribute)]
5823        val: Option<String>,
5824    }
5825
5826    #[derive(FromXml)]
5827    #[xml(rename = "URIMetaData", ns(LAST_CHANGE_NS))]
5828    #[allow(non_camel_case_types)]
5829    struct QueueLastChangeURIMetaData {
5830        #[xml(attribute)]
5831        val: Option<String>,
5832    }
5833
5834    #[derive(FromXml)]
5835    #[xml(rename = "UpdateID", ns(LAST_CHANGE_NS))]
5836    #[allow(non_camel_case_types)]
5837    struct QueueLastChangeUpdateID {
5838        #[xml(attribute)]
5839        val: Option<u32>,
5840    }
5841
5842    #[derive(FromXml)]
5843    #[xml(rename = "Curated", ns(LAST_CHANGE_NS))]
5844    #[allow(non_camel_case_types)]
5845    struct QueueLastChangeCurated {
5846        #[xml(attribute)]
5847        val: Option<bool>,
5848    }
5849
5850    const LAST_CHANGE_NS: &str = "urn:schemas-sonos-com:metadata-1-0/Queue/";
5851
5852    #[derive(FromXml)]
5853    #[xml(rename = "QueueID", ns(LAST_CHANGE_NS))]
5854    struct QueueLastChangeRootObject {
5855        #[xml(rename = "val", attribute)]
5856        object_instance_id_: u32,
5857
5858        count: Option<QueueLastChangeCount>,
5859        enqueue_as_next: Option<QueueLastChangeEnqueueAsNext>,
5860        index: Option<QueueLastChangeIndex>,
5861        list_uri: Option<QueueLastChangeLIST_URI>,
5862        list_uri_and_metadata: Option<QueueLastChangeLIST_URI_AND_METADATA>,
5863        num_tracks: Option<QueueLastChangeNumTracks>,
5864        object_id: Option<QueueLastChangeObjectID>,
5865        queue_id: Option<QueueLastChangeQueueID>,
5866        queue_owner_context: Option<QueueLastChangeQueueOwnerContext>,
5867        queue_owner_id: Option<QueueLastChangeQueueOwnerID>,
5868        queue_policy: Option<QueueLastChangeQueuePolicy>,
5869        result: Option<QueueLastChangeResult>,
5870        saved_queue_title: Option<QueueLastChangeSavedQueueTitle>,
5871        track_number: Option<QueueLastChangeTrackNumber>,
5872        track_numbers_csv: Option<QueueLastChangeTrackNumbersCSV>,
5873        uri: Option<QueueLastChangeURI>,
5874        uri_meta_data: Option<QueueLastChangeURIMetaData>,
5875        update_id: Option<QueueLastChangeUpdateID>,
5876        curated: Option<QueueLastChangeCurated>,
5877    }
5878
5879    #[derive(Debug, Clone, PartialEq, Default)]
5880    pub struct QueueLastChangeMap {
5881        pub map: std::collections::BTreeMap<u32, QueueLastChange>,
5882    }
5883
5884    impl DecodeXml for QueueLastChangeMap {
5885        fn decode_xml(xml: &str) -> crate::Result<Self> {
5886            #[derive(FromXml)]
5887            #[xml(ns(LAST_CHANGE_NS, r = "urn:schemas-rinconnetworks-com:metadata-1-0/"))]
5888            struct Event {
5889                instance: Vec<QueueLastChangeRootObject>,
5890            }
5891
5892            let last_change: Event = instant_xml::from_str(xml)?;
5893            let mut map = std::collections::BTreeMap::new();
5894
5895            for item in last_change.instance {
5896                let mut result = QueueLastChange::default();
5897
5898                result.count = item.count.and_then(|v| v.val);
5899
5900                result.enqueue_as_next = item.enqueue_as_next.and_then(|v| v.val);
5901
5902                result.index = item.index.and_then(|v| v.val);
5903
5904                result.list_uri = item.list_uri.and_then(|v| v.val);
5905
5906                result.list_uri_and_metadata = item.list_uri_and_metadata.and_then(|v| v.val);
5907
5908                result.num_tracks = item.num_tracks.and_then(|v| v.val);
5909
5910                result.object_id = item.object_id.and_then(|v| v.val);
5911
5912                result.queue_id = item.queue_id.and_then(|v| v.val);
5913
5914                result.queue_owner_context = item.queue_owner_context.and_then(|v| v.val);
5915
5916                result.queue_owner_id = item.queue_owner_id.and_then(|v| v.val);
5917
5918                result.queue_policy = item.queue_policy.and_then(|v| v.val);
5919
5920                result.result = item.result.and_then(|v| v.val);
5921
5922                result.saved_queue_title = item.saved_queue_title.and_then(|v| v.val);
5923
5924                result.track_number = item.track_number.and_then(|v| v.val);
5925
5926                result.track_numbers_csv = item.track_numbers_csv.and_then(|v| v.val);
5927
5928                result.uri = item.uri.and_then(|v| v.val);
5929
5930                result.uri_meta_data = item.uri_meta_data.and_then(|v| v.val);
5931
5932                result.update_id = item.update_id.and_then(|v| v.val);
5933
5934                result.curated = item.curated.and_then(|v| v.val);
5935
5936                map.insert(item.object_instance_id_, result);
5937            }
5938
5939            Ok(QueueLastChangeMap { map })
5940        }
5941    }
5942}
5943
5944/// Request and Response types for the `RenderingControl` service.
5945pub mod rendering_control {
5946    use super::*;
5947
5948    /// URN for the `RenderingControl` service.
5949    /// `urn:schemas-upnp-org:service:RenderingControl:1`
5950    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:RenderingControl:1";
5951
5952    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5953    #[xml(rename = "GetBass", ns(SERVICE_TYPE))]
5954    pub struct GetBassRequest {
5955        #[xml(rename = "InstanceID", ns(""))]
5956        pub instance_id: u32,
5957    }
5958
5959    #[derive(FromXml, Debug, Clone, PartialEq)]
5960    #[xml(rename = "GetBassResponse", ns(SERVICE_TYPE))]
5961    pub struct GetBassResponse {
5962        #[xml(rename = "CurrentBass", ns(""))]
5963        pub current_bass: Option<i16>,
5964    }
5965
5966    impl crate::DecodeSoapResponse for GetBassResponse {
5967        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5968            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5969            Ok(envelope.body.payload)
5970        }
5971    }
5972
5973    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5974    #[xml(rename = "GetEQ", ns(SERVICE_TYPE))]
5975    pub struct GetEqRequest {
5976        #[xml(rename = "InstanceID", ns(""))]
5977        pub instance_id: u32,
5978        /// Allowed values `DialogLevel` (bool) / `MusicSurroundLevel` (-15/+15) /  `NightMode` (bool) / `SubGain` (-10/+10) / `SurroundEnable` (bool) / `SurroundLevel` (-15/+15) / `SurroundMode` (0 = ambient, 1 = full) / `HeightChannelLevel` (-10/+10)
5979        #[xml(rename = "EQType", ns(""))]
5980        pub eq_type: String,
5981    }
5982
5983    #[derive(FromXml, Debug, Clone, PartialEq)]
5984    #[xml(rename = "GetEQResponse", ns(SERVICE_TYPE))]
5985    pub struct GetEqResponse {
5986        #[xml(rename = "CurrentValue", ns(""))]
5987        pub current_value: Option<i16>,
5988    }
5989
5990    impl crate::DecodeSoapResponse for GetEqResponse {
5991        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
5992            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
5993            Ok(envelope.body.payload)
5994        }
5995    }
5996
5997    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
5998    #[xml(rename = "GetHeadphoneConnected", ns(SERVICE_TYPE))]
5999    pub struct GetHeadphoneConnectedRequest {
6000        #[xml(rename = "InstanceID", ns(""))]
6001        pub instance_id: u32,
6002    }
6003
6004    #[derive(FromXml, Debug, Clone, PartialEq)]
6005    #[xml(rename = "GetHeadphoneConnectedResponse", ns(SERVICE_TYPE))]
6006    pub struct GetHeadphoneConnectedResponse {
6007        #[xml(rename = "CurrentHeadphoneConnected", ns(""))]
6008        pub current_headphone_connected: Option<bool>,
6009    }
6010
6011    impl crate::DecodeSoapResponse for GetHeadphoneConnectedResponse {
6012        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6013            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6014            Ok(envelope.body.payload)
6015        }
6016    }
6017
6018    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6019    #[xml(rename = "GetLoudness", ns(SERVICE_TYPE))]
6020    pub struct GetLoudnessRequest {
6021        #[xml(rename = "InstanceID", ns(""))]
6022        pub instance_id: u32,
6023        #[xml(rename = "Channel", ns(""))]
6024        pub channel: super::Channel,
6025    }
6026
6027    #[derive(FromXml, Debug, Clone, PartialEq)]
6028    #[xml(rename = "GetLoudnessResponse", ns(SERVICE_TYPE))]
6029    pub struct GetLoudnessResponse {
6030        #[xml(rename = "CurrentLoudness", ns(""))]
6031        pub current_loudness: Option<bool>,
6032    }
6033
6034    impl crate::DecodeSoapResponse for GetLoudnessResponse {
6035        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6036            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6037            Ok(envelope.body.payload)
6038        }
6039    }
6040
6041    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6042    #[xml(rename = "GetMute", ns(SERVICE_TYPE))]
6043    pub struct GetMuteRequest {
6044        #[xml(rename = "InstanceID", ns(""))]
6045        pub instance_id: u32,
6046        #[xml(rename = "Channel", ns(""))]
6047        pub channel: super::MuteChannel,
6048    }
6049
6050    #[derive(FromXml, Debug, Clone, PartialEq)]
6051    #[xml(rename = "GetMuteResponse", ns(SERVICE_TYPE))]
6052    pub struct GetMuteResponse {
6053        #[xml(rename = "CurrentMute", ns(""))]
6054        pub current_mute: Option<bool>,
6055    }
6056
6057    impl crate::DecodeSoapResponse for GetMuteResponse {
6058        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6059            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6060            Ok(envelope.body.payload)
6061        }
6062    }
6063
6064    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6065    #[xml(rename = "GetOutputFixed", ns(SERVICE_TYPE))]
6066    pub struct GetOutputFixedRequest {
6067        #[xml(rename = "InstanceID", ns(""))]
6068        pub instance_id: u32,
6069    }
6070
6071    #[derive(FromXml, Debug, Clone, PartialEq)]
6072    #[xml(rename = "GetOutputFixedResponse", ns(SERVICE_TYPE))]
6073    pub struct GetOutputFixedResponse {
6074        #[xml(rename = "CurrentFixed", ns(""))]
6075        pub current_fixed: Option<bool>,
6076    }
6077
6078    impl crate::DecodeSoapResponse for GetOutputFixedResponse {
6079        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6080            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6081            Ok(envelope.body.payload)
6082        }
6083    }
6084
6085    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6086    #[xml(rename = "GetRoomCalibrationStatus", ns(SERVICE_TYPE))]
6087    pub struct GetRoomCalibrationStatusRequest {
6088        #[xml(rename = "InstanceID", ns(""))]
6089        pub instance_id: u32,
6090    }
6091
6092    #[derive(FromXml, Debug, Clone, PartialEq)]
6093    #[xml(rename = "GetRoomCalibrationStatusResponse", ns(SERVICE_TYPE))]
6094    pub struct GetRoomCalibrationStatusResponse {
6095        #[xml(rename = "RoomCalibrationEnabled", ns(""))]
6096        pub room_calibration_enabled: Option<bool>,
6097        #[xml(rename = "RoomCalibrationAvailable", ns(""))]
6098        pub room_calibration_available: Option<bool>,
6099    }
6100
6101    impl crate::DecodeSoapResponse for GetRoomCalibrationStatusResponse {
6102        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6103            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6104            Ok(envelope.body.payload)
6105        }
6106    }
6107
6108    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6109    #[xml(rename = "GetSupportsOutputFixed", ns(SERVICE_TYPE))]
6110    pub struct GetSupportsOutputFixedRequest {
6111        #[xml(rename = "InstanceID", ns(""))]
6112        pub instance_id: u32,
6113    }
6114
6115    #[derive(FromXml, Debug, Clone, PartialEq)]
6116    #[xml(rename = "GetSupportsOutputFixedResponse", ns(SERVICE_TYPE))]
6117    pub struct GetSupportsOutputFixedResponse {
6118        #[xml(rename = "CurrentSupportsFixed", ns(""))]
6119        pub current_supports_fixed: Option<bool>,
6120    }
6121
6122    impl crate::DecodeSoapResponse for GetSupportsOutputFixedResponse {
6123        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6124            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6125            Ok(envelope.body.payload)
6126        }
6127    }
6128
6129    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6130    #[xml(rename = "GetTreble", ns(SERVICE_TYPE))]
6131    pub struct GetTrebleRequest {
6132        #[xml(rename = "InstanceID", ns(""))]
6133        pub instance_id: u32,
6134    }
6135
6136    #[derive(FromXml, Debug, Clone, PartialEq)]
6137    #[xml(rename = "GetTrebleResponse", ns(SERVICE_TYPE))]
6138    pub struct GetTrebleResponse {
6139        #[xml(rename = "CurrentTreble", ns(""))]
6140        pub current_treble: Option<i16>,
6141    }
6142
6143    impl crate::DecodeSoapResponse for GetTrebleResponse {
6144        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6145            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6146            Ok(envelope.body.payload)
6147        }
6148    }
6149
6150    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6151    #[xml(rename = "GetVolume", ns(SERVICE_TYPE))]
6152    pub struct GetVolumeRequest {
6153        #[xml(rename = "InstanceID", ns(""))]
6154        pub instance_id: u32,
6155        #[xml(rename = "Channel", ns(""))]
6156        pub channel: super::Channel,
6157    }
6158
6159    #[derive(FromXml, Debug, Clone, PartialEq)]
6160    #[xml(rename = "GetVolumeResponse", ns(SERVICE_TYPE))]
6161    pub struct GetVolumeResponse {
6162        #[xml(rename = "CurrentVolume", ns(""))]
6163        pub current_volume: Option<u16>,
6164    }
6165
6166    impl crate::DecodeSoapResponse for GetVolumeResponse {
6167        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6168            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6169            Ok(envelope.body.payload)
6170        }
6171    }
6172
6173    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6174    #[xml(rename = "GetVolumeDB", ns(SERVICE_TYPE))]
6175    pub struct GetVolumeDbRequest {
6176        #[xml(rename = "InstanceID", ns(""))]
6177        pub instance_id: u32,
6178        #[xml(rename = "Channel", ns(""))]
6179        pub channel: super::Channel,
6180    }
6181
6182    #[derive(FromXml, Debug, Clone, PartialEq)]
6183    #[xml(rename = "GetVolumeDBResponse", ns(SERVICE_TYPE))]
6184    pub struct GetVolumeDbResponse {
6185        #[xml(rename = "CurrentVolume", ns(""))]
6186        pub current_volume: Option<i16>,
6187    }
6188
6189    impl crate::DecodeSoapResponse for GetVolumeDbResponse {
6190        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6191            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6192            Ok(envelope.body.payload)
6193        }
6194    }
6195
6196    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6197    #[xml(rename = "GetVolumeDBRange", ns(SERVICE_TYPE))]
6198    pub struct GetVolumeDbRangeRequest {
6199        #[xml(rename = "InstanceID", ns(""))]
6200        pub instance_id: u32,
6201        #[xml(rename = "Channel", ns(""))]
6202        pub channel: super::Channel,
6203    }
6204
6205    #[derive(FromXml, Debug, Clone, PartialEq)]
6206    #[xml(rename = "GetVolumeDBRangeResponse", ns(SERVICE_TYPE))]
6207    pub struct GetVolumeDbRangeResponse {
6208        #[xml(rename = "MinValue", ns(""))]
6209        pub min_value: Option<i16>,
6210        #[xml(rename = "MaxValue", ns(""))]
6211        pub max_value: Option<i16>,
6212    }
6213
6214    impl crate::DecodeSoapResponse for GetVolumeDbRangeResponse {
6215        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6216            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6217            Ok(envelope.body.payload)
6218        }
6219    }
6220
6221    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6222    #[xml(rename = "RampToVolume", ns(SERVICE_TYPE))]
6223    pub struct RampToVolumeRequest {
6224        #[xml(rename = "InstanceID", ns(""))]
6225        pub instance_id: u32,
6226        #[xml(rename = "Channel", ns(""))]
6227        pub channel: super::Channel,
6228        #[xml(rename = "RampType", ns(""))]
6229        pub ramp_type: super::RampType,
6230        #[xml(rename = "DesiredVolume", ns(""))]
6231        pub desired_volume: u16,
6232        #[xml(rename = "ResetVolumeAfter", ns(""))]
6233        pub reset_volume_after: bool,
6234        #[xml(rename = "ProgramURI", ns(""))]
6235        pub program_uri: String,
6236    }
6237
6238    #[derive(FromXml, Debug, Clone, PartialEq)]
6239    #[xml(rename = "RampToVolumeResponse", ns(SERVICE_TYPE))]
6240    pub struct RampToVolumeResponse {
6241        #[xml(rename = "RampTime", ns(""))]
6242        pub ramp_time: Option<u32>,
6243    }
6244
6245    impl crate::DecodeSoapResponse for RampToVolumeResponse {
6246        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6247            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6248            Ok(envelope.body.payload)
6249        }
6250    }
6251
6252    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6253    #[xml(rename = "ResetBasicEQ", ns(SERVICE_TYPE))]
6254    pub struct ResetBasicEqRequest {
6255        #[xml(rename = "InstanceID", ns(""))]
6256        pub instance_id: u32,
6257    }
6258
6259    #[derive(FromXml, Debug, Clone, PartialEq)]
6260    #[xml(rename = "ResetBasicEQResponse", ns(SERVICE_TYPE))]
6261    pub struct ResetBasicEqResponse {
6262        #[xml(rename = "Bass", ns(""))]
6263        pub bass: Option<i16>,
6264        #[xml(rename = "Treble", ns(""))]
6265        pub treble: Option<i16>,
6266        #[xml(rename = "Loudness", ns(""))]
6267        pub loudness: Option<bool>,
6268        #[xml(rename = "LeftVolume", ns(""))]
6269        pub left_volume: Option<u16>,
6270        #[xml(rename = "RightVolume", ns(""))]
6271        pub right_volume: Option<u16>,
6272    }
6273
6274    impl crate::DecodeSoapResponse for ResetBasicEqResponse {
6275        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6276            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6277            Ok(envelope.body.payload)
6278        }
6279    }
6280
6281    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6282    #[xml(rename = "ResetExtEQ", ns(SERVICE_TYPE))]
6283    pub struct ResetExtEqRequest {
6284        #[xml(rename = "InstanceID", ns(""))]
6285        pub instance_id: u32,
6286        #[xml(rename = "EQType", ns(""))]
6287        pub eq_type: String,
6288    }
6289
6290    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6291    #[xml(rename = "RestoreVolumePriorToRamp", ns(SERVICE_TYPE))]
6292    pub struct RestoreVolumePriorToRampRequest {
6293        #[xml(rename = "InstanceID", ns(""))]
6294        pub instance_id: u32,
6295        #[xml(rename = "Channel", ns(""))]
6296        pub channel: super::Channel,
6297    }
6298
6299    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6300    #[xml(rename = "SetBass", ns(SERVICE_TYPE))]
6301    pub struct SetBassRequest {
6302        #[xml(rename = "InstanceID", ns(""))]
6303        pub instance_id: u32,
6304        #[xml(rename = "DesiredBass", ns(""))]
6305        pub desired_bass: i16,
6306    }
6307
6308    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6309    #[xml(rename = "SetChannelMap", ns(SERVICE_TYPE))]
6310    pub struct SetChannelMapRequest {
6311        #[xml(rename = "InstanceID", ns(""))]
6312        pub instance_id: u32,
6313        #[xml(rename = "ChannelMap", ns(""))]
6314        pub channel_map: String,
6315    }
6316
6317    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6318    #[xml(rename = "SetEQ", ns(SERVICE_TYPE))]
6319    pub struct SetEqRequest {
6320        #[xml(rename = "InstanceID", ns(""))]
6321        pub instance_id: u32,
6322        /// Allowed values `DialogLevel` (bool) / `MusicSurroundLevel` (-15/+15) /  `NightMode` (bool) / `SubGain` (-10/+10) / `SurroundEnable` (bool) / `SurroundLevel` (-15/+15) / `SurroundMode` (0 = ambient, 1 = full) / `HeightChannelLevel` (-10/+10)
6323        #[xml(rename = "EQType", ns(""))]
6324        pub eq_type: String,
6325        /// Booleans required `1` for true or `0` for false, rest number as specified
6326        #[xml(rename = "DesiredValue", ns(""))]
6327        pub desired_value: i16,
6328    }
6329
6330    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6331    #[xml(rename = "SetLoudness", ns(SERVICE_TYPE))]
6332    pub struct SetLoudnessRequest {
6333        #[xml(rename = "InstanceID", ns(""))]
6334        pub instance_id: u32,
6335        #[xml(rename = "Channel", ns(""))]
6336        pub channel: super::Channel,
6337        #[xml(rename = "DesiredLoudness", ns(""))]
6338        pub desired_loudness: bool,
6339    }
6340
6341    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6342    #[xml(rename = "SetMute", ns(SERVICE_TYPE))]
6343    pub struct SetMuteRequest {
6344        #[xml(rename = "InstanceID", ns(""))]
6345        pub instance_id: u32,
6346        #[xml(rename = "Channel", ns(""))]
6347        pub channel: super::MuteChannel,
6348        #[xml(rename = "DesiredMute", ns(""))]
6349        pub desired_mute: bool,
6350    }
6351
6352    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6353    #[xml(rename = "SetOutputFixed", ns(SERVICE_TYPE))]
6354    pub struct SetOutputFixedRequest {
6355        #[xml(rename = "InstanceID", ns(""))]
6356        pub instance_id: u32,
6357        #[xml(rename = "DesiredFixed", ns(""))]
6358        pub desired_fixed: bool,
6359    }
6360
6361    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6362    #[xml(rename = "SetRelativeVolume", ns(SERVICE_TYPE))]
6363    pub struct SetRelativeVolumeRequest {
6364        #[xml(rename = "InstanceID", ns(""))]
6365        pub instance_id: u32,
6366        #[xml(rename = "Channel", ns(""))]
6367        pub channel: super::Channel,
6368        #[xml(rename = "Adjustment", ns(""))]
6369        pub adjustment: i32,
6370    }
6371
6372    #[derive(FromXml, Debug, Clone, PartialEq)]
6373    #[xml(rename = "SetRelativeVolumeResponse", ns(SERVICE_TYPE))]
6374    pub struct SetRelativeVolumeResponse {
6375        #[xml(rename = "NewVolume", ns(""))]
6376        pub new_volume: Option<u16>,
6377    }
6378
6379    impl crate::DecodeSoapResponse for SetRelativeVolumeResponse {
6380        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
6381            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
6382            Ok(envelope.body.payload)
6383        }
6384    }
6385
6386    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6387    #[xml(rename = "SetRoomCalibrationStatus", ns(SERVICE_TYPE))]
6388    pub struct SetRoomCalibrationStatusRequest {
6389        #[xml(rename = "InstanceID", ns(""))]
6390        pub instance_id: u32,
6391        #[xml(rename = "RoomCalibrationEnabled", ns(""))]
6392        pub room_calibration_enabled: bool,
6393    }
6394
6395    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6396    #[xml(rename = "SetRoomCalibrationX", ns(SERVICE_TYPE))]
6397    pub struct SetRoomCalibrationXRequest {
6398        #[xml(rename = "InstanceID", ns(""))]
6399        pub instance_id: u32,
6400        #[xml(rename = "CalibrationID", ns(""))]
6401        pub calibration_id: String,
6402        #[xml(rename = "Coefficients", ns(""))]
6403        pub coefficients: String,
6404        #[xml(rename = "CalibrationMode", ns(""))]
6405        pub calibration_mode: String,
6406    }
6407
6408    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6409    #[xml(rename = "SetTreble", ns(SERVICE_TYPE))]
6410    pub struct SetTrebleRequest {
6411        #[xml(rename = "InstanceID", ns(""))]
6412        pub instance_id: u32,
6413        /// between -10 and 10
6414        #[xml(rename = "DesiredTreble", ns(""))]
6415        pub desired_treble: i16,
6416    }
6417
6418    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6419    #[xml(rename = "SetVolume", ns(SERVICE_TYPE))]
6420    pub struct SetVolumeRequest {
6421        #[xml(rename = "InstanceID", ns(""))]
6422        pub instance_id: u32,
6423        #[xml(rename = "Channel", ns(""))]
6424        pub channel: super::Channel,
6425        #[xml(rename = "DesiredVolume", ns(""))]
6426        pub desired_volume: u16,
6427    }
6428
6429    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
6430    #[xml(rename = "SetVolumeDB", ns(SERVICE_TYPE))]
6431    pub struct SetVolumeDbRequest {
6432        #[xml(rename = "InstanceID", ns(""))]
6433        pub instance_id: u32,
6434        #[xml(rename = "Channel", ns(""))]
6435        pub channel: super::Channel,
6436        #[xml(rename = "DesiredVolume", ns(""))]
6437        pub desired_volume: i16,
6438    }
6439
6440    /// A parsed event produced by the `RenderingControl` service.
6441    /// Use `SonosDevice::subscribe_rendering_control()` to obtain an event
6442    /// stream that produces these.
6443    #[derive(Debug, Clone, PartialEq, Default)]
6444    pub struct RenderingControlEvent {
6445        pub last_change: Option<DecodeXmlString<RenderingControlLastChangeMap>>,
6446    }
6447
6448    #[derive(FromXml, Debug, Clone, PartialEq)]
6449    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
6450    struct RenderingControlPropertySet {
6451        pub properties: Vec<RenderingControlProperty>,
6452    }
6453
6454    #[derive(FromXml, Debug, Clone, PartialEq)]
6455    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
6456    struct RenderingControlProperty {
6457        #[xml(rename = "LastChange", ns(""))]
6458        pub last_change: Option<DecodeXmlString<RenderingControlLastChangeMap>>,
6459    }
6460
6461    impl DecodeXml for RenderingControlEvent {
6462        fn decode_xml(xml: &str) -> crate::Result<Self> {
6463            let mut result = Self::default();
6464            let set: RenderingControlPropertySet = instant_xml::from_str(xml)?;
6465            for prop in set.properties {
6466                if let Some(v) = prop.last_change {
6467                    result.last_change.replace(v);
6468                }
6469            }
6470            Ok(result)
6471        }
6472    }
6473
6474    impl crate::SonosDevice {
6475        /// Subscribe to events from the `RenderingControl` service on this device
6476        pub async fn subscribe_rendering_control(
6477            &self,
6478        ) -> crate::Result<crate::upnp::EventStream<RenderingControlEvent>> {
6479            self.subscribe_helper(&SERVICE_TYPE).await
6480        }
6481    }
6482
6483    #[derive(Debug, Clone, PartialEq, Default)]
6484    pub struct RenderingControlLastChange {
6485        pub channel: Option<super::Channel>,
6486        pub channel_map: Option<String>,
6487        pub eq_type: Option<String>,
6488        pub instance_id: Option<u32>,
6489        pub left_volume: Option<u16>,
6490        pub mute_channel: Option<super::MuteChannel>,
6491        pub program_uri: Option<String>,
6492        pub ramp_time_seconds: Option<u32>,
6493        pub ramp_type: Option<super::RampType>,
6494        pub reset_volume_after: Option<bool>,
6495        pub right_volume: Option<u16>,
6496        pub volume_adjustment: Option<i32>,
6497        pub audio_delay: Option<String>,
6498        pub audio_delay_left_rear: Option<String>,
6499        pub audio_delay_right_rear: Option<String>,
6500        pub bass: Option<i16>,
6501        pub dialog_level: Option<String>,
6502        pub eq_value: Option<i16>,
6503        pub headphone_connected: Option<bool>,
6504        pub loudness: Option<bool>,
6505        pub music_surround_level: Option<String>,
6506        pub mute: Option<bool>,
6507        pub night_mode: Option<bool>,
6508        pub output_fixed: Option<bool>,
6509        pub preset_name_list: Option<String>,
6510        pub room_calibration_available: Option<bool>,
6511        pub room_calibration_calibration_mode: Option<String>,
6512        pub room_calibration_coefficients: Option<String>,
6513        pub room_calibration_enabled: Option<bool>,
6514        pub room_calibration_id: Option<String>,
6515        pub speaker_size: Option<u32>,
6516        pub sub_crossover: Option<String>,
6517        pub sub_enabled: Option<bool>,
6518        pub sub_gain: Option<String>,
6519        pub sub_polarity: Option<String>,
6520        pub supports_output_fixed: Option<bool>,
6521        pub surround_enabled: Option<bool>,
6522        pub surround_level: Option<String>,
6523        pub surround_mode: Option<String>,
6524        pub treble: Option<i16>,
6525        pub volume: Option<u16>,
6526        pub volume_db: Option<i16>,
6527    }
6528
6529    #[derive(FromXml)]
6530    #[xml(rename = "Channel", ns(LAST_CHANGE_NS))]
6531    #[allow(non_camel_case_types)]
6532    struct RenderingControlLastChangeChannel {
6533        #[xml(attribute)]
6534        val: Option<super::Channel>,
6535    }
6536
6537    #[derive(FromXml)]
6538    #[xml(rename = "ChannelMap", ns(LAST_CHANGE_NS))]
6539    #[allow(non_camel_case_types)]
6540    struct RenderingControlLastChangeChannelMap {
6541        #[xml(attribute)]
6542        val: Option<String>,
6543    }
6544
6545    #[derive(FromXml)]
6546    #[xml(rename = "EQType", ns(LAST_CHANGE_NS))]
6547    #[allow(non_camel_case_types)]
6548    struct RenderingControlLastChangeEQType {
6549        #[xml(attribute)]
6550        val: Option<String>,
6551    }
6552
6553    #[derive(FromXml)]
6554    #[xml(rename = "InstanceID", ns(LAST_CHANGE_NS))]
6555    #[allow(non_camel_case_types)]
6556    struct RenderingControlLastChangeInstanceID {
6557        #[xml(attribute)]
6558        val: Option<u32>,
6559    }
6560
6561    #[derive(FromXml)]
6562    #[xml(rename = "LeftVolume", ns(LAST_CHANGE_NS))]
6563    #[allow(non_camel_case_types)]
6564    struct RenderingControlLastChangeLeftVolume {
6565        #[xml(attribute)]
6566        val: Option<u16>,
6567    }
6568
6569    #[derive(FromXml)]
6570    #[xml(rename = "MuteChannel", ns(LAST_CHANGE_NS))]
6571    #[allow(non_camel_case_types)]
6572    struct RenderingControlLastChangeMuteChannel {
6573        #[xml(attribute)]
6574        val: Option<super::MuteChannel>,
6575    }
6576
6577    #[derive(FromXml)]
6578    #[xml(rename = "ProgramURI", ns(LAST_CHANGE_NS))]
6579    #[allow(non_camel_case_types)]
6580    struct RenderingControlLastChangeProgramURI {
6581        #[xml(attribute)]
6582        val: Option<String>,
6583    }
6584
6585    #[derive(FromXml)]
6586    #[xml(rename = "RampTimeSeconds", ns(LAST_CHANGE_NS))]
6587    #[allow(non_camel_case_types)]
6588    struct RenderingControlLastChangeRampTimeSeconds {
6589        #[xml(attribute)]
6590        val: Option<u32>,
6591    }
6592
6593    #[derive(FromXml)]
6594    #[xml(rename = "RampType", ns(LAST_CHANGE_NS))]
6595    #[allow(non_camel_case_types)]
6596    struct RenderingControlLastChangeRampType {
6597        #[xml(attribute)]
6598        val: Option<super::RampType>,
6599    }
6600
6601    #[derive(FromXml)]
6602    #[xml(rename = "ResetVolumeAfter", ns(LAST_CHANGE_NS))]
6603    #[allow(non_camel_case_types)]
6604    struct RenderingControlLastChangeResetVolumeAfter {
6605        #[xml(attribute)]
6606        val: Option<bool>,
6607    }
6608
6609    #[derive(FromXml)]
6610    #[xml(rename = "RightVolume", ns(LAST_CHANGE_NS))]
6611    #[allow(non_camel_case_types)]
6612    struct RenderingControlLastChangeRightVolume {
6613        #[xml(attribute)]
6614        val: Option<u16>,
6615    }
6616
6617    #[derive(FromXml)]
6618    #[xml(rename = "VolumeAdjustment", ns(LAST_CHANGE_NS))]
6619    #[allow(non_camel_case_types)]
6620    struct RenderingControlLastChangeVolumeAdjustment {
6621        #[xml(attribute)]
6622        val: Option<i32>,
6623    }
6624
6625    #[derive(FromXml)]
6626    #[xml(rename = "AudioDelay", ns(LAST_CHANGE_NS))]
6627    #[allow(non_camel_case_types)]
6628    struct RenderingControlLastChangeAudioDelay {
6629        #[xml(attribute)]
6630        val: Option<String>,
6631    }
6632
6633    #[derive(FromXml)]
6634    #[xml(rename = "AudioDelayLeftRear", ns(LAST_CHANGE_NS))]
6635    #[allow(non_camel_case_types)]
6636    struct RenderingControlLastChangeAudioDelayLeftRear {
6637        #[xml(attribute)]
6638        val: Option<String>,
6639    }
6640
6641    #[derive(FromXml)]
6642    #[xml(rename = "AudioDelayRightRear", ns(LAST_CHANGE_NS))]
6643    #[allow(non_camel_case_types)]
6644    struct RenderingControlLastChangeAudioDelayRightRear {
6645        #[xml(attribute)]
6646        val: Option<String>,
6647    }
6648
6649    #[derive(FromXml)]
6650    #[xml(rename = "Bass", ns(LAST_CHANGE_NS))]
6651    #[allow(non_camel_case_types)]
6652    struct RenderingControlLastChangeBass {
6653        #[xml(attribute)]
6654        val: Option<i16>,
6655    }
6656
6657    #[derive(FromXml)]
6658    #[xml(rename = "DialogLevel", ns(LAST_CHANGE_NS))]
6659    #[allow(non_camel_case_types)]
6660    struct RenderingControlLastChangeDialogLevel {
6661        #[xml(attribute)]
6662        val: Option<String>,
6663    }
6664
6665    #[derive(FromXml)]
6666    #[xml(rename = "EQValue", ns(LAST_CHANGE_NS))]
6667    #[allow(non_camel_case_types)]
6668    struct RenderingControlLastChangeEQValue {
6669        #[xml(attribute)]
6670        val: Option<i16>,
6671    }
6672
6673    #[derive(FromXml)]
6674    #[xml(rename = "HeadphoneConnected", ns(LAST_CHANGE_NS))]
6675    #[allow(non_camel_case_types)]
6676    struct RenderingControlLastChangeHeadphoneConnected {
6677        #[xml(attribute)]
6678        val: Option<bool>,
6679    }
6680
6681    #[derive(FromXml)]
6682    #[xml(rename = "Loudness", ns(LAST_CHANGE_NS))]
6683    #[allow(non_camel_case_types)]
6684    struct RenderingControlLastChangeLoudness {
6685        #[xml(attribute)]
6686        val: Option<bool>,
6687    }
6688
6689    #[derive(FromXml)]
6690    #[xml(rename = "MusicSurroundLevel", ns(LAST_CHANGE_NS))]
6691    #[allow(non_camel_case_types)]
6692    struct RenderingControlLastChangeMusicSurroundLevel {
6693        #[xml(attribute)]
6694        val: Option<String>,
6695    }
6696
6697    #[derive(FromXml)]
6698    #[xml(rename = "Mute", ns(LAST_CHANGE_NS))]
6699    #[allow(non_camel_case_types)]
6700    struct RenderingControlLastChangeMute {
6701        #[xml(attribute)]
6702        val: Option<bool>,
6703    }
6704
6705    #[derive(FromXml)]
6706    #[xml(rename = "NightMode", ns(LAST_CHANGE_NS))]
6707    #[allow(non_camel_case_types)]
6708    struct RenderingControlLastChangeNightMode {
6709        #[xml(attribute)]
6710        val: Option<bool>,
6711    }
6712
6713    #[derive(FromXml)]
6714    #[xml(rename = "OutputFixed", ns(LAST_CHANGE_NS))]
6715    #[allow(non_camel_case_types)]
6716    struct RenderingControlLastChangeOutputFixed {
6717        #[xml(attribute)]
6718        val: Option<bool>,
6719    }
6720
6721    #[derive(FromXml)]
6722    #[xml(rename = "PresetNameList", ns(LAST_CHANGE_NS))]
6723    #[allow(non_camel_case_types)]
6724    struct RenderingControlLastChangePresetNameList {
6725        #[xml(attribute)]
6726        val: Option<String>,
6727    }
6728
6729    #[derive(FromXml)]
6730    #[xml(rename = "RoomCalibrationAvailable", ns(LAST_CHANGE_NS))]
6731    #[allow(non_camel_case_types)]
6732    struct RenderingControlLastChangeRoomCalibrationAvailable {
6733        #[xml(attribute)]
6734        val: Option<bool>,
6735    }
6736
6737    #[derive(FromXml)]
6738    #[xml(rename = "RoomCalibrationCalibrationMode", ns(LAST_CHANGE_NS))]
6739    #[allow(non_camel_case_types)]
6740    struct RenderingControlLastChangeRoomCalibrationCalibrationMode {
6741        #[xml(attribute)]
6742        val: Option<String>,
6743    }
6744
6745    #[derive(FromXml)]
6746    #[xml(rename = "RoomCalibrationCoefficients", ns(LAST_CHANGE_NS))]
6747    #[allow(non_camel_case_types)]
6748    struct RenderingControlLastChangeRoomCalibrationCoefficients {
6749        #[xml(attribute)]
6750        val: Option<String>,
6751    }
6752
6753    #[derive(FromXml)]
6754    #[xml(rename = "RoomCalibrationEnabled", ns(LAST_CHANGE_NS))]
6755    #[allow(non_camel_case_types)]
6756    struct RenderingControlLastChangeRoomCalibrationEnabled {
6757        #[xml(attribute)]
6758        val: Option<bool>,
6759    }
6760
6761    #[derive(FromXml)]
6762    #[xml(rename = "RoomCalibrationID", ns(LAST_CHANGE_NS))]
6763    #[allow(non_camel_case_types)]
6764    struct RenderingControlLastChangeRoomCalibrationID {
6765        #[xml(attribute)]
6766        val: Option<String>,
6767    }
6768
6769    #[derive(FromXml)]
6770    #[xml(rename = "SpeakerSize", ns(LAST_CHANGE_NS))]
6771    #[allow(non_camel_case_types)]
6772    struct RenderingControlLastChangeSpeakerSize {
6773        #[xml(attribute)]
6774        val: Option<u32>,
6775    }
6776
6777    #[derive(FromXml)]
6778    #[xml(rename = "SubCrossover", ns(LAST_CHANGE_NS))]
6779    #[allow(non_camel_case_types)]
6780    struct RenderingControlLastChangeSubCrossover {
6781        #[xml(attribute)]
6782        val: Option<String>,
6783    }
6784
6785    #[derive(FromXml)]
6786    #[xml(rename = "SubEnabled", ns(LAST_CHANGE_NS))]
6787    #[allow(non_camel_case_types)]
6788    struct RenderingControlLastChangeSubEnabled {
6789        #[xml(attribute)]
6790        val: Option<bool>,
6791    }
6792
6793    #[derive(FromXml)]
6794    #[xml(rename = "SubGain", ns(LAST_CHANGE_NS))]
6795    #[allow(non_camel_case_types)]
6796    struct RenderingControlLastChangeSubGain {
6797        #[xml(attribute)]
6798        val: Option<String>,
6799    }
6800
6801    #[derive(FromXml)]
6802    #[xml(rename = "SubPolarity", ns(LAST_CHANGE_NS))]
6803    #[allow(non_camel_case_types)]
6804    struct RenderingControlLastChangeSubPolarity {
6805        #[xml(attribute)]
6806        val: Option<String>,
6807    }
6808
6809    #[derive(FromXml)]
6810    #[xml(rename = "SupportsOutputFixed", ns(LAST_CHANGE_NS))]
6811    #[allow(non_camel_case_types)]
6812    struct RenderingControlLastChangeSupportsOutputFixed {
6813        #[xml(attribute)]
6814        val: Option<bool>,
6815    }
6816
6817    #[derive(FromXml)]
6818    #[xml(rename = "SurroundEnabled", ns(LAST_CHANGE_NS))]
6819    #[allow(non_camel_case_types)]
6820    struct RenderingControlLastChangeSurroundEnabled {
6821        #[xml(attribute)]
6822        val: Option<bool>,
6823    }
6824
6825    #[derive(FromXml)]
6826    #[xml(rename = "SurroundLevel", ns(LAST_CHANGE_NS))]
6827    #[allow(non_camel_case_types)]
6828    struct RenderingControlLastChangeSurroundLevel {
6829        #[xml(attribute)]
6830        val: Option<String>,
6831    }
6832
6833    #[derive(FromXml)]
6834    #[xml(rename = "SurroundMode", ns(LAST_CHANGE_NS))]
6835    #[allow(non_camel_case_types)]
6836    struct RenderingControlLastChangeSurroundMode {
6837        #[xml(attribute)]
6838        val: Option<String>,
6839    }
6840
6841    #[derive(FromXml)]
6842    #[xml(rename = "Treble", ns(LAST_CHANGE_NS))]
6843    #[allow(non_camel_case_types)]
6844    struct RenderingControlLastChangeTreble {
6845        #[xml(attribute)]
6846        val: Option<i16>,
6847    }
6848
6849    #[derive(FromXml)]
6850    #[xml(rename = "Volume", ns(LAST_CHANGE_NS))]
6851    #[allow(non_camel_case_types)]
6852    struct RenderingControlLastChangeVolume {
6853        #[xml(attribute)]
6854        val: Option<u16>,
6855    }
6856
6857    #[derive(FromXml)]
6858    #[xml(rename = "VolumeDB", ns(LAST_CHANGE_NS))]
6859    #[allow(non_camel_case_types)]
6860    struct RenderingControlLastChangeVolumeDB {
6861        #[xml(attribute)]
6862        val: Option<i16>,
6863    }
6864
6865    const LAST_CHANGE_NS: &str = "urn:schemas-upnp-org:metadata-1-0/RCS/";
6866
6867    #[derive(FromXml)]
6868    #[xml(rename = "InstanceID", ns(LAST_CHANGE_NS))]
6869    struct RenderingControlLastChangeRootObject {
6870        #[xml(rename = "val", attribute)]
6871        object_instance_id_: u32,
6872
6873        channel: Option<RenderingControlLastChangeChannel>,
6874        channel_map: Option<RenderingControlLastChangeChannelMap>,
6875        eq_type: Option<RenderingControlLastChangeEQType>,
6876        instance_id: Option<RenderingControlLastChangeInstanceID>,
6877        left_volume: Option<RenderingControlLastChangeLeftVolume>,
6878        mute_channel: Option<RenderingControlLastChangeMuteChannel>,
6879        program_uri: Option<RenderingControlLastChangeProgramURI>,
6880        ramp_time_seconds: Option<RenderingControlLastChangeRampTimeSeconds>,
6881        ramp_type: Option<RenderingControlLastChangeRampType>,
6882        reset_volume_after: Option<RenderingControlLastChangeResetVolumeAfter>,
6883        right_volume: Option<RenderingControlLastChangeRightVolume>,
6884        volume_adjustment: Option<RenderingControlLastChangeVolumeAdjustment>,
6885        audio_delay: Option<RenderingControlLastChangeAudioDelay>,
6886        audio_delay_left_rear: Option<RenderingControlLastChangeAudioDelayLeftRear>,
6887        audio_delay_right_rear: Option<RenderingControlLastChangeAudioDelayRightRear>,
6888        bass: Option<RenderingControlLastChangeBass>,
6889        dialog_level: Option<RenderingControlLastChangeDialogLevel>,
6890        eq_value: Option<RenderingControlLastChangeEQValue>,
6891        headphone_connected: Option<RenderingControlLastChangeHeadphoneConnected>,
6892        loudness: Option<RenderingControlLastChangeLoudness>,
6893        music_surround_level: Option<RenderingControlLastChangeMusicSurroundLevel>,
6894        mute: Option<RenderingControlLastChangeMute>,
6895        night_mode: Option<RenderingControlLastChangeNightMode>,
6896        output_fixed: Option<RenderingControlLastChangeOutputFixed>,
6897        preset_name_list: Option<RenderingControlLastChangePresetNameList>,
6898        room_calibration_available: Option<RenderingControlLastChangeRoomCalibrationAvailable>,
6899        room_calibration_calibration_mode:
6900            Option<RenderingControlLastChangeRoomCalibrationCalibrationMode>,
6901        room_calibration_coefficients:
6902            Option<RenderingControlLastChangeRoomCalibrationCoefficients>,
6903        room_calibration_enabled: Option<RenderingControlLastChangeRoomCalibrationEnabled>,
6904        room_calibration_id: Option<RenderingControlLastChangeRoomCalibrationID>,
6905        speaker_size: Option<RenderingControlLastChangeSpeakerSize>,
6906        sub_crossover: Option<RenderingControlLastChangeSubCrossover>,
6907        sub_enabled: Option<RenderingControlLastChangeSubEnabled>,
6908        sub_gain: Option<RenderingControlLastChangeSubGain>,
6909        sub_polarity: Option<RenderingControlLastChangeSubPolarity>,
6910        supports_output_fixed: Option<RenderingControlLastChangeSupportsOutputFixed>,
6911        surround_enabled: Option<RenderingControlLastChangeSurroundEnabled>,
6912        surround_level: Option<RenderingControlLastChangeSurroundLevel>,
6913        surround_mode: Option<RenderingControlLastChangeSurroundMode>,
6914        treble: Option<RenderingControlLastChangeTreble>,
6915        volume: Option<RenderingControlLastChangeVolume>,
6916        volume_db: Option<RenderingControlLastChangeVolumeDB>,
6917    }
6918
6919    #[derive(Debug, Clone, PartialEq, Default)]
6920    pub struct RenderingControlLastChangeMap {
6921        pub map: std::collections::BTreeMap<u32, RenderingControlLastChange>,
6922    }
6923
6924    impl DecodeXml for RenderingControlLastChangeMap {
6925        fn decode_xml(xml: &str) -> crate::Result<Self> {
6926            #[derive(FromXml)]
6927            #[xml(ns(LAST_CHANGE_NS, r = "urn:schemas-rinconnetworks-com:metadata-1-0/"))]
6928            struct Event {
6929                instance: Vec<RenderingControlLastChangeRootObject>,
6930            }
6931
6932            let last_change: Event = instant_xml::from_str(xml)?;
6933            let mut map = std::collections::BTreeMap::new();
6934
6935            for item in last_change.instance {
6936                let mut result = RenderingControlLastChange::default();
6937
6938                result.channel = item.channel.and_then(|v| v.val);
6939
6940                result.channel_map = item.channel_map.and_then(|v| v.val);
6941
6942                result.eq_type = item.eq_type.and_then(|v| v.val);
6943
6944                result.instance_id = item.instance_id.and_then(|v| v.val);
6945
6946                result.left_volume = item.left_volume.and_then(|v| v.val);
6947
6948                result.mute_channel = item.mute_channel.and_then(|v| v.val);
6949
6950                result.program_uri = item.program_uri.and_then(|v| v.val);
6951
6952                result.ramp_time_seconds = item.ramp_time_seconds.and_then(|v| v.val);
6953
6954                result.ramp_type = item.ramp_type.and_then(|v| v.val);
6955
6956                result.reset_volume_after = item.reset_volume_after.and_then(|v| v.val);
6957
6958                result.right_volume = item.right_volume.and_then(|v| v.val);
6959
6960                result.volume_adjustment = item.volume_adjustment.and_then(|v| v.val);
6961
6962                result.audio_delay = item.audio_delay.and_then(|v| v.val);
6963
6964                result.audio_delay_left_rear = item.audio_delay_left_rear.and_then(|v| v.val);
6965
6966                result.audio_delay_right_rear = item.audio_delay_right_rear.and_then(|v| v.val);
6967
6968                result.bass = item.bass.and_then(|v| v.val);
6969
6970                result.dialog_level = item.dialog_level.and_then(|v| v.val);
6971
6972                result.eq_value = item.eq_value.and_then(|v| v.val);
6973
6974                result.headphone_connected = item.headphone_connected.and_then(|v| v.val);
6975
6976                result.loudness = item.loudness.and_then(|v| v.val);
6977
6978                result.music_surround_level = item.music_surround_level.and_then(|v| v.val);
6979
6980                result.mute = item.mute.and_then(|v| v.val);
6981
6982                result.night_mode = item.night_mode.and_then(|v| v.val);
6983
6984                result.output_fixed = item.output_fixed.and_then(|v| v.val);
6985
6986                result.preset_name_list = item.preset_name_list.and_then(|v| v.val);
6987
6988                result.room_calibration_available =
6989                    item.room_calibration_available.and_then(|v| v.val);
6990
6991                result.room_calibration_calibration_mode =
6992                    item.room_calibration_calibration_mode.and_then(|v| v.val);
6993
6994                result.room_calibration_coefficients =
6995                    item.room_calibration_coefficients.and_then(|v| v.val);
6996
6997                result.room_calibration_enabled = item.room_calibration_enabled.and_then(|v| v.val);
6998
6999                result.room_calibration_id = item.room_calibration_id.and_then(|v| v.val);
7000
7001                result.speaker_size = item.speaker_size.and_then(|v| v.val);
7002
7003                result.sub_crossover = item.sub_crossover.and_then(|v| v.val);
7004
7005                result.sub_enabled = item.sub_enabled.and_then(|v| v.val);
7006
7007                result.sub_gain = item.sub_gain.and_then(|v| v.val);
7008
7009                result.sub_polarity = item.sub_polarity.and_then(|v| v.val);
7010
7011                result.supports_output_fixed = item.supports_output_fixed.and_then(|v| v.val);
7012
7013                result.surround_enabled = item.surround_enabled.and_then(|v| v.val);
7014
7015                result.surround_level = item.surround_level.and_then(|v| v.val);
7016
7017                result.surround_mode = item.surround_mode.and_then(|v| v.val);
7018
7019                result.treble = item.treble.and_then(|v| v.val);
7020
7021                result.volume = item.volume.and_then(|v| v.val);
7022
7023                result.volume_db = item.volume_db.and_then(|v| v.val);
7024
7025                map.insert(item.object_instance_id_, result);
7026            }
7027
7028            Ok(RenderingControlLastChangeMap { map })
7029        }
7030    }
7031}
7032
7033#[derive(PartialEq, Debug, Clone, Eq, Default)]
7034pub enum Channel {
7035    #[default]
7036    Master,
7037    Lf,
7038    Rf,
7039
7040    /// Allows passing a value that was not known at the
7041    /// time that this crate was generated from the available
7042    /// device descriptions
7043    Unspecified(String),
7044}
7045
7046impl ToString for Channel {
7047    fn to_string(&self) -> String {
7048        match self {
7049            Channel::Master => "Master".to_string(),
7050            Channel::Lf => "LF".to_string(),
7051            Channel::Rf => "RF".to_string(),
7052            Channel::Unspecified(s) => s.to_string(),
7053        }
7054    }
7055}
7056
7057impl FromStr for Channel {
7058    type Err = crate::Error;
7059    fn from_str(s: &str) -> Result<Channel> {
7060        match s {
7061            "Master" => Ok(Channel::Master),
7062            "LF" => Ok(Channel::Lf),
7063            "RF" => Ok(Channel::Rf),
7064            s => Ok(Channel::Unspecified(s.to_string())),
7065        }
7066    }
7067}
7068
7069impl instant_xml::ToXml for Channel {
7070    fn serialize<W: std::fmt::Write + ?Sized>(
7071        &self,
7072        field: Option<instant_xml::Id<'_>>,
7073        serializer: &mut instant_xml::Serializer<W>,
7074    ) -> std::result::Result<(), instant_xml::Error> {
7075        self.to_string().serialize(field, serializer)
7076    }
7077
7078    fn present(&self) -> bool {
7079        true
7080    }
7081}
7082
7083impl<'xml> instant_xml::FromXml<'xml> for Channel {
7084    #[inline]
7085    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
7086        match field {
7087            Some(field) => id == field,
7088            None => false,
7089        }
7090    }
7091
7092    fn deserialize<'cx>(
7093        into: &mut Self::Accumulator,
7094        field: &'static str,
7095        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
7096    ) -> std::result::Result<(), instant_xml::Error> {
7097        if into.is_some() {
7098            return Err(instant_xml::Error::DuplicateValue(field));
7099        }
7100
7101        match deserializer.take_str()? {
7102            Some(value) => {
7103                let parsed: Channel = value.parse().map_err(|err| {
7104                    instant_xml::Error::Other(format!(
7105                        "invalid value for field {field}: {value}: {err:#}"
7106                    ))
7107                })?;
7108                *into = Some(parsed);
7109                Ok(())
7110            }
7111            None => Err(instant_xml::Error::MissingValue(field)),
7112        }
7113    }
7114
7115    type Accumulator = Option<Channel>;
7116    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
7117}
7118
7119#[derive(PartialEq, Debug, Clone, Eq, Default)]
7120pub enum MuteChannel {
7121    #[default]
7122    Master,
7123    Lf,
7124    Rf,
7125    SpeakerOnly,
7126
7127    /// Allows passing a value that was not known at the
7128    /// time that this crate was generated from the available
7129    /// device descriptions
7130    Unspecified(String),
7131}
7132
7133impl ToString for MuteChannel {
7134    fn to_string(&self) -> String {
7135        match self {
7136            MuteChannel::Master => "Master".to_string(),
7137            MuteChannel::Lf => "LF".to_string(),
7138            MuteChannel::Rf => "RF".to_string(),
7139            MuteChannel::SpeakerOnly => "SpeakerOnly".to_string(),
7140            MuteChannel::Unspecified(s) => s.to_string(),
7141        }
7142    }
7143}
7144
7145impl FromStr for MuteChannel {
7146    type Err = crate::Error;
7147    fn from_str(s: &str) -> Result<MuteChannel> {
7148        match s {
7149            "Master" => Ok(MuteChannel::Master),
7150            "LF" => Ok(MuteChannel::Lf),
7151            "RF" => Ok(MuteChannel::Rf),
7152            "SpeakerOnly" => Ok(MuteChannel::SpeakerOnly),
7153            s => Ok(MuteChannel::Unspecified(s.to_string())),
7154        }
7155    }
7156}
7157
7158impl instant_xml::ToXml for MuteChannel {
7159    fn serialize<W: std::fmt::Write + ?Sized>(
7160        &self,
7161        field: Option<instant_xml::Id<'_>>,
7162        serializer: &mut instant_xml::Serializer<W>,
7163    ) -> std::result::Result<(), instant_xml::Error> {
7164        self.to_string().serialize(field, serializer)
7165    }
7166
7167    fn present(&self) -> bool {
7168        true
7169    }
7170}
7171
7172impl<'xml> instant_xml::FromXml<'xml> for MuteChannel {
7173    #[inline]
7174    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
7175        match field {
7176            Some(field) => id == field,
7177            None => false,
7178        }
7179    }
7180
7181    fn deserialize<'cx>(
7182        into: &mut Self::Accumulator,
7183        field: &'static str,
7184        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
7185    ) -> std::result::Result<(), instant_xml::Error> {
7186        if into.is_some() {
7187            return Err(instant_xml::Error::DuplicateValue(field));
7188        }
7189
7190        match deserializer.take_str()? {
7191            Some(value) => {
7192                let parsed: MuteChannel = value.parse().map_err(|err| {
7193                    instant_xml::Error::Other(format!(
7194                        "invalid value for field {field}: {value}: {err:#}"
7195                    ))
7196                })?;
7197                *into = Some(parsed);
7198                Ok(())
7199            }
7200            None => Err(instant_xml::Error::MissingValue(field)),
7201        }
7202    }
7203
7204    type Accumulator = Option<MuteChannel>;
7205    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
7206}
7207
7208#[derive(PartialEq, Debug, Clone, Eq, Default)]
7209pub enum RampType {
7210    #[default]
7211    SleepTimerRampType,
7212    AlarmRampType,
7213    AutoplayRampType,
7214
7215    /// Allows passing a value that was not known at the
7216    /// time that this crate was generated from the available
7217    /// device descriptions
7218    Unspecified(String),
7219}
7220
7221impl ToString for RampType {
7222    fn to_string(&self) -> String {
7223        match self {
7224            RampType::SleepTimerRampType => "SLEEP_TIMER_RAMP_TYPE".to_string(),
7225            RampType::AlarmRampType => "ALARM_RAMP_TYPE".to_string(),
7226            RampType::AutoplayRampType => "AUTOPLAY_RAMP_TYPE".to_string(),
7227            RampType::Unspecified(s) => s.to_string(),
7228        }
7229    }
7230}
7231
7232impl FromStr for RampType {
7233    type Err = crate::Error;
7234    fn from_str(s: &str) -> Result<RampType> {
7235        match s {
7236            "SLEEP_TIMER_RAMP_TYPE" => Ok(RampType::SleepTimerRampType),
7237            "ALARM_RAMP_TYPE" => Ok(RampType::AlarmRampType),
7238            "AUTOPLAY_RAMP_TYPE" => Ok(RampType::AutoplayRampType),
7239            s => Ok(RampType::Unspecified(s.to_string())),
7240        }
7241    }
7242}
7243
7244impl instant_xml::ToXml for RampType {
7245    fn serialize<W: std::fmt::Write + ?Sized>(
7246        &self,
7247        field: Option<instant_xml::Id<'_>>,
7248        serializer: &mut instant_xml::Serializer<W>,
7249    ) -> std::result::Result<(), instant_xml::Error> {
7250        self.to_string().serialize(field, serializer)
7251    }
7252
7253    fn present(&self) -> bool {
7254        true
7255    }
7256}
7257
7258impl<'xml> instant_xml::FromXml<'xml> for RampType {
7259    #[inline]
7260    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
7261        match field {
7262            Some(field) => id == field,
7263            None => false,
7264        }
7265    }
7266
7267    fn deserialize<'cx>(
7268        into: &mut Self::Accumulator,
7269        field: &'static str,
7270        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
7271    ) -> std::result::Result<(), instant_xml::Error> {
7272        if into.is_some() {
7273            return Err(instant_xml::Error::DuplicateValue(field));
7274        }
7275
7276        match deserializer.take_str()? {
7277            Some(value) => {
7278                let parsed: RampType = value.parse().map_err(|err| {
7279                    instant_xml::Error::Other(format!(
7280                        "invalid value for field {field}: {value}: {err:#}"
7281                    ))
7282                })?;
7283                *into = Some(parsed);
7284                Ok(())
7285            }
7286            None => Err(instant_xml::Error::MissingValue(field)),
7287        }
7288    }
7289
7290    type Accumulator = Option<RampType>;
7291    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
7292}
7293
7294/// Request and Response types for the `SystemProperties` service.
7295pub mod system_properties {
7296    use super::*;
7297
7298    /// URN for the `SystemProperties` service.
7299    /// `urn:schemas-upnp-org:service:SystemProperties:1`
7300    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:SystemProperties:1";
7301
7302    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7303    #[xml(rename = "AddAccountX", ns(SERVICE_TYPE))]
7304    pub struct AddAccountXRequest {
7305        #[xml(rename = "AccountType", ns(""))]
7306        pub account_type: u32,
7307        #[xml(rename = "AccountID", ns(""))]
7308        pub account_id: String,
7309        #[xml(rename = "AccountPassword", ns(""))]
7310        pub account_password: String,
7311    }
7312
7313    #[derive(FromXml, Debug, Clone, PartialEq)]
7314    #[xml(rename = "AddAccountXResponse", ns(SERVICE_TYPE))]
7315    pub struct AddAccountXResponse {
7316        #[xml(rename = "AccountUDN", ns(""))]
7317        pub account_udn: Option<String>,
7318    }
7319
7320    impl crate::DecodeSoapResponse for AddAccountXResponse {
7321        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7322            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7323            Ok(envelope.body.payload)
7324        }
7325    }
7326
7327    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7328    #[xml(rename = "AddOAuthAccountX", ns(SERVICE_TYPE))]
7329    pub struct AddOAuthAccountXRequest {
7330        #[xml(rename = "AccountType", ns(""))]
7331        pub account_type: u32,
7332        #[xml(rename = "AccountToken", ns(""))]
7333        pub account_token: String,
7334        #[xml(rename = "AccountKey", ns(""))]
7335        pub account_key: String,
7336        #[xml(rename = "OAuthDeviceID", ns(""))]
7337        pub o_auth_device_id: String,
7338        #[xml(rename = "AuthorizationCode", ns(""))]
7339        pub authorization_code: String,
7340        #[xml(rename = "RedirectURI", ns(""))]
7341        pub redirect_uri: String,
7342        #[xml(rename = "UserIdHashCode", ns(""))]
7343        pub user_id_hash_code: String,
7344        #[xml(rename = "AccountTier", ns(""))]
7345        pub account_tier: u32,
7346    }
7347
7348    #[derive(FromXml, Debug, Clone, PartialEq)]
7349    #[xml(rename = "AddOAuthAccountXResponse", ns(SERVICE_TYPE))]
7350    pub struct AddOAuthAccountXResponse {
7351        #[xml(rename = "AccountUDN", ns(""))]
7352        pub account_udn: Option<String>,
7353        #[xml(rename = "AccountNickname", ns(""))]
7354        pub account_nickname: Option<String>,
7355    }
7356
7357    impl crate::DecodeSoapResponse for AddOAuthAccountXResponse {
7358        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7359            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7360            Ok(envelope.body.payload)
7361        }
7362    }
7363
7364    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7365    #[xml(rename = "EditAccountMd", ns(SERVICE_TYPE))]
7366    pub struct EditAccountMdRequest {
7367        #[xml(rename = "AccountType", ns(""))]
7368        pub account_type: u32,
7369        #[xml(rename = "AccountID", ns(""))]
7370        pub account_id: String,
7371        #[xml(rename = "NewAccountMd", ns(""))]
7372        pub new_account_md: String,
7373    }
7374
7375    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7376    #[xml(rename = "EditAccountPasswordX", ns(SERVICE_TYPE))]
7377    pub struct EditAccountPasswordXRequest {
7378        #[xml(rename = "AccountType", ns(""))]
7379        pub account_type: u32,
7380        #[xml(rename = "AccountID", ns(""))]
7381        pub account_id: String,
7382        #[xml(rename = "NewAccountPassword", ns(""))]
7383        pub new_account_password: String,
7384    }
7385
7386    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7387    #[xml(rename = "EnableRDM", ns(SERVICE_TYPE))]
7388    pub struct EnableRdmRequest {
7389        #[xml(rename = "RDMValue", ns(""))]
7390        pub rdm_value: bool,
7391    }
7392
7393    #[derive(FromXml, Debug, Clone, PartialEq)]
7394    #[xml(rename = "GetRDMResponse", ns(SERVICE_TYPE))]
7395    pub struct GetRdmResponse {
7396        #[xml(rename = "RDMValue", ns(""))]
7397        pub rdm_value: Option<bool>,
7398    }
7399
7400    impl crate::DecodeSoapResponse for GetRdmResponse {
7401        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7402            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7403            Ok(envelope.body.payload)
7404        }
7405    }
7406
7407    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7408    #[xml(rename = "GetString", ns(SERVICE_TYPE))]
7409    pub struct GetStringRequest {
7410        /// The key for this variable
7411        #[xml(rename = "VariableName", ns(""))]
7412        pub variable_name: String,
7413    }
7414
7415    #[derive(FromXml, Debug, Clone, PartialEq)]
7416    #[xml(rename = "GetStringResponse", ns(SERVICE_TYPE))]
7417    pub struct GetStringResponse {
7418        #[xml(rename = "StringValue", ns(""))]
7419        pub string_value: Option<String>,
7420    }
7421
7422    impl crate::DecodeSoapResponse for GetStringResponse {
7423        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7424            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7425            Ok(envelope.body.payload)
7426        }
7427    }
7428
7429    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7430    #[xml(rename = "GetWebCode", ns(SERVICE_TYPE))]
7431    pub struct GetWebCodeRequest {
7432        #[xml(rename = "AccountType", ns(""))]
7433        pub account_type: u32,
7434    }
7435
7436    #[derive(FromXml, Debug, Clone, PartialEq)]
7437    #[xml(rename = "GetWebCodeResponse", ns(SERVICE_TYPE))]
7438    pub struct GetWebCodeResponse {
7439        #[xml(rename = "WebCode", ns(""))]
7440        pub web_code: Option<String>,
7441    }
7442
7443    impl crate::DecodeSoapResponse for GetWebCodeResponse {
7444        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7445            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7446            Ok(envelope.body.payload)
7447        }
7448    }
7449
7450    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7451    #[xml(rename = "ProvisionCredentialedTrialAccountX", ns(SERVICE_TYPE))]
7452    pub struct ProvisionCredentialedTrialAccountXRequest {
7453        #[xml(rename = "AccountType", ns(""))]
7454        pub account_type: u32,
7455        #[xml(rename = "AccountID", ns(""))]
7456        pub account_id: String,
7457        #[xml(rename = "AccountPassword", ns(""))]
7458        pub account_password: String,
7459    }
7460
7461    #[derive(FromXml, Debug, Clone, PartialEq)]
7462    #[xml(
7463        rename = "ProvisionCredentialedTrialAccountXResponse",
7464        ns(SERVICE_TYPE)
7465    )]
7466    pub struct ProvisionCredentialedTrialAccountXResponse {
7467        #[xml(rename = "IsExpired", ns(""))]
7468        pub is_expired: Option<bool>,
7469        #[xml(rename = "AccountUDN", ns(""))]
7470        pub account_udn: Option<String>,
7471    }
7472
7473    impl crate::DecodeSoapResponse for ProvisionCredentialedTrialAccountXResponse {
7474        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7475            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7476            Ok(envelope.body.payload)
7477        }
7478    }
7479
7480    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7481    #[xml(rename = "RefreshAccountCredentialsX", ns(SERVICE_TYPE))]
7482    pub struct RefreshAccountCredentialsXRequest {
7483        #[xml(rename = "AccountType", ns(""))]
7484        pub account_type: u32,
7485        #[xml(rename = "AccountUID", ns(""))]
7486        pub account_uid: u32,
7487        #[xml(rename = "AccountToken", ns(""))]
7488        pub account_token: String,
7489        #[xml(rename = "AccountKey", ns(""))]
7490        pub account_key: String,
7491    }
7492
7493    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7494    #[xml(rename = "Remove", ns(SERVICE_TYPE))]
7495    pub struct RemoveRequest {
7496        /// The key for this variable
7497        #[xml(rename = "VariableName", ns(""))]
7498        pub variable_name: String,
7499    }
7500
7501    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7502    #[xml(rename = "RemoveAccount", ns(SERVICE_TYPE))]
7503    pub struct RemoveAccountRequest {
7504        #[xml(rename = "AccountType", ns(""))]
7505        pub account_type: u32,
7506        #[xml(rename = "AccountID", ns(""))]
7507        pub account_id: String,
7508    }
7509
7510    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7511    #[xml(rename = "ReplaceAccountX", ns(SERVICE_TYPE))]
7512    pub struct ReplaceAccountXRequest {
7513        #[xml(rename = "AccountUDN", ns(""))]
7514        pub account_udn: String,
7515        #[xml(rename = "NewAccountID", ns(""))]
7516        pub new_account_id: String,
7517        #[xml(rename = "NewAccountPassword", ns(""))]
7518        pub new_account_password: String,
7519        #[xml(rename = "AccountToken", ns(""))]
7520        pub account_token: String,
7521        #[xml(rename = "AccountKey", ns(""))]
7522        pub account_key: String,
7523        #[xml(rename = "OAuthDeviceID", ns(""))]
7524        pub o_auth_device_id: String,
7525    }
7526
7527    #[derive(FromXml, Debug, Clone, PartialEq)]
7528    #[xml(rename = "ReplaceAccountXResponse", ns(SERVICE_TYPE))]
7529    pub struct ReplaceAccountXResponse {
7530        #[xml(rename = "NewAccountUDN", ns(""))]
7531        pub new_account_udn: Option<String>,
7532    }
7533
7534    impl crate::DecodeSoapResponse for ReplaceAccountXResponse {
7535        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7536            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7537            Ok(envelope.body.payload)
7538        }
7539    }
7540
7541    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7542    #[xml(rename = "SetAccountNicknameX", ns(SERVICE_TYPE))]
7543    pub struct SetAccountNicknameXRequest {
7544        #[xml(rename = "AccountUDN", ns(""))]
7545        pub account_udn: String,
7546        #[xml(rename = "AccountNickname", ns(""))]
7547        pub account_nickname: String,
7548    }
7549
7550    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7551    #[xml(rename = "SetString", ns(SERVICE_TYPE))]
7552    pub struct SetStringRequest {
7553        /// The key for this variable, use something unique
7554        #[xml(rename = "VariableName", ns(""))]
7555        pub variable_name: String,
7556        #[xml(rename = "StringValue", ns(""))]
7557        pub string_value: String,
7558    }
7559
7560    /// A parsed event produced by the `SystemProperties` service.
7561    /// Use `SonosDevice::subscribe_system_properties()` to obtain an event
7562    /// stream that produces these.
7563    #[derive(Debug, Clone, PartialEq, Default)]
7564    pub struct SystemPropertiesEvent {
7565        pub customer_id: Option<String>,
7566        pub third_party_hash: Option<String>,
7567        pub update_id: Option<u32>,
7568        pub update_idx: Option<u32>,
7569        pub voice_update_id: Option<u32>,
7570    }
7571
7572    #[derive(FromXml, Debug, Clone, PartialEq)]
7573    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7574    struct SystemPropertiesPropertySet {
7575        pub properties: Vec<SystemPropertiesProperty>,
7576    }
7577
7578    #[derive(FromXml, Debug, Clone, PartialEq)]
7579    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7580    struct SystemPropertiesProperty {
7581        #[xml(rename = "CustomerID", ns(""))]
7582        pub customer_id: Option<String>,
7583        #[xml(rename = "ThirdPartyHash", ns(""))]
7584        pub third_party_hash: Option<String>,
7585        #[xml(rename = "UpdateID", ns(""))]
7586        pub update_id: Option<u32>,
7587        #[xml(rename = "UpdateIDX", ns(""))]
7588        pub update_idx: Option<u32>,
7589        #[xml(rename = "VoiceUpdateID", ns(""))]
7590        pub voice_update_id: Option<u32>,
7591    }
7592
7593    impl DecodeXml for SystemPropertiesEvent {
7594        fn decode_xml(xml: &str) -> crate::Result<Self> {
7595            let mut result = Self::default();
7596            let set: SystemPropertiesPropertySet = instant_xml::from_str(xml)?;
7597            for prop in set.properties {
7598                if let Some(v) = prop.customer_id {
7599                    result.customer_id.replace(v);
7600                }
7601
7602                if let Some(v) = prop.third_party_hash {
7603                    result.third_party_hash.replace(v);
7604                }
7605
7606                if let Some(v) = prop.update_id {
7607                    result.update_id.replace(v);
7608                }
7609
7610                if let Some(v) = prop.update_idx {
7611                    result.update_idx.replace(v);
7612                }
7613
7614                if let Some(v) = prop.voice_update_id {
7615                    result.voice_update_id.replace(v);
7616                }
7617            }
7618            Ok(result)
7619        }
7620    }
7621
7622    impl crate::SonosDevice {
7623        /// Subscribe to events from the `SystemProperties` service on this device
7624        pub async fn subscribe_system_properties(
7625            &self,
7626        ) -> crate::Result<crate::upnp::EventStream<SystemPropertiesEvent>> {
7627            self.subscribe_helper(&SERVICE_TYPE).await
7628        }
7629    }
7630}
7631
7632/// Request and Response types for the `VirtualLineIn` service.
7633pub mod virtual_line_in {
7634    use super::*;
7635
7636    /// URN for the `VirtualLineIn` service.
7637    /// `urn:schemas-upnp-org:service:VirtualLineIn:1`
7638    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:VirtualLineIn:1";
7639
7640    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7641    #[xml(rename = "Next", ns(SERVICE_TYPE))]
7642    pub struct NextRequest {
7643        #[xml(rename = "InstanceID", ns(""))]
7644        pub instance_id: u32,
7645    }
7646
7647    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7648    #[xml(rename = "Pause", ns(SERVICE_TYPE))]
7649    pub struct PauseRequest {
7650        #[xml(rename = "InstanceID", ns(""))]
7651        pub instance_id: u32,
7652    }
7653
7654    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7655    #[xml(rename = "Play", ns(SERVICE_TYPE))]
7656    pub struct PlayRequest {
7657        #[xml(rename = "InstanceID", ns(""))]
7658        pub instance_id: u32,
7659        #[xml(rename = "Speed", ns(""))]
7660        pub speed: String,
7661    }
7662
7663    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7664    #[xml(rename = "Previous", ns(SERVICE_TYPE))]
7665    pub struct PreviousRequest {
7666        #[xml(rename = "InstanceID", ns(""))]
7667        pub instance_id: u32,
7668    }
7669
7670    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7671    #[xml(rename = "SetVolume", ns(SERVICE_TYPE))]
7672    pub struct SetVolumeRequest {
7673        #[xml(rename = "InstanceID", ns(""))]
7674        pub instance_id: u32,
7675        #[xml(rename = "DesiredVolume", ns(""))]
7676        pub desired_volume: u16,
7677    }
7678
7679    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7680    #[xml(rename = "StartTransmission", ns(SERVICE_TYPE))]
7681    pub struct StartTransmissionRequest {
7682        #[xml(rename = "InstanceID", ns(""))]
7683        pub instance_id: u32,
7684        #[xml(rename = "CoordinatorID", ns(""))]
7685        pub coordinator_id: String,
7686    }
7687
7688    #[derive(FromXml, Debug, Clone, PartialEq)]
7689    #[xml(rename = "StartTransmissionResponse", ns(SERVICE_TYPE))]
7690    pub struct StartTransmissionResponse {
7691        #[xml(rename = "CurrentTransportSettings", ns(""))]
7692        pub current_transport_settings: Option<String>,
7693    }
7694
7695    impl crate::DecodeSoapResponse for StartTransmissionResponse {
7696        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7697            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7698            Ok(envelope.body.payload)
7699        }
7700    }
7701
7702    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7703    #[xml(rename = "Stop", ns(SERVICE_TYPE))]
7704    pub struct StopRequest {
7705        #[xml(rename = "InstanceID", ns(""))]
7706        pub instance_id: u32,
7707    }
7708
7709    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7710    #[xml(rename = "StopTransmission", ns(SERVICE_TYPE))]
7711    pub struct StopTransmissionRequest {
7712        #[xml(rename = "InstanceID", ns(""))]
7713        pub instance_id: u32,
7714        #[xml(rename = "CoordinatorID", ns(""))]
7715        pub coordinator_id: String,
7716    }
7717
7718    /// A parsed event produced by the `VirtualLineIn` service.
7719    /// Use `SonosDevice::subscribe_virtual_line_in()` to obtain an event
7720    /// stream that produces these.
7721    #[derive(Debug, Clone, PartialEq, Default)]
7722    pub struct VirtualLineInEvent {
7723        pub current_track_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
7724        pub last_change: Option<String>,
7725    }
7726
7727    #[derive(FromXml, Debug, Clone, PartialEq)]
7728    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7729    struct VirtualLineInPropertySet {
7730        pub properties: Vec<VirtualLineInProperty>,
7731    }
7732
7733    #[derive(FromXml, Debug, Clone, PartialEq)]
7734    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7735    struct VirtualLineInProperty {
7736        #[xml(rename = "CurrentTrackMetaData", ns(""))]
7737        pub current_track_meta_data: Option<DecodeXmlString<crate::TrackMetaData>>,
7738        #[xml(rename = "LastChange", ns(""))]
7739        pub last_change: Option<String>,
7740    }
7741
7742    impl DecodeXml for VirtualLineInEvent {
7743        fn decode_xml(xml: &str) -> crate::Result<Self> {
7744            let mut result = Self::default();
7745            let set: VirtualLineInPropertySet = instant_xml::from_str(xml)?;
7746            for prop in set.properties {
7747                if let Some(v) = prop.current_track_meta_data {
7748                    result.current_track_meta_data.replace(v);
7749                }
7750
7751                if let Some(v) = prop.last_change {
7752                    result.last_change.replace(v);
7753                }
7754            }
7755            Ok(result)
7756        }
7757    }
7758
7759    impl crate::SonosDevice {
7760        /// Subscribe to events from the `VirtualLineIn` service on this device
7761        pub async fn subscribe_virtual_line_in(
7762            &self,
7763        ) -> crate::Result<crate::upnp::EventStream<VirtualLineInEvent>> {
7764            self.subscribe_helper(&SERVICE_TYPE).await
7765        }
7766    }
7767}
7768
7769/// Request and Response types for the `ZoneGroupTopology` service.
7770pub mod zone_group_topology {
7771    use super::*;
7772
7773    /// URN for the `ZoneGroupTopology` service.
7774    /// `urn:schemas-upnp-org:service:ZoneGroupTopology:1`
7775    pub const SERVICE_TYPE: &str = "urn:schemas-upnp-org:service:ZoneGroupTopology:1";
7776
7777    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7778    #[xml(rename = "BeginSoftwareUpdate", ns(SERVICE_TYPE))]
7779    pub struct BeginSoftwareUpdateRequest {
7780        #[xml(rename = "UpdateURL", ns(""))]
7781        pub update_url: String,
7782        #[xml(rename = "Flags", ns(""))]
7783        pub flags: u32,
7784        #[xml(rename = "ExtraOptions", ns(""))]
7785        pub extra_options: String,
7786    }
7787
7788    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7789    #[xml(rename = "CheckForUpdate", ns(SERVICE_TYPE))]
7790    pub struct CheckForUpdateRequest {
7791        #[xml(rename = "UpdateType", ns(""))]
7792        pub update_type: super::UpdateType,
7793        #[xml(rename = "CachedOnly", ns(""))]
7794        pub cached_only: bool,
7795        #[xml(rename = "Version", ns(""))]
7796        pub version: String,
7797    }
7798
7799    #[derive(FromXml, Debug, Clone, PartialEq)]
7800    #[xml(rename = "CheckForUpdateResponse", ns(SERVICE_TYPE))]
7801    pub struct CheckForUpdateResponse {
7802        #[xml(rename = "UpdateItem", ns(""))]
7803        pub update_item: Option<String>,
7804    }
7805
7806    impl crate::DecodeSoapResponse for CheckForUpdateResponse {
7807        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7808            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7809            Ok(envelope.body.payload)
7810        }
7811    }
7812
7813    #[derive(FromXml, Debug, Clone, PartialEq)]
7814    #[xml(rename = "GetZoneGroupAttributesResponse", ns(SERVICE_TYPE))]
7815    pub struct GetZoneGroupAttributesResponse {
7816        #[xml(rename = "CurrentZoneGroupName", ns(""))]
7817        pub current_zone_group_name: Option<String>,
7818        #[xml(rename = "CurrentZoneGroupID", ns(""))]
7819        pub current_zone_group_id: Option<String>,
7820        #[xml(rename = "CurrentZonePlayerUUIDsInGroup", ns(""))]
7821        pub current_zone_player_uuids_in_group: Option<String>,
7822        #[xml(rename = "CurrentMuseHouseholdId", ns(""))]
7823        pub current_muse_household_id: Option<String>,
7824    }
7825
7826    impl crate::DecodeSoapResponse for GetZoneGroupAttributesResponse {
7827        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7828            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7829            Ok(envelope.body.payload)
7830        }
7831    }
7832
7833    #[derive(FromXml, Debug, Clone, PartialEq)]
7834    #[xml(rename = "GetZoneGroupStateResponse", ns(SERVICE_TYPE))]
7835    pub struct GetZoneGroupStateResponse {
7836        #[xml(rename = "ZoneGroupState", ns(""))]
7837        pub zone_group_state: Option<DecodeXmlString<crate::ZoneGroupState>>,
7838    }
7839
7840    impl crate::DecodeSoapResponse for GetZoneGroupStateResponse {
7841        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7842            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7843            Ok(envelope.body.payload)
7844        }
7845    }
7846
7847    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7848    #[xml(rename = "RegisterMobileDevice", ns(SERVICE_TYPE))]
7849    pub struct RegisterMobileDeviceRequest {
7850        #[xml(rename = "MobileDeviceName", ns(""))]
7851        pub mobile_device_name: String,
7852        #[xml(rename = "MobileDeviceUDN", ns(""))]
7853        pub mobile_device_udn: String,
7854        #[xml(rename = "MobileIPAndPort", ns(""))]
7855        pub mobile_ip_and_port: String,
7856    }
7857
7858    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7859    #[xml(rename = "ReportUnresponsiveDevice", ns(SERVICE_TYPE))]
7860    pub struct ReportUnresponsiveDeviceRequest {
7861        #[xml(rename = "DeviceUUID", ns(""))]
7862        pub device_uuid: String,
7863        #[xml(rename = "DesiredAction", ns(""))]
7864        pub desired_action: super::UnresponsiveDeviceActionType,
7865    }
7866
7867    #[derive(ToXml, Debug, Clone, PartialEq, Default)]
7868    #[xml(rename = "SubmitDiagnostics", ns(SERVICE_TYPE))]
7869    pub struct SubmitDiagnosticsRequest {
7870        #[xml(rename = "IncludeControllers", ns(""))]
7871        pub include_controllers: bool,
7872        #[xml(rename = "Type", ns(""))]
7873        pub type_: String,
7874    }
7875
7876    #[derive(FromXml, Debug, Clone, PartialEq)]
7877    #[xml(rename = "SubmitDiagnosticsResponse", ns(SERVICE_TYPE))]
7878    pub struct SubmitDiagnosticsResponse {
7879        #[xml(rename = "DiagnosticID", ns(""))]
7880        pub diagnostic_id: Option<u32>,
7881    }
7882
7883    impl crate::DecodeSoapResponse for SubmitDiagnosticsResponse {
7884        fn decode_soap_xml(xml: &str) -> crate::Result<Self> {
7885            let envelope: crate::soap_resp::Envelope<Self> = instant_xml::from_str(xml)?;
7886            Ok(envelope.body.payload)
7887        }
7888    }
7889
7890    /// A parsed event produced by the `ZoneGroupTopology` service.
7891    /// Use `SonosDevice::subscribe_zone_group_topology()` to obtain an event
7892    /// stream that produces these.
7893    #[derive(Debug, Clone, PartialEq, Default)]
7894    pub struct ZoneGroupTopologyEvent {
7895        pub alarm_run_sequence: Option<String>,
7896        pub areas_update_id: Option<String>,
7897        pub available_software_update: Option<String>,
7898        pub muse_household_id: Option<String>,
7899        pub netsettings_update_id: Option<String>,
7900        pub source_areas_update_id: Option<String>,
7901        pub third_party_media_servers_x: Option<String>,
7902        pub zone_group_id: Option<String>,
7903        pub zone_group_name: Option<String>,
7904        pub zone_group_state: Option<DecodeXmlString<crate::ZoneGroupState>>,
7905        pub zone_player_uuids_in_group: Option<String>,
7906    }
7907
7908    #[derive(FromXml, Debug, Clone, PartialEq)]
7909    #[xml(rename="propertyset", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7910    struct ZoneGroupTopologyPropertySet {
7911        pub properties: Vec<ZoneGroupTopologyProperty>,
7912    }
7913
7914    #[derive(FromXml, Debug, Clone, PartialEq)]
7915    #[xml(rename="property", ns(crate::upnp::UPNP_EVENT, e=crate::upnp::UPNP_EVENT))]
7916    struct ZoneGroupTopologyProperty {
7917        #[xml(rename = "AlarmRunSequence", ns(""))]
7918        pub alarm_run_sequence: Option<String>,
7919        #[xml(rename = "AreasUpdateID", ns(""))]
7920        pub areas_update_id: Option<String>,
7921        #[xml(rename = "AvailableSoftwareUpdate", ns(""))]
7922        pub available_software_update: Option<String>,
7923        #[xml(rename = "MuseHouseholdId", ns(""))]
7924        pub muse_household_id: Option<String>,
7925        #[xml(rename = "NetsettingsUpdateID", ns(""))]
7926        pub netsettings_update_id: Option<String>,
7927        #[xml(rename = "SourceAreasUpdateID", ns(""))]
7928        pub source_areas_update_id: Option<String>,
7929        #[xml(rename = "ThirdPartyMediaServersX", ns(""))]
7930        pub third_party_media_servers_x: Option<String>,
7931        #[xml(rename = "ZoneGroupID", ns(""))]
7932        pub zone_group_id: Option<String>,
7933        #[xml(rename = "ZoneGroupName", ns(""))]
7934        pub zone_group_name: Option<String>,
7935        #[xml(rename = "ZoneGroupState", ns(""))]
7936        pub zone_group_state: Option<DecodeXmlString<crate::ZoneGroupState>>,
7937        #[xml(rename = "ZonePlayerUUIDsInGroup", ns(""))]
7938        pub zone_player_uuids_in_group: Option<String>,
7939    }
7940
7941    impl DecodeXml for ZoneGroupTopologyEvent {
7942        fn decode_xml(xml: &str) -> crate::Result<Self> {
7943            let mut result = Self::default();
7944            let set: ZoneGroupTopologyPropertySet = instant_xml::from_str(xml)?;
7945            for prop in set.properties {
7946                if let Some(v) = prop.alarm_run_sequence {
7947                    result.alarm_run_sequence.replace(v);
7948                }
7949
7950                if let Some(v) = prop.areas_update_id {
7951                    result.areas_update_id.replace(v);
7952                }
7953
7954                if let Some(v) = prop.available_software_update {
7955                    result.available_software_update.replace(v);
7956                }
7957
7958                if let Some(v) = prop.muse_household_id {
7959                    result.muse_household_id.replace(v);
7960                }
7961
7962                if let Some(v) = prop.netsettings_update_id {
7963                    result.netsettings_update_id.replace(v);
7964                }
7965
7966                if let Some(v) = prop.source_areas_update_id {
7967                    result.source_areas_update_id.replace(v);
7968                }
7969
7970                if let Some(v) = prop.third_party_media_servers_x {
7971                    result.third_party_media_servers_x.replace(v);
7972                }
7973
7974                if let Some(v) = prop.zone_group_id {
7975                    result.zone_group_id.replace(v);
7976                }
7977
7978                if let Some(v) = prop.zone_group_name {
7979                    result.zone_group_name.replace(v);
7980                }
7981
7982                if let Some(v) = prop.zone_group_state {
7983                    result.zone_group_state.replace(v);
7984                }
7985
7986                if let Some(v) = prop.zone_player_uuids_in_group {
7987                    result.zone_player_uuids_in_group.replace(v);
7988                }
7989            }
7990            Ok(result)
7991        }
7992    }
7993
7994    impl crate::SonosDevice {
7995        /// Subscribe to events from the `ZoneGroupTopology` service on this device
7996        pub async fn subscribe_zone_group_topology(
7997            &self,
7998        ) -> crate::Result<crate::upnp::EventStream<ZoneGroupTopologyEvent>> {
7999            self.subscribe_helper(&SERVICE_TYPE).await
8000        }
8001    }
8002}
8003
8004#[derive(PartialEq, Debug, Clone, Eq, Default)]
8005pub enum UnresponsiveDeviceActionType {
8006    #[default]
8007    Remove,
8008    TopologyMonitorProbe,
8009    VerifyThenRemoveSystemwide,
8010
8011    /// Allows passing a value that was not known at the
8012    /// time that this crate was generated from the available
8013    /// device descriptions
8014    Unspecified(String),
8015}
8016
8017impl ToString for UnresponsiveDeviceActionType {
8018    fn to_string(&self) -> String {
8019        match self {
8020            UnresponsiveDeviceActionType::Remove => "Remove".to_string(),
8021            UnresponsiveDeviceActionType::TopologyMonitorProbe => {
8022                "TopologyMonitorProbe".to_string()
8023            }
8024            UnresponsiveDeviceActionType::VerifyThenRemoveSystemwide => {
8025                "VerifyThenRemoveSystemwide".to_string()
8026            }
8027            UnresponsiveDeviceActionType::Unspecified(s) => s.to_string(),
8028        }
8029    }
8030}
8031
8032impl FromStr for UnresponsiveDeviceActionType {
8033    type Err = crate::Error;
8034    fn from_str(s: &str) -> Result<UnresponsiveDeviceActionType> {
8035        match s {
8036            "Remove" => Ok(UnresponsiveDeviceActionType::Remove),
8037            "TopologyMonitorProbe" => Ok(UnresponsiveDeviceActionType::TopologyMonitorProbe),
8038            "VerifyThenRemoveSystemwide" => {
8039                Ok(UnresponsiveDeviceActionType::VerifyThenRemoveSystemwide)
8040            }
8041            s => Ok(UnresponsiveDeviceActionType::Unspecified(s.to_string())),
8042        }
8043    }
8044}
8045
8046impl instant_xml::ToXml for UnresponsiveDeviceActionType {
8047    fn serialize<W: std::fmt::Write + ?Sized>(
8048        &self,
8049        field: Option<instant_xml::Id<'_>>,
8050        serializer: &mut instant_xml::Serializer<W>,
8051    ) -> std::result::Result<(), instant_xml::Error> {
8052        self.to_string().serialize(field, serializer)
8053    }
8054
8055    fn present(&self) -> bool {
8056        true
8057    }
8058}
8059
8060impl<'xml> instant_xml::FromXml<'xml> for UnresponsiveDeviceActionType {
8061    #[inline]
8062    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
8063        match field {
8064            Some(field) => id == field,
8065            None => false,
8066        }
8067    }
8068
8069    fn deserialize<'cx>(
8070        into: &mut Self::Accumulator,
8071        field: &'static str,
8072        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
8073    ) -> std::result::Result<(), instant_xml::Error> {
8074        if into.is_some() {
8075            return Err(instant_xml::Error::DuplicateValue(field));
8076        }
8077
8078        match deserializer.take_str()? {
8079            Some(value) => {
8080                let parsed: UnresponsiveDeviceActionType = value.parse().map_err(|err| {
8081                    instant_xml::Error::Other(format!(
8082                        "invalid value for field {field}: {value}: {err:#}"
8083                    ))
8084                })?;
8085                *into = Some(parsed);
8086                Ok(())
8087            }
8088            None => Err(instant_xml::Error::MissingValue(field)),
8089        }
8090    }
8091
8092    type Accumulator = Option<UnresponsiveDeviceActionType>;
8093    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
8094}
8095
8096#[derive(PartialEq, Debug, Clone, Eq, Default)]
8097pub enum UpdateType {
8098    #[default]
8099    All,
8100    Software,
8101
8102    /// Allows passing a value that was not known at the
8103    /// time that this crate was generated from the available
8104    /// device descriptions
8105    Unspecified(String),
8106}
8107
8108impl ToString for UpdateType {
8109    fn to_string(&self) -> String {
8110        match self {
8111            UpdateType::All => "All".to_string(),
8112            UpdateType::Software => "Software".to_string(),
8113            UpdateType::Unspecified(s) => s.to_string(),
8114        }
8115    }
8116}
8117
8118impl FromStr for UpdateType {
8119    type Err = crate::Error;
8120    fn from_str(s: &str) -> Result<UpdateType> {
8121        match s {
8122            "All" => Ok(UpdateType::All),
8123            "Software" => Ok(UpdateType::Software),
8124            s => Ok(UpdateType::Unspecified(s.to_string())),
8125        }
8126    }
8127}
8128
8129impl instant_xml::ToXml for UpdateType {
8130    fn serialize<W: std::fmt::Write + ?Sized>(
8131        &self,
8132        field: Option<instant_xml::Id<'_>>,
8133        serializer: &mut instant_xml::Serializer<W>,
8134    ) -> std::result::Result<(), instant_xml::Error> {
8135        self.to_string().serialize(field, serializer)
8136    }
8137
8138    fn present(&self) -> bool {
8139        true
8140    }
8141}
8142
8143impl<'xml> instant_xml::FromXml<'xml> for UpdateType {
8144    #[inline]
8145    fn matches(id: instant_xml::Id<'_>, field: Option<instant_xml::Id<'_>>) -> bool {
8146        match field {
8147            Some(field) => id == field,
8148            None => false,
8149        }
8150    }
8151
8152    fn deserialize<'cx>(
8153        into: &mut Self::Accumulator,
8154        field: &'static str,
8155        deserializer: &mut instant_xml::Deserializer<'cx, 'xml>,
8156    ) -> std::result::Result<(), instant_xml::Error> {
8157        if into.is_some() {
8158            return Err(instant_xml::Error::DuplicateValue(field));
8159        }
8160
8161        match deserializer.take_str()? {
8162            Some(value) => {
8163                let parsed: UpdateType = value.parse().map_err(|err| {
8164                    instant_xml::Error::Other(format!(
8165                        "invalid value for field {field}: {value}: {err:#}"
8166                    ))
8167                })?;
8168                *into = Some(parsed);
8169                Ok(())
8170            }
8171            None => Err(instant_xml::Error::MissingValue(field)),
8172        }
8173    }
8174
8175    type Accumulator = Option<UpdateType>;
8176    const KIND: instant_xml::Kind = instant_xml::Kind::Scalar;
8177}
8178
8179#[allow(async_fn_in_trait)]
8180/// Service that controls stuff related to transport (play/pause/next/special URLs)
8181pub trait AVTransport {
8182    async fn add_multiple_uris_to_queue(
8183        &self,
8184        request: av_transport::AddMultipleUrisToQueueRequest,
8185    ) -> Result<av_transport::AddMultipleUrisToQueueResponse>;
8186    /// Adds songs to the SONOS queue
8187    async fn add_uri_to_queue(
8188        &self,
8189        request: av_transport::AddUriToQueueRequest,
8190    ) -> Result<av_transport::AddUriToQueueResponse>;
8191    async fn add_uri_to_saved_queue(
8192        &self,
8193        request: av_transport::AddUriToSavedQueueRequest,
8194    ) -> Result<av_transport::AddUriToSavedQueueResponse>;
8195    async fn backup_queue(&self, request: av_transport::BackupQueueRequest) -> Result<()>;
8196    /// Leave the current group and revert to a single player.
8197    async fn become_coordinator_of_standalone_group(
8198        &self,
8199        request: av_transport::BecomeCoordinatorOfStandaloneGroupRequest,
8200    ) -> Result<av_transport::BecomeCoordinatorOfStandaloneGroupResponse>;
8201    async fn become_group_coordinator(
8202        &self,
8203        request: av_transport::BecomeGroupCoordinatorRequest,
8204    ) -> Result<()>;
8205    async fn become_group_coordinator_and_source(
8206        &self,
8207        request: av_transport::BecomeGroupCoordinatorAndSourceRequest,
8208    ) -> Result<()>;
8209    async fn change_coordinator(
8210        &self,
8211        request: av_transport::ChangeCoordinatorRequest,
8212    ) -> Result<()>;
8213    async fn change_transport_settings(
8214        &self,
8215        request: av_transport::ChangeTransportSettingsRequest,
8216    ) -> Result<()>;
8217    /// Stop playing after set sleep timer or cancel
8218    async fn configure_sleep_timer(
8219        &self,
8220        request: av_transport::ConfigureSleepTimerRequest,
8221    ) -> Result<()>;
8222    async fn create_saved_queue(
8223        &self,
8224        request: av_transport::CreateSavedQueueRequest,
8225    ) -> Result<av_transport::CreateSavedQueueResponse>;
8226    /// Delegates the coordinator role to another player in the same group
8227    async fn delegate_group_coordination_to(
8228        &self,
8229        request: av_transport::DelegateGroupCoordinationToRequest,
8230    ) -> Result<()>;
8231    async fn end_direct_control_session(
8232        &self,
8233        request: av_transport::EndDirectControlSessionRequest,
8234    ) -> Result<()>;
8235    /// Get crossfade mode
8236    async fn get_crossfade_mode(
8237        &self,
8238        request: av_transport::GetCrossfadeModeRequest,
8239    ) -> Result<av_transport::GetCrossfadeModeResponse>;
8240    /// Get current transport actions such as Set, Stop, Pause, Play, X_DLNA_SeekTime, Next, X_DLNA_SeekTrackNr
8241    async fn get_current_transport_actions(
8242        &self,
8243        request: av_transport::GetCurrentTransportActionsRequest,
8244    ) -> Result<av_transport::GetCurrentTransportActionsResponse>;
8245    async fn get_device_capabilities(
8246        &self,
8247        request: av_transport::GetDeviceCapabilitiesRequest,
8248    ) -> Result<av_transport::GetDeviceCapabilitiesResponse>;
8249    /// Get information about the current playing media (queue)
8250    async fn get_media_info(
8251        &self,
8252        request: av_transport::GetMediaInfoRequest,
8253    ) -> Result<av_transport::GetMediaInfoResponse>;
8254    /// Get information about current position (position in queue and time in current song)
8255    async fn get_position_info(
8256        &self,
8257        request: av_transport::GetPositionInfoRequest,
8258    ) -> Result<av_transport::GetPositionInfoResponse>;
8259    /// Get time left on sleeptimer.
8260    async fn get_remaining_sleep_timer_duration(
8261        &self,
8262        request: av_transport::GetRemainingSleepTimerDurationRequest,
8263    ) -> Result<av_transport::GetRemainingSleepTimerDurationResponse>;
8264    async fn get_running_alarm_properties(
8265        &self,
8266        request: av_transport::GetRunningAlarmPropertiesRequest,
8267    ) -> Result<av_transport::GetRunningAlarmPropertiesResponse>;
8268    /// Get current transport status, speed and state such as PLAYING, STOPPED, PLAYING, PAUSED_PLAYBACK, TRANSITIONING, NO_MEDIA_PRESENT
8269    async fn get_transport_info(
8270        &self,
8271        request: av_transport::GetTransportInfoRequest,
8272    ) -> Result<av_transport::GetTransportInfoResponse>;
8273    /// Get transport settings
8274    async fn get_transport_settings(
8275        &self,
8276        request: av_transport::GetTransportSettingsRequest,
8277    ) -> Result<av_transport::GetTransportSettingsResponse>;
8278    /// Go to next song
8279    async fn next(&self, request: av_transport::NextRequest) -> Result<()>;
8280    async fn notify_deleted_uri(
8281        &self,
8282        request: av_transport::NotifyDeletedUriRequest,
8283    ) -> Result<()>;
8284    /// Pause playback
8285    async fn pause(&self, request: av_transport::PauseRequest) -> Result<()>;
8286    /// Start playing the set TransportURI
8287    async fn play(&self, request: av_transport::PlayRequest) -> Result<()>;
8288    /// Go to previous song
8289    async fn previous(&self, request: av_transport::PreviousRequest) -> Result<()>;
8290    /// Flushes the SONOS queue.
8291    async fn remove_all_tracks_from_queue(
8292        &self,
8293        request: av_transport::RemoveAllTracksFromQueueRequest,
8294    ) -> Result<()>;
8295    async fn remove_track_from_queue(
8296        &self,
8297        request: av_transport::RemoveTrackFromQueueRequest,
8298    ) -> Result<()>;
8299    /// Removes the specified range of songs from the SONOS queue.
8300    async fn remove_track_range_from_queue(
8301        &self,
8302        request: av_transport::RemoveTrackRangeFromQueueRequest,
8303    ) -> Result<av_transport::RemoveTrackRangeFromQueueResponse>;
8304    async fn reorder_tracks_in_queue(
8305        &self,
8306        request: av_transport::ReorderTracksInQueueRequest,
8307    ) -> Result<()>;
8308    async fn reorder_tracks_in_saved_queue(
8309        &self,
8310        request: av_transport::ReorderTracksInSavedQueueRequest,
8311    ) -> Result<av_transport::ReorderTracksInSavedQueueResponse>;
8312    async fn run_alarm(&self, request: av_transport::RunAlarmRequest) -> Result<()>;
8313    /// Saves the current SONOS queue as a SONOS playlist and outputs objectID
8314    async fn save_queue(
8315        &self,
8316        request: av_transport::SaveQueueRequest,
8317    ) -> Result<av_transport::SaveQueueResponse>;
8318    /// Seek track in queue, time delta or absolute time in song
8319    async fn seek(&self, request: av_transport::SeekRequest) -> Result<()>;
8320    /// Set the transport URI to a song, a stream, the queue, another player-rincon and a lot more
8321    async fn set_av_transport_uri(
8322        &self,
8323        request: av_transport::SetAvTransportUriRequest,
8324    ) -> Result<()>;
8325    /// Set crossfade mode
8326    async fn set_crossfade_mode(
8327        &self,
8328        request: av_transport::SetCrossfadeModeRequest,
8329    ) -> Result<()>;
8330    async fn set_next_av_transport_uri(
8331        &self,
8332        request: av_transport::SetNextAvTransportUriRequest,
8333    ) -> Result<()>;
8334    /// Set the PlayMode
8335    async fn set_play_mode(&self, request: av_transport::SetPlayModeRequest) -> Result<()>;
8336    /// Snooze the current alarm for some time.
8337    async fn snooze_alarm(&self, request: av_transport::SnoozeAlarmRequest) -> Result<()>;
8338    async fn start_autoplay(&self, request: av_transport::StartAutoplayRequest) -> Result<()>;
8339    /// Stop playback
8340    async fn stop(&self, request: av_transport::StopRequest) -> Result<()>;
8341}
8342
8343#[allow(async_fn_in_trait)]
8344/// Control the sonos alarms and times
8345pub trait AlarmClock {
8346    /// Create a single alarm, all properties are required
8347    async fn create_alarm(
8348        &self,
8349        request: alarm_clock::CreateAlarmRequest,
8350    ) -> Result<alarm_clock::CreateAlarmResponse>;
8351    /// Delete an alarm
8352    async fn destroy_alarm(&self, request: alarm_clock::DestroyAlarmRequest) -> Result<()>;
8353    async fn get_daily_index_refresh_time(
8354        &self,
8355    ) -> Result<alarm_clock::GetDailyIndexRefreshTimeResponse>;
8356    async fn get_format(&self) -> Result<alarm_clock::GetFormatResponse>;
8357    async fn get_household_time_at_stamp(
8358        &self,
8359        request: alarm_clock::GetHouseholdTimeAtStampRequest,
8360    ) -> Result<alarm_clock::GetHouseholdTimeAtStampResponse>;
8361    async fn get_time_now(&self) -> Result<alarm_clock::GetTimeNowResponse>;
8362    async fn get_time_server(&self) -> Result<alarm_clock::GetTimeServerResponse>;
8363    async fn get_time_zone(&self) -> Result<alarm_clock::GetTimeZoneResponse>;
8364    async fn get_time_zone_and_rule(&self) -> Result<alarm_clock::GetTimeZoneAndRuleResponse>;
8365    async fn get_time_zone_rule(
8366        &self,
8367        request: alarm_clock::GetTimeZoneRuleRequest,
8368    ) -> Result<alarm_clock::GetTimeZoneRuleResponse>;
8369    /// Get the AlarmList as XML
8370    async fn list_alarms(&self) -> Result<alarm_clock::ListAlarmsResponse>;
8371    async fn set_daily_index_refresh_time(
8372        &self,
8373        request: alarm_clock::SetDailyIndexRefreshTimeRequest,
8374    ) -> Result<()>;
8375    async fn set_format(&self, request: alarm_clock::SetFormatRequest) -> Result<()>;
8376    async fn set_time_now(&self, request: alarm_clock::SetTimeNowRequest) -> Result<()>;
8377    async fn set_time_server(&self, request: alarm_clock::SetTimeServerRequest) -> Result<()>;
8378    async fn set_time_zone(&self, request: alarm_clock::SetTimeZoneRequest) -> Result<()>;
8379    /// Update an alarm, all parameters are required.
8380    async fn update_alarm(&self, request: alarm_clock::UpdateAlarmRequest) -> Result<()>;
8381}
8382
8383#[allow(async_fn_in_trait)]
8384/// Control line in
8385pub trait AudioIn {
8386    async fn get_audio_input_attributes(&self)
8387        -> Result<audio_in::GetAudioInputAttributesResponse>;
8388    async fn get_line_in_level(&self) -> Result<audio_in::GetLineInLevelResponse>;
8389    async fn select_audio(&self, request: audio_in::SelectAudioRequest) -> Result<()>;
8390    async fn set_audio_input_attributes(
8391        &self,
8392        request: audio_in::SetAudioInputAttributesRequest,
8393    ) -> Result<()>;
8394    async fn set_line_in_level(&self, request: audio_in::SetLineInLevelRequest) -> Result<()>;
8395    async fn start_transmission_to_group(
8396        &self,
8397        request: audio_in::StartTransmissionToGroupRequest,
8398    ) -> Result<audio_in::StartTransmissionToGroupResponse>;
8399    async fn stop_transmission_to_group(
8400        &self,
8401        request: audio_in::StopTransmissionToGroupRequest,
8402    ) -> Result<()>;
8403}
8404
8405#[allow(async_fn_in_trait)]
8406/// Services related to connections and protocols
8407pub trait ConnectionManager {
8408    async fn get_current_connection_ids(
8409        &self,
8410    ) -> Result<connection_manager::GetCurrentConnectionIdsResponse>;
8411    async fn get_current_connection_info(
8412        &self,
8413        request: connection_manager::GetCurrentConnectionInfoRequest,
8414    ) -> Result<connection_manager::GetCurrentConnectionInfoResponse>;
8415    async fn get_protocol_info(&self) -> Result<connection_manager::GetProtocolInfoResponse>;
8416}
8417
8418#[allow(async_fn_in_trait)]
8419/// Browse for local content
8420pub trait ContentDirectory {
8421    /// Browse for content: Music library (A), share(S:), Sonos playlists(SQ:), Sonos favorites(FV:2), radio stations(R:0/0), radio shows(R:0/1), queue(Q:)). Recommendation: Send one request, check the `TotalMatches` and - if necessary - do additional requests with higher `StartingIndex`. In case of duplicates only the first is returned! Example: albums with same title, even if artists are different
8422    async fn browse(
8423        &self,
8424        request: content_directory::BrowseRequest,
8425    ) -> Result<content_directory::BrowseResponse>;
8426    async fn create_object(
8427        &self,
8428        request: content_directory::CreateObjectRequest,
8429    ) -> Result<content_directory::CreateObjectResponse>;
8430    async fn destroy_object(&self, request: content_directory::DestroyObjectRequest) -> Result<()>;
8431    async fn find_prefix(
8432        &self,
8433        request: content_directory::FindPrefixRequest,
8434    ) -> Result<content_directory::FindPrefixResponse>;
8435    /// Get the current album art display option such as `WMP`, `ITUNES` or `NONE`
8436    async fn get_album_artist_display_option(
8437        &self,
8438    ) -> Result<content_directory::GetAlbumArtistDisplayOptionResponse>;
8439    async fn get_all_prefix_locations(
8440        &self,
8441        request: content_directory::GetAllPrefixLocationsRequest,
8442    ) -> Result<content_directory::GetAllPrefixLocationsResponse>;
8443    async fn get_browseable(&self) -> Result<content_directory::GetBrowseableResponse>;
8444    async fn get_last_index_change(&self) -> Result<content_directory::GetLastIndexChangeResponse>;
8445    async fn get_search_capabilities(
8446        &self,
8447    ) -> Result<content_directory::GetSearchCapabilitiesResponse>;
8448    async fn get_share_index_in_progress(
8449        &self,
8450    ) -> Result<content_directory::GetShareIndexInProgressResponse>;
8451    async fn get_sort_capabilities(&self)
8452        -> Result<content_directory::GetSortCapabilitiesResponse>;
8453    async fn get_system_update_id(&self) -> Result<content_directory::GetSystemUpdateIdResponse>;
8454    /// Updates the music library (share) index
8455    async fn refresh_share_index(
8456        &self,
8457        request: content_directory::RefreshShareIndexRequest,
8458    ) -> Result<()>;
8459    async fn request_resort(&self, request: content_directory::RequestResortRequest) -> Result<()>;
8460    async fn set_browseable(&self, request: content_directory::SetBrowseableRequest) -> Result<()>;
8461    async fn update_object(&self, request: content_directory::UpdateObjectRequest) -> Result<()>;
8462}
8463
8464#[allow(async_fn_in_trait)]
8465/// Modify device properties, like LED status and stereo pairs
8466pub trait DeviceProperties {
8467    async fn add_bonded_zones(
8468        &self,
8469        request: device_properties::AddBondedZonesRequest,
8470    ) -> Result<()>;
8471    /// Adds satellites and/or a sub woofer to a (main) player. The satellites become hidden. The main player RINCON_* is mandatory. RR: right - rear, LF: left - front, SW: subwoofer
8472    async fn add_ht_satellite(
8473        &self,
8474        request: device_properties::AddHtSatelliteRequest,
8475    ) -> Result<()>;
8476    /// Create a stereo pair (left, right speakers), right one becomes hidden
8477    async fn create_stereo_pair(
8478        &self,
8479        request: device_properties::CreateStereoPairRequest,
8480    ) -> Result<()>;
8481    async fn enter_config_mode(
8482        &self,
8483        request: device_properties::EnterConfigModeRequest,
8484    ) -> Result<device_properties::EnterConfigModeResponse>;
8485    async fn exit_config_mode(
8486        &self,
8487        request: device_properties::ExitConfigModeRequest,
8488    ) -> Result<()>;
8489    async fn get_autoplay_linked_zones(
8490        &self,
8491        request: device_properties::GetAutoplayLinkedZonesRequest,
8492    ) -> Result<device_properties::GetAutoplayLinkedZonesResponse>;
8493    async fn get_autoplay_room_uuid(
8494        &self,
8495        request: device_properties::GetAutoplayRoomUuidRequest,
8496    ) -> Result<device_properties::GetAutoplayRoomUuidResponse>;
8497    async fn get_autoplay_volume(
8498        &self,
8499        request: device_properties::GetAutoplayVolumeRequest,
8500    ) -> Result<device_properties::GetAutoplayVolumeResponse>;
8501    /// Get the current button lock state
8502    async fn get_button_lock_state(&self) -> Result<device_properties::GetButtonLockStateResponse>;
8503    async fn get_button_state(&self) -> Result<device_properties::GetButtonStateResponse>;
8504    async fn get_ht_forward_state(&self) -> Result<device_properties::GetHtForwardStateResponse>;
8505    async fn get_household_id(&self) -> Result<device_properties::GetHouseholdIdResponse>;
8506    /// Get the current LED state
8507    async fn get_led_state(&self) -> Result<device_properties::GetLedStateResponse>;
8508    async fn get_use_autoplay_volume(
8509        &self,
8510        request: device_properties::GetUseAutoplayVolumeRequest,
8511    ) -> Result<device_properties::GetUseAutoplayVolumeResponse>;
8512    async fn get_zone_attributes(&self) -> Result<device_properties::GetZoneAttributesResponse>;
8513    /// Get information about this specific speaker
8514    async fn get_zone_info(&self) -> Result<device_properties::GetZoneInfoResponse>;
8515    async fn remove_bonded_zones(
8516        &self,
8517        request: device_properties::RemoveBondedZonesRequest,
8518    ) -> Result<()>;
8519    /// Removes a satellite or a sub woofer from (main) player. The satellite becomes visible.
8520    async fn remove_ht_satellite(
8521        &self,
8522        request: device_properties::RemoveHtSatelliteRequest,
8523    ) -> Result<()>;
8524    async fn room_detection_start_chirping(
8525        &self,
8526        request: device_properties::RoomDetectionStartChirpingRequest,
8527    ) -> Result<device_properties::RoomDetectionStartChirpingResponse>;
8528    async fn room_detection_stop_chirping(
8529        &self,
8530        request: device_properties::RoomDetectionStopChirpingRequest,
8531    ) -> Result<()>;
8532    /// Separate a stereo pair
8533    async fn separate_stereo_pair(
8534        &self,
8535        request: device_properties::SeparateStereoPairRequest,
8536    ) -> Result<()>;
8537    async fn set_autoplay_linked_zones(
8538        &self,
8539        request: device_properties::SetAutoplayLinkedZonesRequest,
8540    ) -> Result<()>;
8541    async fn set_autoplay_room_uuid(
8542        &self,
8543        request: device_properties::SetAutoplayRoomUuidRequest,
8544    ) -> Result<()>;
8545    async fn set_autoplay_volume(
8546        &self,
8547        request: device_properties::SetAutoplayVolumeRequest,
8548    ) -> Result<()>;
8549    /// Set the button lock state
8550    async fn set_button_lock_state(
8551        &self,
8552        request: device_properties::SetButtonLockStateRequest,
8553    ) -> Result<()>;
8554    /// Set the LED state
8555    async fn set_led_state(&self, request: device_properties::SetLedStateRequest) -> Result<()>;
8556    async fn set_use_autoplay_volume(
8557        &self,
8558        request: device_properties::SetUseAutoplayVolumeRequest,
8559    ) -> Result<()>;
8560    async fn set_zone_attributes(
8561        &self,
8562        request: device_properties::SetZoneAttributesRequest,
8563    ) -> Result<()>;
8564}
8565
8566#[allow(async_fn_in_trait)]
8567/// Services related to groups
8568pub trait GroupManagement {
8569    async fn add_member(
8570        &self,
8571        request: group_management::AddMemberRequest,
8572    ) -> Result<group_management::AddMemberResponse>;
8573    async fn remove_member(&self, request: group_management::RemoveMemberRequest) -> Result<()>;
8574    async fn report_track_buffering_result(
8575        &self,
8576        request: group_management::ReportTrackBufferingResultRequest,
8577    ) -> Result<()>;
8578    async fn set_source_area_ids(
8579        &self,
8580        request: group_management::SetSourceAreaIdsRequest,
8581    ) -> Result<()>;
8582}
8583
8584#[allow(async_fn_in_trait)]
8585/// Volume related controls for groups
8586pub trait GroupRenderingControl {
8587    /// Get the group mute state.
8588    async fn get_group_mute(
8589        &self,
8590        request: group_rendering_control::GetGroupMuteRequest,
8591    ) -> Result<group_rendering_control::GetGroupMuteResponse>;
8592    /// Get the group volume.
8593    async fn get_group_volume(
8594        &self,
8595        request: group_rendering_control::GetGroupVolumeRequest,
8596    ) -> Result<group_rendering_control::GetGroupVolumeResponse>;
8597    /// (Un-/)Mute the entire group
8598    async fn set_group_mute(
8599        &self,
8600        request: group_rendering_control::SetGroupMuteRequest,
8601    ) -> Result<()>;
8602    /// Change group volume. Players volume will be changed proportionally based on last snapshot
8603    async fn set_group_volume(
8604        &self,
8605        request: group_rendering_control::SetGroupVolumeRequest,
8606    ) -> Result<()>;
8607    /// Relatively change group volume - returns final group volume. Players volume will be changed proportionally based on last snapshot
8608    async fn set_relative_group_volume(
8609        &self,
8610        request: group_rendering_control::SetRelativeGroupVolumeRequest,
8611    ) -> Result<group_rendering_control::SetRelativeGroupVolumeResponse>;
8612    /// Creates a new group volume snapshot,  the volume ratio between all players. It is used by SetGroupVolume and SetRelativeGroupVolume
8613    async fn snapshot_group_volume(
8614        &self,
8615        request: group_rendering_control::SnapshotGroupVolumeRequest,
8616    ) -> Result<()>;
8617}
8618
8619#[allow(async_fn_in_trait)]
8620/// Service related to the TV remote control
8621pub trait HTControl {
8622    async fn commit_learned_ir_codes(
8623        &self,
8624        request: ht_control::CommitLearnedIrCodesRequest,
8625    ) -> Result<()>;
8626    async fn get_ir_repeater_state(&self) -> Result<ht_control::GetIrRepeaterStateResponse>;
8627    async fn get_led_feedback_state(&self) -> Result<ht_control::GetLedFeedbackStateResponse>;
8628    async fn identify_ir_remote(&self, request: ht_control::IdentifyIrRemoteRequest) -> Result<()>;
8629    async fn is_remote_configured(&self) -> Result<ht_control::IsRemoteConfiguredResponse>;
8630    async fn learn_ir_code(&self, request: ht_control::LearnIrCodeRequest) -> Result<()>;
8631    async fn set_ir_repeater_state(
8632        &self,
8633        request: ht_control::SetIrRepeaterStateRequest,
8634    ) -> Result<()>;
8635    async fn set_led_feedback_state(
8636        &self,
8637        request: ht_control::SetLedFeedbackStateRequest,
8638    ) -> Result<()>;
8639}
8640
8641#[allow(async_fn_in_trait)]
8642/// Access to external music services, like Spotify or Youtube Music
8643pub trait MusicServices {
8644    async fn get_session_id(
8645        &self,
8646        request: music_services::GetSessionIdRequest,
8647    ) -> Result<music_services::GetSessionIdResponse>;
8648    /// Load music service list as xml
8649    async fn list_available_services(
8650        &self,
8651    ) -> Result<music_services::ListAvailableServicesResponse>;
8652    async fn update_available_services(&self) -> Result<()>;
8653}
8654
8655#[allow(async_fn_in_trait)]
8656/// Services related to Chinese Tencent Qplay service
8657pub trait QPlay {
8658    async fn q_play_auth(
8659        &self,
8660        request: q_play::QPlayAuthRequest,
8661    ) -> Result<q_play::QPlayAuthResponse>;
8662}
8663
8664#[allow(async_fn_in_trait)]
8665/// Modify and browse queues
8666pub trait Queue {
8667    async fn add_multiple_uris(
8668        &self,
8669        request: queue::AddMultipleUrisRequest,
8670    ) -> Result<queue::AddMultipleUrisResponse>;
8671    async fn add_uri(&self, request: queue::AddUriRequest) -> Result<queue::AddUriResponse>;
8672    async fn attach_queue(
8673        &self,
8674        request: queue::AttachQueueRequest,
8675    ) -> Result<queue::AttachQueueResponse>;
8676    async fn backup(&self) -> Result<()>;
8677    async fn browse(&self, request: queue::BrowseRequest) -> Result<queue::BrowseResponse>;
8678    async fn create_queue(
8679        &self,
8680        request: queue::CreateQueueRequest,
8681    ) -> Result<queue::CreateQueueResponse>;
8682    async fn remove_all_tracks(
8683        &self,
8684        request: queue::RemoveAllTracksRequest,
8685    ) -> Result<queue::RemoveAllTracksResponse>;
8686    async fn remove_track_range(
8687        &self,
8688        request: queue::RemoveTrackRangeRequest,
8689    ) -> Result<queue::RemoveTrackRangeResponse>;
8690    async fn reorder_tracks(
8691        &self,
8692        request: queue::ReorderTracksRequest,
8693    ) -> Result<queue::ReorderTracksResponse>;
8694    async fn replace_all_tracks(
8695        &self,
8696        request: queue::ReplaceAllTracksRequest,
8697    ) -> Result<queue::ReplaceAllTracksResponse>;
8698    async fn save_as_sonos_playlist(
8699        &self,
8700        request: queue::SaveAsSonosPlaylistRequest,
8701    ) -> Result<queue::SaveAsSonosPlaylistResponse>;
8702}
8703
8704#[allow(async_fn_in_trait)]
8705/// Volume related controls
8706pub trait RenderingControl {
8707    /// Get bass level between -10 and 10
8708    async fn get_bass(
8709        &self,
8710        request: rendering_control::GetBassRequest,
8711    ) -> Result<rendering_control::GetBassResponse>;
8712    /// Get equalizer value
8713    async fn get_eq(
8714        &self,
8715        request: rendering_control::GetEqRequest,
8716    ) -> Result<rendering_control::GetEqResponse>;
8717    async fn get_headphone_connected(
8718        &self,
8719        request: rendering_control::GetHeadphoneConnectedRequest,
8720    ) -> Result<rendering_control::GetHeadphoneConnectedResponse>;
8721    /// Whether or not Loudness is on
8722    async fn get_loudness(
8723        &self,
8724        request: rendering_control::GetLoudnessRequest,
8725    ) -> Result<rendering_control::GetLoudnessResponse>;
8726    async fn get_mute(
8727        &self,
8728        request: rendering_control::GetMuteRequest,
8729    ) -> Result<rendering_control::GetMuteResponse>;
8730    async fn get_output_fixed(
8731        &self,
8732        request: rendering_control::GetOutputFixedRequest,
8733    ) -> Result<rendering_control::GetOutputFixedResponse>;
8734    async fn get_room_calibration_status(
8735        &self,
8736        request: rendering_control::GetRoomCalibrationStatusRequest,
8737    ) -> Result<rendering_control::GetRoomCalibrationStatusResponse>;
8738    async fn get_supports_output_fixed(
8739        &self,
8740        request: rendering_control::GetSupportsOutputFixedRequest,
8741    ) -> Result<rendering_control::GetSupportsOutputFixedResponse>;
8742    /// Get treble
8743    async fn get_treble(
8744        &self,
8745        request: rendering_control::GetTrebleRequest,
8746    ) -> Result<rendering_control::GetTrebleResponse>;
8747    /// Get volume
8748    async fn get_volume(
8749        &self,
8750        request: rendering_control::GetVolumeRequest,
8751    ) -> Result<rendering_control::GetVolumeResponse>;
8752    async fn get_volume_db(
8753        &self,
8754        request: rendering_control::GetVolumeDbRequest,
8755    ) -> Result<rendering_control::GetVolumeDbResponse>;
8756    async fn get_volume_db_range(
8757        &self,
8758        request: rendering_control::GetVolumeDbRangeRequest,
8759    ) -> Result<rendering_control::GetVolumeDbRangeResponse>;
8760    async fn ramp_to_volume(
8761        &self,
8762        request: rendering_control::RampToVolumeRequest,
8763    ) -> Result<rendering_control::RampToVolumeResponse>;
8764    async fn reset_basic_eq(
8765        &self,
8766        request: rendering_control::ResetBasicEqRequest,
8767    ) -> Result<rendering_control::ResetBasicEqResponse>;
8768    async fn reset_ext_eq(&self, request: rendering_control::ResetExtEqRequest) -> Result<()>;
8769    async fn restore_volume_prior_to_ramp(
8770        &self,
8771        request: rendering_control::RestoreVolumePriorToRampRequest,
8772    ) -> Result<()>;
8773    /// Set bass level, between -10 and 10
8774    async fn set_bass(&self, request: rendering_control::SetBassRequest) -> Result<()>;
8775    async fn set_channel_map(&self, request: rendering_control::SetChannelMapRequest)
8776        -> Result<()>;
8777    /// Set equalizer value for different types
8778    async fn set_eq(&self, request: rendering_control::SetEqRequest) -> Result<()>;
8779    /// Set loudness on / off
8780    async fn set_loudness(&self, request: rendering_control::SetLoudnessRequest) -> Result<()>;
8781    async fn set_mute(&self, request: rendering_control::SetMuteRequest) -> Result<()>;
8782    async fn set_output_fixed(
8783        &self,
8784        request: rendering_control::SetOutputFixedRequest,
8785    ) -> Result<()>;
8786    async fn set_relative_volume(
8787        &self,
8788        request: rendering_control::SetRelativeVolumeRequest,
8789    ) -> Result<rendering_control::SetRelativeVolumeResponse>;
8790    async fn set_room_calibration_status(
8791        &self,
8792        request: rendering_control::SetRoomCalibrationStatusRequest,
8793    ) -> Result<()>;
8794    async fn set_room_calibration_x(
8795        &self,
8796        request: rendering_control::SetRoomCalibrationXRequest,
8797    ) -> Result<()>;
8798    /// Set treble level
8799    async fn set_treble(&self, request: rendering_control::SetTrebleRequest) -> Result<()>;
8800    async fn set_volume(&self, request: rendering_control::SetVolumeRequest) -> Result<()>;
8801    async fn set_volume_db(&self, request: rendering_control::SetVolumeDbRequest) -> Result<()>;
8802}
8803
8804#[allow(async_fn_in_trait)]
8805/// Manage system-wide settings, mainly account stuff
8806pub trait SystemProperties {
8807    async fn add_account_x(
8808        &self,
8809        request: system_properties::AddAccountXRequest,
8810    ) -> Result<system_properties::AddAccountXResponse>;
8811    async fn add_o_auth_account_x(
8812        &self,
8813        request: system_properties::AddOAuthAccountXRequest,
8814    ) -> Result<system_properties::AddOAuthAccountXResponse>;
8815    async fn do_post_update_tasks(&self) -> Result<()>;
8816    async fn edit_account_md(&self, request: system_properties::EditAccountMdRequest)
8817        -> Result<()>;
8818    async fn edit_account_password_x(
8819        &self,
8820        request: system_properties::EditAccountPasswordXRequest,
8821    ) -> Result<()>;
8822    async fn enable_rdm(&self, request: system_properties::EnableRdmRequest) -> Result<()>;
8823    async fn get_rdm(&self) -> Result<system_properties::GetRdmResponse>;
8824    /// Get a saved string.
8825    async fn get_string(
8826        &self,
8827        request: system_properties::GetStringRequest,
8828    ) -> Result<system_properties::GetStringResponse>;
8829    async fn get_web_code(
8830        &self,
8831        request: system_properties::GetWebCodeRequest,
8832    ) -> Result<system_properties::GetWebCodeResponse>;
8833    async fn provision_credentialed_trial_account_x(
8834        &self,
8835        request: system_properties::ProvisionCredentialedTrialAccountXRequest,
8836    ) -> Result<system_properties::ProvisionCredentialedTrialAccountXResponse>;
8837    async fn refresh_account_credentials_x(
8838        &self,
8839        request: system_properties::RefreshAccountCredentialsXRequest,
8840    ) -> Result<()>;
8841    /// Remove a saved string
8842    async fn remove(&self, request: system_properties::RemoveRequest) -> Result<()>;
8843    async fn remove_account(&self, request: system_properties::RemoveAccountRequest) -> Result<()>;
8844    async fn replace_account_x(
8845        &self,
8846        request: system_properties::ReplaceAccountXRequest,
8847    ) -> Result<system_properties::ReplaceAccountXResponse>;
8848    async fn reset_third_party_credentials(&self) -> Result<()>;
8849    async fn set_account_nickname_x(
8850        &self,
8851        request: system_properties::SetAccountNicknameXRequest,
8852    ) -> Result<()>;
8853    /// Save a string in the system
8854    async fn set_string(&self, request: system_properties::SetStringRequest) -> Result<()>;
8855}
8856
8857#[allow(async_fn_in_trait)]
8858pub trait VirtualLineIn {
8859    async fn next(&self, request: virtual_line_in::NextRequest) -> Result<()>;
8860    async fn pause(&self, request: virtual_line_in::PauseRequest) -> Result<()>;
8861    async fn play(&self, request: virtual_line_in::PlayRequest) -> Result<()>;
8862    async fn previous(&self, request: virtual_line_in::PreviousRequest) -> Result<()>;
8863    async fn set_volume(&self, request: virtual_line_in::SetVolumeRequest) -> Result<()>;
8864    async fn start_transmission(
8865        &self,
8866        request: virtual_line_in::StartTransmissionRequest,
8867    ) -> Result<virtual_line_in::StartTransmissionResponse>;
8868    async fn stop(&self, request: virtual_line_in::StopRequest) -> Result<()>;
8869    async fn stop_transmission(
8870        &self,
8871        request: virtual_line_in::StopTransmissionRequest,
8872    ) -> Result<()>;
8873}
8874
8875#[allow(async_fn_in_trait)]
8876/// Zone config stuff, eg getting all the configured sonos zones
8877pub trait ZoneGroupTopology {
8878    async fn begin_software_update(
8879        &self,
8880        request: zone_group_topology::BeginSoftwareUpdateRequest,
8881    ) -> Result<()>;
8882    async fn check_for_update(
8883        &self,
8884        request: zone_group_topology::CheckForUpdateRequest,
8885    ) -> Result<zone_group_topology::CheckForUpdateResponse>;
8886    /// Get information about the current Zone
8887    async fn get_zone_group_attributes(
8888        &self,
8889    ) -> Result<zone_group_topology::GetZoneGroupAttributesResponse>;
8890    /// Get all the Sonos groups, (as XML)
8891    async fn get_zone_group_state(&self) -> Result<zone_group_topology::GetZoneGroupStateResponse>;
8892    async fn register_mobile_device(
8893        &self,
8894        request: zone_group_topology::RegisterMobileDeviceRequest,
8895    ) -> Result<()>;
8896    async fn report_alarm_started_running(&self) -> Result<()>;
8897    async fn report_unresponsive_device(
8898        &self,
8899        request: zone_group_topology::ReportUnresponsiveDeviceRequest,
8900    ) -> Result<()>;
8901    async fn submit_diagnostics(
8902        &self,
8903        request: zone_group_topology::SubmitDiagnosticsRequest,
8904    ) -> Result<zone_group_topology::SubmitDiagnosticsResponse>;
8905}
8906
8907impl AVTransport for SonosDevice {
8908    async fn add_multiple_uris_to_queue(
8909        &self,
8910        request: av_transport::AddMultipleUrisToQueueRequest,
8911    ) -> Result<av_transport::AddMultipleUrisToQueueResponse> {
8912        self.action(
8913            &av_transport::SERVICE_TYPE,
8914            "AddMultipleURIsToQueue",
8915            request,
8916        )
8917        .await
8918    }
8919
8920    async fn add_uri_to_queue(
8921        &self,
8922        request: av_transport::AddUriToQueueRequest,
8923    ) -> Result<av_transport::AddUriToQueueResponse> {
8924        self.action(&av_transport::SERVICE_TYPE, "AddURIToQueue", request)
8925            .await
8926    }
8927
8928    async fn add_uri_to_saved_queue(
8929        &self,
8930        request: av_transport::AddUriToSavedQueueRequest,
8931    ) -> Result<av_transport::AddUriToSavedQueueResponse> {
8932        self.action(&av_transport::SERVICE_TYPE, "AddURIToSavedQueue", request)
8933            .await
8934    }
8935
8936    async fn backup_queue(&self, request: av_transport::BackupQueueRequest) -> Result<()> {
8937        self.action(&av_transport::SERVICE_TYPE, "BackupQueue", request)
8938            .await
8939    }
8940
8941    async fn become_coordinator_of_standalone_group(
8942        &self,
8943        request: av_transport::BecomeCoordinatorOfStandaloneGroupRequest,
8944    ) -> Result<av_transport::BecomeCoordinatorOfStandaloneGroupResponse> {
8945        self.action(
8946            &av_transport::SERVICE_TYPE,
8947            "BecomeCoordinatorOfStandaloneGroup",
8948            request,
8949        )
8950        .await
8951    }
8952
8953    async fn become_group_coordinator(
8954        &self,
8955        request: av_transport::BecomeGroupCoordinatorRequest,
8956    ) -> Result<()> {
8957        self.action(
8958            &av_transport::SERVICE_TYPE,
8959            "BecomeGroupCoordinator",
8960            request,
8961        )
8962        .await
8963    }
8964
8965    async fn become_group_coordinator_and_source(
8966        &self,
8967        request: av_transport::BecomeGroupCoordinatorAndSourceRequest,
8968    ) -> Result<()> {
8969        self.action(
8970            &av_transport::SERVICE_TYPE,
8971            "BecomeGroupCoordinatorAndSource",
8972            request,
8973        )
8974        .await
8975    }
8976
8977    async fn change_coordinator(
8978        &self,
8979        request: av_transport::ChangeCoordinatorRequest,
8980    ) -> Result<()> {
8981        self.action(&av_transport::SERVICE_TYPE, "ChangeCoordinator", request)
8982            .await
8983    }
8984
8985    async fn change_transport_settings(
8986        &self,
8987        request: av_transport::ChangeTransportSettingsRequest,
8988    ) -> Result<()> {
8989        self.action(
8990            &av_transport::SERVICE_TYPE,
8991            "ChangeTransportSettings",
8992            request,
8993        )
8994        .await
8995    }
8996
8997    async fn configure_sleep_timer(
8998        &self,
8999        request: av_transport::ConfigureSleepTimerRequest,
9000    ) -> Result<()> {
9001        self.action(&av_transport::SERVICE_TYPE, "ConfigureSleepTimer", request)
9002            .await
9003    }
9004
9005    async fn create_saved_queue(
9006        &self,
9007        request: av_transport::CreateSavedQueueRequest,
9008    ) -> Result<av_transport::CreateSavedQueueResponse> {
9009        self.action(&av_transport::SERVICE_TYPE, "CreateSavedQueue", request)
9010            .await
9011    }
9012
9013    async fn delegate_group_coordination_to(
9014        &self,
9015        request: av_transport::DelegateGroupCoordinationToRequest,
9016    ) -> Result<()> {
9017        self.action(
9018            &av_transport::SERVICE_TYPE,
9019            "DelegateGroupCoordinationTo",
9020            request,
9021        )
9022        .await
9023    }
9024
9025    async fn end_direct_control_session(
9026        &self,
9027        request: av_transport::EndDirectControlSessionRequest,
9028    ) -> Result<()> {
9029        self.action(
9030            &av_transport::SERVICE_TYPE,
9031            "EndDirectControlSession",
9032            request,
9033        )
9034        .await
9035    }
9036
9037    async fn get_crossfade_mode(
9038        &self,
9039        request: av_transport::GetCrossfadeModeRequest,
9040    ) -> Result<av_transport::GetCrossfadeModeResponse> {
9041        self.action(&av_transport::SERVICE_TYPE, "GetCrossfadeMode", request)
9042            .await
9043    }
9044
9045    async fn get_current_transport_actions(
9046        &self,
9047        request: av_transport::GetCurrentTransportActionsRequest,
9048    ) -> Result<av_transport::GetCurrentTransportActionsResponse> {
9049        self.action(
9050            &av_transport::SERVICE_TYPE,
9051            "GetCurrentTransportActions",
9052            request,
9053        )
9054        .await
9055    }
9056
9057    async fn get_device_capabilities(
9058        &self,
9059        request: av_transport::GetDeviceCapabilitiesRequest,
9060    ) -> Result<av_transport::GetDeviceCapabilitiesResponse> {
9061        self.action(
9062            &av_transport::SERVICE_TYPE,
9063            "GetDeviceCapabilities",
9064            request,
9065        )
9066        .await
9067    }
9068
9069    async fn get_media_info(
9070        &self,
9071        request: av_transport::GetMediaInfoRequest,
9072    ) -> Result<av_transport::GetMediaInfoResponse> {
9073        self.action(&av_transport::SERVICE_TYPE, "GetMediaInfo", request)
9074            .await
9075    }
9076
9077    async fn get_position_info(
9078        &self,
9079        request: av_transport::GetPositionInfoRequest,
9080    ) -> Result<av_transport::GetPositionInfoResponse> {
9081        self.action(&av_transport::SERVICE_TYPE, "GetPositionInfo", request)
9082            .await
9083    }
9084
9085    async fn get_remaining_sleep_timer_duration(
9086        &self,
9087        request: av_transport::GetRemainingSleepTimerDurationRequest,
9088    ) -> Result<av_transport::GetRemainingSleepTimerDurationResponse> {
9089        self.action(
9090            &av_transport::SERVICE_TYPE,
9091            "GetRemainingSleepTimerDuration",
9092            request,
9093        )
9094        .await
9095    }
9096
9097    async fn get_running_alarm_properties(
9098        &self,
9099        request: av_transport::GetRunningAlarmPropertiesRequest,
9100    ) -> Result<av_transport::GetRunningAlarmPropertiesResponse> {
9101        self.action(
9102            &av_transport::SERVICE_TYPE,
9103            "GetRunningAlarmProperties",
9104            request,
9105        )
9106        .await
9107    }
9108
9109    async fn get_transport_info(
9110        &self,
9111        request: av_transport::GetTransportInfoRequest,
9112    ) -> Result<av_transport::GetTransportInfoResponse> {
9113        self.action(&av_transport::SERVICE_TYPE, "GetTransportInfo", request)
9114            .await
9115    }
9116
9117    async fn get_transport_settings(
9118        &self,
9119        request: av_transport::GetTransportSettingsRequest,
9120    ) -> Result<av_transport::GetTransportSettingsResponse> {
9121        self.action(&av_transport::SERVICE_TYPE, "GetTransportSettings", request)
9122            .await
9123    }
9124
9125    async fn next(&self, request: av_transport::NextRequest) -> Result<()> {
9126        self.action(&av_transport::SERVICE_TYPE, "Next", request)
9127            .await
9128    }
9129
9130    async fn notify_deleted_uri(
9131        &self,
9132        request: av_transport::NotifyDeletedUriRequest,
9133    ) -> Result<()> {
9134        self.action(&av_transport::SERVICE_TYPE, "NotifyDeletedURI", request)
9135            .await
9136    }
9137
9138    async fn pause(&self, request: av_transport::PauseRequest) -> Result<()> {
9139        self.action(&av_transport::SERVICE_TYPE, "Pause", request)
9140            .await
9141    }
9142
9143    async fn play(&self, request: av_transport::PlayRequest) -> Result<()> {
9144        self.action(&av_transport::SERVICE_TYPE, "Play", request)
9145            .await
9146    }
9147
9148    async fn previous(&self, request: av_transport::PreviousRequest) -> Result<()> {
9149        self.action(&av_transport::SERVICE_TYPE, "Previous", request)
9150            .await
9151    }
9152
9153    async fn remove_all_tracks_from_queue(
9154        &self,
9155        request: av_transport::RemoveAllTracksFromQueueRequest,
9156    ) -> Result<()> {
9157        self.action(
9158            &av_transport::SERVICE_TYPE,
9159            "RemoveAllTracksFromQueue",
9160            request,
9161        )
9162        .await
9163    }
9164
9165    async fn remove_track_from_queue(
9166        &self,
9167        request: av_transport::RemoveTrackFromQueueRequest,
9168    ) -> Result<()> {
9169        self.action(&av_transport::SERVICE_TYPE, "RemoveTrackFromQueue", request)
9170            .await
9171    }
9172
9173    async fn remove_track_range_from_queue(
9174        &self,
9175        request: av_transport::RemoveTrackRangeFromQueueRequest,
9176    ) -> Result<av_transport::RemoveTrackRangeFromQueueResponse> {
9177        self.action(
9178            &av_transport::SERVICE_TYPE,
9179            "RemoveTrackRangeFromQueue",
9180            request,
9181        )
9182        .await
9183    }
9184
9185    async fn reorder_tracks_in_queue(
9186        &self,
9187        request: av_transport::ReorderTracksInQueueRequest,
9188    ) -> Result<()> {
9189        self.action(&av_transport::SERVICE_TYPE, "ReorderTracksInQueue", request)
9190            .await
9191    }
9192
9193    async fn reorder_tracks_in_saved_queue(
9194        &self,
9195        request: av_transport::ReorderTracksInSavedQueueRequest,
9196    ) -> Result<av_transport::ReorderTracksInSavedQueueResponse> {
9197        self.action(
9198            &av_transport::SERVICE_TYPE,
9199            "ReorderTracksInSavedQueue",
9200            request,
9201        )
9202        .await
9203    }
9204
9205    async fn run_alarm(&self, request: av_transport::RunAlarmRequest) -> Result<()> {
9206        self.action(&av_transport::SERVICE_TYPE, "RunAlarm", request)
9207            .await
9208    }
9209
9210    async fn save_queue(
9211        &self,
9212        request: av_transport::SaveQueueRequest,
9213    ) -> Result<av_transport::SaveQueueResponse> {
9214        self.action(&av_transport::SERVICE_TYPE, "SaveQueue", request)
9215            .await
9216    }
9217
9218    async fn seek(&self, request: av_transport::SeekRequest) -> Result<()> {
9219        self.action(&av_transport::SERVICE_TYPE, "Seek", request)
9220            .await
9221    }
9222
9223    async fn set_av_transport_uri(
9224        &self,
9225        request: av_transport::SetAvTransportUriRequest,
9226    ) -> Result<()> {
9227        self.action(&av_transport::SERVICE_TYPE, "SetAVTransportURI", request)
9228            .await
9229    }
9230
9231    async fn set_crossfade_mode(
9232        &self,
9233        request: av_transport::SetCrossfadeModeRequest,
9234    ) -> Result<()> {
9235        self.action(&av_transport::SERVICE_TYPE, "SetCrossfadeMode", request)
9236            .await
9237    }
9238
9239    async fn set_next_av_transport_uri(
9240        &self,
9241        request: av_transport::SetNextAvTransportUriRequest,
9242    ) -> Result<()> {
9243        self.action(
9244            &av_transport::SERVICE_TYPE,
9245            "SetNextAVTransportURI",
9246            request,
9247        )
9248        .await
9249    }
9250
9251    async fn set_play_mode(&self, request: av_transport::SetPlayModeRequest) -> Result<()> {
9252        self.action(&av_transport::SERVICE_TYPE, "SetPlayMode", request)
9253            .await
9254    }
9255
9256    async fn snooze_alarm(&self, request: av_transport::SnoozeAlarmRequest) -> Result<()> {
9257        self.action(&av_transport::SERVICE_TYPE, "SnoozeAlarm", request)
9258            .await
9259    }
9260
9261    async fn start_autoplay(&self, request: av_transport::StartAutoplayRequest) -> Result<()> {
9262        self.action(&av_transport::SERVICE_TYPE, "StartAutoplay", request)
9263            .await
9264    }
9265
9266    async fn stop(&self, request: av_transport::StopRequest) -> Result<()> {
9267        self.action(&av_transport::SERVICE_TYPE, "Stop", request)
9268            .await
9269    }
9270}
9271
9272impl AlarmClock for SonosDevice {
9273    async fn create_alarm(
9274        &self,
9275        request: alarm_clock::CreateAlarmRequest,
9276    ) -> Result<alarm_clock::CreateAlarmResponse> {
9277        self.action(&alarm_clock::SERVICE_TYPE, "CreateAlarm", request)
9278            .await
9279    }
9280
9281    async fn destroy_alarm(&self, request: alarm_clock::DestroyAlarmRequest) -> Result<()> {
9282        self.action(&alarm_clock::SERVICE_TYPE, "DestroyAlarm", request)
9283            .await
9284    }
9285
9286    async fn get_daily_index_refresh_time(
9287        &self,
9288    ) -> Result<alarm_clock::GetDailyIndexRefreshTimeResponse> {
9289        self.action(
9290            &alarm_clock::SERVICE_TYPE,
9291            "GetDailyIndexRefreshTime",
9292            crate::soap::Unit {},
9293        )
9294        .await
9295    }
9296
9297    async fn get_format(&self) -> Result<alarm_clock::GetFormatResponse> {
9298        self.action(
9299            &alarm_clock::SERVICE_TYPE,
9300            "GetFormat",
9301            crate::soap::Unit {},
9302        )
9303        .await
9304    }
9305
9306    async fn get_household_time_at_stamp(
9307        &self,
9308        request: alarm_clock::GetHouseholdTimeAtStampRequest,
9309    ) -> Result<alarm_clock::GetHouseholdTimeAtStampResponse> {
9310        self.action(
9311            &alarm_clock::SERVICE_TYPE,
9312            "GetHouseholdTimeAtStamp",
9313            request,
9314        )
9315        .await
9316    }
9317
9318    async fn get_time_now(&self) -> Result<alarm_clock::GetTimeNowResponse> {
9319        self.action(
9320            &alarm_clock::SERVICE_TYPE,
9321            "GetTimeNow",
9322            crate::soap::Unit {},
9323        )
9324        .await
9325    }
9326
9327    async fn get_time_server(&self) -> Result<alarm_clock::GetTimeServerResponse> {
9328        self.action(
9329            &alarm_clock::SERVICE_TYPE,
9330            "GetTimeServer",
9331            crate::soap::Unit {},
9332        )
9333        .await
9334    }
9335
9336    async fn get_time_zone(&self) -> Result<alarm_clock::GetTimeZoneResponse> {
9337        self.action(
9338            &alarm_clock::SERVICE_TYPE,
9339            "GetTimeZone",
9340            crate::soap::Unit {},
9341        )
9342        .await
9343    }
9344
9345    async fn get_time_zone_and_rule(&self) -> Result<alarm_clock::GetTimeZoneAndRuleResponse> {
9346        self.action(
9347            &alarm_clock::SERVICE_TYPE,
9348            "GetTimeZoneAndRule",
9349            crate::soap::Unit {},
9350        )
9351        .await
9352    }
9353
9354    async fn get_time_zone_rule(
9355        &self,
9356        request: alarm_clock::GetTimeZoneRuleRequest,
9357    ) -> Result<alarm_clock::GetTimeZoneRuleResponse> {
9358        self.action(&alarm_clock::SERVICE_TYPE, "GetTimeZoneRule", request)
9359            .await
9360    }
9361
9362    async fn list_alarms(&self) -> Result<alarm_clock::ListAlarmsResponse> {
9363        self.action(
9364            &alarm_clock::SERVICE_TYPE,
9365            "ListAlarms",
9366            crate::soap::Unit {},
9367        )
9368        .await
9369    }
9370
9371    async fn set_daily_index_refresh_time(
9372        &self,
9373        request: alarm_clock::SetDailyIndexRefreshTimeRequest,
9374    ) -> Result<()> {
9375        self.action(
9376            &alarm_clock::SERVICE_TYPE,
9377            "SetDailyIndexRefreshTime",
9378            request,
9379        )
9380        .await
9381    }
9382
9383    async fn set_format(&self, request: alarm_clock::SetFormatRequest) -> Result<()> {
9384        self.action(&alarm_clock::SERVICE_TYPE, "SetFormat", request)
9385            .await
9386    }
9387
9388    async fn set_time_now(&self, request: alarm_clock::SetTimeNowRequest) -> Result<()> {
9389        self.action(&alarm_clock::SERVICE_TYPE, "SetTimeNow", request)
9390            .await
9391    }
9392
9393    async fn set_time_server(&self, request: alarm_clock::SetTimeServerRequest) -> Result<()> {
9394        self.action(&alarm_clock::SERVICE_TYPE, "SetTimeServer", request)
9395            .await
9396    }
9397
9398    async fn set_time_zone(&self, request: alarm_clock::SetTimeZoneRequest) -> Result<()> {
9399        self.action(&alarm_clock::SERVICE_TYPE, "SetTimeZone", request)
9400            .await
9401    }
9402
9403    async fn update_alarm(&self, request: alarm_clock::UpdateAlarmRequest) -> Result<()> {
9404        self.action(&alarm_clock::SERVICE_TYPE, "UpdateAlarm", request)
9405            .await
9406    }
9407}
9408
9409impl AudioIn for SonosDevice {
9410    async fn get_audio_input_attributes(
9411        &self,
9412    ) -> Result<audio_in::GetAudioInputAttributesResponse> {
9413        self.action(
9414            &audio_in::SERVICE_TYPE,
9415            "GetAudioInputAttributes",
9416            crate::soap::Unit {},
9417        )
9418        .await
9419    }
9420
9421    async fn get_line_in_level(&self) -> Result<audio_in::GetLineInLevelResponse> {
9422        self.action(
9423            &audio_in::SERVICE_TYPE,
9424            "GetLineInLevel",
9425            crate::soap::Unit {},
9426        )
9427        .await
9428    }
9429
9430    async fn select_audio(&self, request: audio_in::SelectAudioRequest) -> Result<()> {
9431        self.action(&audio_in::SERVICE_TYPE, "SelectAudio", request)
9432            .await
9433    }
9434
9435    async fn set_audio_input_attributes(
9436        &self,
9437        request: audio_in::SetAudioInputAttributesRequest,
9438    ) -> Result<()> {
9439        self.action(&audio_in::SERVICE_TYPE, "SetAudioInputAttributes", request)
9440            .await
9441    }
9442
9443    async fn set_line_in_level(&self, request: audio_in::SetLineInLevelRequest) -> Result<()> {
9444        self.action(&audio_in::SERVICE_TYPE, "SetLineInLevel", request)
9445            .await
9446    }
9447
9448    async fn start_transmission_to_group(
9449        &self,
9450        request: audio_in::StartTransmissionToGroupRequest,
9451    ) -> Result<audio_in::StartTransmissionToGroupResponse> {
9452        self.action(&audio_in::SERVICE_TYPE, "StartTransmissionToGroup", request)
9453            .await
9454    }
9455
9456    async fn stop_transmission_to_group(
9457        &self,
9458        request: audio_in::StopTransmissionToGroupRequest,
9459    ) -> Result<()> {
9460        self.action(&audio_in::SERVICE_TYPE, "StopTransmissionToGroup", request)
9461            .await
9462    }
9463}
9464
9465impl ConnectionManager for SonosDevice {
9466    async fn get_current_connection_ids(
9467        &self,
9468    ) -> Result<connection_manager::GetCurrentConnectionIdsResponse> {
9469        self.action(
9470            &connection_manager::SERVICE_TYPE,
9471            "GetCurrentConnectionIDs",
9472            crate::soap::Unit {},
9473        )
9474        .await
9475    }
9476
9477    async fn get_current_connection_info(
9478        &self,
9479        request: connection_manager::GetCurrentConnectionInfoRequest,
9480    ) -> Result<connection_manager::GetCurrentConnectionInfoResponse> {
9481        self.action(
9482            &connection_manager::SERVICE_TYPE,
9483            "GetCurrentConnectionInfo",
9484            request,
9485        )
9486        .await
9487    }
9488
9489    async fn get_protocol_info(&self) -> Result<connection_manager::GetProtocolInfoResponse> {
9490        self.action(
9491            &connection_manager::SERVICE_TYPE,
9492            "GetProtocolInfo",
9493            crate::soap::Unit {},
9494        )
9495        .await
9496    }
9497}
9498
9499impl ContentDirectory for SonosDevice {
9500    async fn browse(
9501        &self,
9502        request: content_directory::BrowseRequest,
9503    ) -> Result<content_directory::BrowseResponse> {
9504        self.action(&content_directory::SERVICE_TYPE, "Browse", request)
9505            .await
9506    }
9507
9508    async fn create_object(
9509        &self,
9510        request: content_directory::CreateObjectRequest,
9511    ) -> Result<content_directory::CreateObjectResponse> {
9512        self.action(&content_directory::SERVICE_TYPE, "CreateObject", request)
9513            .await
9514    }
9515
9516    async fn destroy_object(&self, request: content_directory::DestroyObjectRequest) -> Result<()> {
9517        self.action(&content_directory::SERVICE_TYPE, "DestroyObject", request)
9518            .await
9519    }
9520
9521    async fn find_prefix(
9522        &self,
9523        request: content_directory::FindPrefixRequest,
9524    ) -> Result<content_directory::FindPrefixResponse> {
9525        self.action(&content_directory::SERVICE_TYPE, "FindPrefix", request)
9526            .await
9527    }
9528
9529    async fn get_album_artist_display_option(
9530        &self,
9531    ) -> Result<content_directory::GetAlbumArtistDisplayOptionResponse> {
9532        self.action(
9533            &content_directory::SERVICE_TYPE,
9534            "GetAlbumArtistDisplayOption",
9535            crate::soap::Unit {},
9536        )
9537        .await
9538    }
9539
9540    async fn get_all_prefix_locations(
9541        &self,
9542        request: content_directory::GetAllPrefixLocationsRequest,
9543    ) -> Result<content_directory::GetAllPrefixLocationsResponse> {
9544        self.action(
9545            &content_directory::SERVICE_TYPE,
9546            "GetAllPrefixLocations",
9547            request,
9548        )
9549        .await
9550    }
9551
9552    async fn get_browseable(&self) -> Result<content_directory::GetBrowseableResponse> {
9553        self.action(
9554            &content_directory::SERVICE_TYPE,
9555            "GetBrowseable",
9556            crate::soap::Unit {},
9557        )
9558        .await
9559    }
9560
9561    async fn get_last_index_change(&self) -> Result<content_directory::GetLastIndexChangeResponse> {
9562        self.action(
9563            &content_directory::SERVICE_TYPE,
9564            "GetLastIndexChange",
9565            crate::soap::Unit {},
9566        )
9567        .await
9568    }
9569
9570    async fn get_search_capabilities(
9571        &self,
9572    ) -> Result<content_directory::GetSearchCapabilitiesResponse> {
9573        self.action(
9574            &content_directory::SERVICE_TYPE,
9575            "GetSearchCapabilities",
9576            crate::soap::Unit {},
9577        )
9578        .await
9579    }
9580
9581    async fn get_share_index_in_progress(
9582        &self,
9583    ) -> Result<content_directory::GetShareIndexInProgressResponse> {
9584        self.action(
9585            &content_directory::SERVICE_TYPE,
9586            "GetShareIndexInProgress",
9587            crate::soap::Unit {},
9588        )
9589        .await
9590    }
9591
9592    async fn get_sort_capabilities(
9593        &self,
9594    ) -> Result<content_directory::GetSortCapabilitiesResponse> {
9595        self.action(
9596            &content_directory::SERVICE_TYPE,
9597            "GetSortCapabilities",
9598            crate::soap::Unit {},
9599        )
9600        .await
9601    }
9602
9603    async fn get_system_update_id(&self) -> Result<content_directory::GetSystemUpdateIdResponse> {
9604        self.action(
9605            &content_directory::SERVICE_TYPE,
9606            "GetSystemUpdateID",
9607            crate::soap::Unit {},
9608        )
9609        .await
9610    }
9611
9612    async fn refresh_share_index(
9613        &self,
9614        request: content_directory::RefreshShareIndexRequest,
9615    ) -> Result<()> {
9616        self.action(
9617            &content_directory::SERVICE_TYPE,
9618            "RefreshShareIndex",
9619            request,
9620        )
9621        .await
9622    }
9623
9624    async fn request_resort(&self, request: content_directory::RequestResortRequest) -> Result<()> {
9625        self.action(&content_directory::SERVICE_TYPE, "RequestResort", request)
9626            .await
9627    }
9628
9629    async fn set_browseable(&self, request: content_directory::SetBrowseableRequest) -> Result<()> {
9630        self.action(&content_directory::SERVICE_TYPE, "SetBrowseable", request)
9631            .await
9632    }
9633
9634    async fn update_object(&self, request: content_directory::UpdateObjectRequest) -> Result<()> {
9635        self.action(&content_directory::SERVICE_TYPE, "UpdateObject", request)
9636            .await
9637    }
9638}
9639
9640impl DeviceProperties for SonosDevice {
9641    async fn add_bonded_zones(
9642        &self,
9643        request: device_properties::AddBondedZonesRequest,
9644    ) -> Result<()> {
9645        self.action(&device_properties::SERVICE_TYPE, "AddBondedZones", request)
9646            .await
9647    }
9648
9649    async fn add_ht_satellite(
9650        &self,
9651        request: device_properties::AddHtSatelliteRequest,
9652    ) -> Result<()> {
9653        self.action(&device_properties::SERVICE_TYPE, "AddHTSatellite", request)
9654            .await
9655    }
9656
9657    async fn create_stereo_pair(
9658        &self,
9659        request: device_properties::CreateStereoPairRequest,
9660    ) -> Result<()> {
9661        self.action(
9662            &device_properties::SERVICE_TYPE,
9663            "CreateStereoPair",
9664            request,
9665        )
9666        .await
9667    }
9668
9669    async fn enter_config_mode(
9670        &self,
9671        request: device_properties::EnterConfigModeRequest,
9672    ) -> Result<device_properties::EnterConfigModeResponse> {
9673        self.action(&device_properties::SERVICE_TYPE, "EnterConfigMode", request)
9674            .await
9675    }
9676
9677    async fn exit_config_mode(
9678        &self,
9679        request: device_properties::ExitConfigModeRequest,
9680    ) -> Result<()> {
9681        self.action(&device_properties::SERVICE_TYPE, "ExitConfigMode", request)
9682            .await
9683    }
9684
9685    async fn get_autoplay_linked_zones(
9686        &self,
9687        request: device_properties::GetAutoplayLinkedZonesRequest,
9688    ) -> Result<device_properties::GetAutoplayLinkedZonesResponse> {
9689        self.action(
9690            &device_properties::SERVICE_TYPE,
9691            "GetAutoplayLinkedZones",
9692            request,
9693        )
9694        .await
9695    }
9696
9697    async fn get_autoplay_room_uuid(
9698        &self,
9699        request: device_properties::GetAutoplayRoomUuidRequest,
9700    ) -> Result<device_properties::GetAutoplayRoomUuidResponse> {
9701        self.action(
9702            &device_properties::SERVICE_TYPE,
9703            "GetAutoplayRoomUUID",
9704            request,
9705        )
9706        .await
9707    }
9708
9709    async fn get_autoplay_volume(
9710        &self,
9711        request: device_properties::GetAutoplayVolumeRequest,
9712    ) -> Result<device_properties::GetAutoplayVolumeResponse> {
9713        self.action(
9714            &device_properties::SERVICE_TYPE,
9715            "GetAutoplayVolume",
9716            request,
9717        )
9718        .await
9719    }
9720
9721    async fn get_button_lock_state(&self) -> Result<device_properties::GetButtonLockStateResponse> {
9722        self.action(
9723            &device_properties::SERVICE_TYPE,
9724            "GetButtonLockState",
9725            crate::soap::Unit {},
9726        )
9727        .await
9728    }
9729
9730    async fn get_button_state(&self) -> Result<device_properties::GetButtonStateResponse> {
9731        self.action(
9732            &device_properties::SERVICE_TYPE,
9733            "GetButtonState",
9734            crate::soap::Unit {},
9735        )
9736        .await
9737    }
9738
9739    async fn get_ht_forward_state(&self) -> Result<device_properties::GetHtForwardStateResponse> {
9740        self.action(
9741            &device_properties::SERVICE_TYPE,
9742            "GetHTForwardState",
9743            crate::soap::Unit {},
9744        )
9745        .await
9746    }
9747
9748    async fn get_household_id(&self) -> Result<device_properties::GetHouseholdIdResponse> {
9749        self.action(
9750            &device_properties::SERVICE_TYPE,
9751            "GetHouseholdID",
9752            crate::soap::Unit {},
9753        )
9754        .await
9755    }
9756
9757    async fn get_led_state(&self) -> Result<device_properties::GetLedStateResponse> {
9758        self.action(
9759            &device_properties::SERVICE_TYPE,
9760            "GetLEDState",
9761            crate::soap::Unit {},
9762        )
9763        .await
9764    }
9765
9766    async fn get_use_autoplay_volume(
9767        &self,
9768        request: device_properties::GetUseAutoplayVolumeRequest,
9769    ) -> Result<device_properties::GetUseAutoplayVolumeResponse> {
9770        self.action(
9771            &device_properties::SERVICE_TYPE,
9772            "GetUseAutoplayVolume",
9773            request,
9774        )
9775        .await
9776    }
9777
9778    async fn get_zone_attributes(&self) -> Result<device_properties::GetZoneAttributesResponse> {
9779        self.action(
9780            &device_properties::SERVICE_TYPE,
9781            "GetZoneAttributes",
9782            crate::soap::Unit {},
9783        )
9784        .await
9785    }
9786
9787    async fn get_zone_info(&self) -> Result<device_properties::GetZoneInfoResponse> {
9788        self.action(
9789            &device_properties::SERVICE_TYPE,
9790            "GetZoneInfo",
9791            crate::soap::Unit {},
9792        )
9793        .await
9794    }
9795
9796    async fn remove_bonded_zones(
9797        &self,
9798        request: device_properties::RemoveBondedZonesRequest,
9799    ) -> Result<()> {
9800        self.action(
9801            &device_properties::SERVICE_TYPE,
9802            "RemoveBondedZones",
9803            request,
9804        )
9805        .await
9806    }
9807
9808    async fn remove_ht_satellite(
9809        &self,
9810        request: device_properties::RemoveHtSatelliteRequest,
9811    ) -> Result<()> {
9812        self.action(
9813            &device_properties::SERVICE_TYPE,
9814            "RemoveHTSatellite",
9815            request,
9816        )
9817        .await
9818    }
9819
9820    async fn room_detection_start_chirping(
9821        &self,
9822        request: device_properties::RoomDetectionStartChirpingRequest,
9823    ) -> Result<device_properties::RoomDetectionStartChirpingResponse> {
9824        self.action(
9825            &device_properties::SERVICE_TYPE,
9826            "RoomDetectionStartChirping",
9827            request,
9828        )
9829        .await
9830    }
9831
9832    async fn room_detection_stop_chirping(
9833        &self,
9834        request: device_properties::RoomDetectionStopChirpingRequest,
9835    ) -> Result<()> {
9836        self.action(
9837            &device_properties::SERVICE_TYPE,
9838            "RoomDetectionStopChirping",
9839            request,
9840        )
9841        .await
9842    }
9843
9844    async fn separate_stereo_pair(
9845        &self,
9846        request: device_properties::SeparateStereoPairRequest,
9847    ) -> Result<()> {
9848        self.action(
9849            &device_properties::SERVICE_TYPE,
9850            "SeparateStereoPair",
9851            request,
9852        )
9853        .await
9854    }
9855
9856    async fn set_autoplay_linked_zones(
9857        &self,
9858        request: device_properties::SetAutoplayLinkedZonesRequest,
9859    ) -> Result<()> {
9860        self.action(
9861            &device_properties::SERVICE_TYPE,
9862            "SetAutoplayLinkedZones",
9863            request,
9864        )
9865        .await
9866    }
9867
9868    async fn set_autoplay_room_uuid(
9869        &self,
9870        request: device_properties::SetAutoplayRoomUuidRequest,
9871    ) -> Result<()> {
9872        self.action(
9873            &device_properties::SERVICE_TYPE,
9874            "SetAutoplayRoomUUID",
9875            request,
9876        )
9877        .await
9878    }
9879
9880    async fn set_autoplay_volume(
9881        &self,
9882        request: device_properties::SetAutoplayVolumeRequest,
9883    ) -> Result<()> {
9884        self.action(
9885            &device_properties::SERVICE_TYPE,
9886            "SetAutoplayVolume",
9887            request,
9888        )
9889        .await
9890    }
9891
9892    async fn set_button_lock_state(
9893        &self,
9894        request: device_properties::SetButtonLockStateRequest,
9895    ) -> Result<()> {
9896        self.action(
9897            &device_properties::SERVICE_TYPE,
9898            "SetButtonLockState",
9899            request,
9900        )
9901        .await
9902    }
9903
9904    async fn set_led_state(&self, request: device_properties::SetLedStateRequest) -> Result<()> {
9905        self.action(&device_properties::SERVICE_TYPE, "SetLEDState", request)
9906            .await
9907    }
9908
9909    async fn set_use_autoplay_volume(
9910        &self,
9911        request: device_properties::SetUseAutoplayVolumeRequest,
9912    ) -> Result<()> {
9913        self.action(
9914            &device_properties::SERVICE_TYPE,
9915            "SetUseAutoplayVolume",
9916            request,
9917        )
9918        .await
9919    }
9920
9921    async fn set_zone_attributes(
9922        &self,
9923        request: device_properties::SetZoneAttributesRequest,
9924    ) -> Result<()> {
9925        self.action(
9926            &device_properties::SERVICE_TYPE,
9927            "SetZoneAttributes",
9928            request,
9929        )
9930        .await
9931    }
9932}
9933
9934impl GroupManagement for SonosDevice {
9935    async fn add_member(
9936        &self,
9937        request: group_management::AddMemberRequest,
9938    ) -> Result<group_management::AddMemberResponse> {
9939        self.action(&group_management::SERVICE_TYPE, "AddMember", request)
9940            .await
9941    }
9942
9943    async fn remove_member(&self, request: group_management::RemoveMemberRequest) -> Result<()> {
9944        self.action(&group_management::SERVICE_TYPE, "RemoveMember", request)
9945            .await
9946    }
9947
9948    async fn report_track_buffering_result(
9949        &self,
9950        request: group_management::ReportTrackBufferingResultRequest,
9951    ) -> Result<()> {
9952        self.action(
9953            &group_management::SERVICE_TYPE,
9954            "ReportTrackBufferingResult",
9955            request,
9956        )
9957        .await
9958    }
9959
9960    async fn set_source_area_ids(
9961        &self,
9962        request: group_management::SetSourceAreaIdsRequest,
9963    ) -> Result<()> {
9964        self.action(&group_management::SERVICE_TYPE, "SetSourceAreaIds", request)
9965            .await
9966    }
9967}
9968
9969impl GroupRenderingControl for SonosDevice {
9970    async fn get_group_mute(
9971        &self,
9972        request: group_rendering_control::GetGroupMuteRequest,
9973    ) -> Result<group_rendering_control::GetGroupMuteResponse> {
9974        self.action(
9975            &group_rendering_control::SERVICE_TYPE,
9976            "GetGroupMute",
9977            request,
9978        )
9979        .await
9980    }
9981
9982    async fn get_group_volume(
9983        &self,
9984        request: group_rendering_control::GetGroupVolumeRequest,
9985    ) -> Result<group_rendering_control::GetGroupVolumeResponse> {
9986        self.action(
9987            &group_rendering_control::SERVICE_TYPE,
9988            "GetGroupVolume",
9989            request,
9990        )
9991        .await
9992    }
9993
9994    async fn set_group_mute(
9995        &self,
9996        request: group_rendering_control::SetGroupMuteRequest,
9997    ) -> Result<()> {
9998        self.action(
9999            &group_rendering_control::SERVICE_TYPE,
10000            "SetGroupMute",
10001            request,
10002        )
10003        .await
10004    }
10005
10006    async fn set_group_volume(
10007        &self,
10008        request: group_rendering_control::SetGroupVolumeRequest,
10009    ) -> Result<()> {
10010        self.action(
10011            &group_rendering_control::SERVICE_TYPE,
10012            "SetGroupVolume",
10013            request,
10014        )
10015        .await
10016    }
10017
10018    async fn set_relative_group_volume(
10019        &self,
10020        request: group_rendering_control::SetRelativeGroupVolumeRequest,
10021    ) -> Result<group_rendering_control::SetRelativeGroupVolumeResponse> {
10022        self.action(
10023            &group_rendering_control::SERVICE_TYPE,
10024            "SetRelativeGroupVolume",
10025            request,
10026        )
10027        .await
10028    }
10029
10030    async fn snapshot_group_volume(
10031        &self,
10032        request: group_rendering_control::SnapshotGroupVolumeRequest,
10033    ) -> Result<()> {
10034        self.action(
10035            &group_rendering_control::SERVICE_TYPE,
10036            "SnapshotGroupVolume",
10037            request,
10038        )
10039        .await
10040    }
10041}
10042
10043impl HTControl for SonosDevice {
10044    async fn commit_learned_ir_codes(
10045        &self,
10046        request: ht_control::CommitLearnedIrCodesRequest,
10047    ) -> Result<()> {
10048        self.action(&ht_control::SERVICE_TYPE, "CommitLearnedIRCodes", request)
10049            .await
10050    }
10051
10052    async fn get_ir_repeater_state(&self) -> Result<ht_control::GetIrRepeaterStateResponse> {
10053        self.action(
10054            &ht_control::SERVICE_TYPE,
10055            "GetIRRepeaterState",
10056            crate::soap::Unit {},
10057        )
10058        .await
10059    }
10060
10061    async fn get_led_feedback_state(&self) -> Result<ht_control::GetLedFeedbackStateResponse> {
10062        self.action(
10063            &ht_control::SERVICE_TYPE,
10064            "GetLEDFeedbackState",
10065            crate::soap::Unit {},
10066        )
10067        .await
10068    }
10069
10070    async fn identify_ir_remote(&self, request: ht_control::IdentifyIrRemoteRequest) -> Result<()> {
10071        self.action(&ht_control::SERVICE_TYPE, "IdentifyIRRemote", request)
10072            .await
10073    }
10074
10075    async fn is_remote_configured(&self) -> Result<ht_control::IsRemoteConfiguredResponse> {
10076        self.action(
10077            &ht_control::SERVICE_TYPE,
10078            "IsRemoteConfigured",
10079            crate::soap::Unit {},
10080        )
10081        .await
10082    }
10083
10084    async fn learn_ir_code(&self, request: ht_control::LearnIrCodeRequest) -> Result<()> {
10085        self.action(&ht_control::SERVICE_TYPE, "LearnIRCode", request)
10086            .await
10087    }
10088
10089    async fn set_ir_repeater_state(
10090        &self,
10091        request: ht_control::SetIrRepeaterStateRequest,
10092    ) -> Result<()> {
10093        self.action(&ht_control::SERVICE_TYPE, "SetIRRepeaterState", request)
10094            .await
10095    }
10096
10097    async fn set_led_feedback_state(
10098        &self,
10099        request: ht_control::SetLedFeedbackStateRequest,
10100    ) -> Result<()> {
10101        self.action(&ht_control::SERVICE_TYPE, "SetLEDFeedbackState", request)
10102            .await
10103    }
10104}
10105
10106impl MusicServices for SonosDevice {
10107    async fn get_session_id(
10108        &self,
10109        request: music_services::GetSessionIdRequest,
10110    ) -> Result<music_services::GetSessionIdResponse> {
10111        self.action(&music_services::SERVICE_TYPE, "GetSessionId", request)
10112            .await
10113    }
10114
10115    async fn list_available_services(
10116        &self,
10117    ) -> Result<music_services::ListAvailableServicesResponse> {
10118        self.action(
10119            &music_services::SERVICE_TYPE,
10120            "ListAvailableServices",
10121            crate::soap::Unit {},
10122        )
10123        .await
10124    }
10125
10126    async fn update_available_services(&self) -> Result<()> {
10127        self.action(
10128            &music_services::SERVICE_TYPE,
10129            "UpdateAvailableServices",
10130            crate::soap::Unit {},
10131        )
10132        .await
10133    }
10134}
10135
10136impl QPlay for SonosDevice {
10137    async fn q_play_auth(
10138        &self,
10139        request: q_play::QPlayAuthRequest,
10140    ) -> Result<q_play::QPlayAuthResponse> {
10141        self.action(&q_play::SERVICE_TYPE, "QPlayAuth", request)
10142            .await
10143    }
10144}
10145
10146impl Queue for SonosDevice {
10147    async fn add_multiple_uris(
10148        &self,
10149        request: queue::AddMultipleUrisRequest,
10150    ) -> Result<queue::AddMultipleUrisResponse> {
10151        self.action(&queue::SERVICE_TYPE, "AddMultipleURIs", request)
10152            .await
10153    }
10154
10155    async fn add_uri(&self, request: queue::AddUriRequest) -> Result<queue::AddUriResponse> {
10156        self.action(&queue::SERVICE_TYPE, "AddURI", request).await
10157    }
10158
10159    async fn attach_queue(
10160        &self,
10161        request: queue::AttachQueueRequest,
10162    ) -> Result<queue::AttachQueueResponse> {
10163        self.action(&queue::SERVICE_TYPE, "AttachQueue", request)
10164            .await
10165    }
10166
10167    async fn backup(&self) -> Result<()> {
10168        self.action(&queue::SERVICE_TYPE, "Backup", crate::soap::Unit {})
10169            .await
10170    }
10171
10172    async fn browse(&self, request: queue::BrowseRequest) -> Result<queue::BrowseResponse> {
10173        self.action(&queue::SERVICE_TYPE, "Browse", request).await
10174    }
10175
10176    async fn create_queue(
10177        &self,
10178        request: queue::CreateQueueRequest,
10179    ) -> Result<queue::CreateQueueResponse> {
10180        self.action(&queue::SERVICE_TYPE, "CreateQueue", request)
10181            .await
10182    }
10183
10184    async fn remove_all_tracks(
10185        &self,
10186        request: queue::RemoveAllTracksRequest,
10187    ) -> Result<queue::RemoveAllTracksResponse> {
10188        self.action(&queue::SERVICE_TYPE, "RemoveAllTracks", request)
10189            .await
10190    }
10191
10192    async fn remove_track_range(
10193        &self,
10194        request: queue::RemoveTrackRangeRequest,
10195    ) -> Result<queue::RemoveTrackRangeResponse> {
10196        self.action(&queue::SERVICE_TYPE, "RemoveTrackRange", request)
10197            .await
10198    }
10199
10200    async fn reorder_tracks(
10201        &self,
10202        request: queue::ReorderTracksRequest,
10203    ) -> Result<queue::ReorderTracksResponse> {
10204        self.action(&queue::SERVICE_TYPE, "ReorderTracks", request)
10205            .await
10206    }
10207
10208    async fn replace_all_tracks(
10209        &self,
10210        request: queue::ReplaceAllTracksRequest,
10211    ) -> Result<queue::ReplaceAllTracksResponse> {
10212        self.action(&queue::SERVICE_TYPE, "ReplaceAllTracks", request)
10213            .await
10214    }
10215
10216    async fn save_as_sonos_playlist(
10217        &self,
10218        request: queue::SaveAsSonosPlaylistRequest,
10219    ) -> Result<queue::SaveAsSonosPlaylistResponse> {
10220        self.action(&queue::SERVICE_TYPE, "SaveAsSonosPlaylist", request)
10221            .await
10222    }
10223}
10224
10225impl RenderingControl for SonosDevice {
10226    async fn get_bass(
10227        &self,
10228        request: rendering_control::GetBassRequest,
10229    ) -> Result<rendering_control::GetBassResponse> {
10230        self.action(&rendering_control::SERVICE_TYPE, "GetBass", request)
10231            .await
10232    }
10233
10234    async fn get_eq(
10235        &self,
10236        request: rendering_control::GetEqRequest,
10237    ) -> Result<rendering_control::GetEqResponse> {
10238        self.action(&rendering_control::SERVICE_TYPE, "GetEQ", request)
10239            .await
10240    }
10241
10242    async fn get_headphone_connected(
10243        &self,
10244        request: rendering_control::GetHeadphoneConnectedRequest,
10245    ) -> Result<rendering_control::GetHeadphoneConnectedResponse> {
10246        self.action(
10247            &rendering_control::SERVICE_TYPE,
10248            "GetHeadphoneConnected",
10249            request,
10250        )
10251        .await
10252    }
10253
10254    async fn get_loudness(
10255        &self,
10256        request: rendering_control::GetLoudnessRequest,
10257    ) -> Result<rendering_control::GetLoudnessResponse> {
10258        self.action(&rendering_control::SERVICE_TYPE, "GetLoudness", request)
10259            .await
10260    }
10261
10262    async fn get_mute(
10263        &self,
10264        request: rendering_control::GetMuteRequest,
10265    ) -> Result<rendering_control::GetMuteResponse> {
10266        self.action(&rendering_control::SERVICE_TYPE, "GetMute", request)
10267            .await
10268    }
10269
10270    async fn get_output_fixed(
10271        &self,
10272        request: rendering_control::GetOutputFixedRequest,
10273    ) -> Result<rendering_control::GetOutputFixedResponse> {
10274        self.action(&rendering_control::SERVICE_TYPE, "GetOutputFixed", request)
10275            .await
10276    }
10277
10278    async fn get_room_calibration_status(
10279        &self,
10280        request: rendering_control::GetRoomCalibrationStatusRequest,
10281    ) -> Result<rendering_control::GetRoomCalibrationStatusResponse> {
10282        self.action(
10283            &rendering_control::SERVICE_TYPE,
10284            "GetRoomCalibrationStatus",
10285            request,
10286        )
10287        .await
10288    }
10289
10290    async fn get_supports_output_fixed(
10291        &self,
10292        request: rendering_control::GetSupportsOutputFixedRequest,
10293    ) -> Result<rendering_control::GetSupportsOutputFixedResponse> {
10294        self.action(
10295            &rendering_control::SERVICE_TYPE,
10296            "GetSupportsOutputFixed",
10297            request,
10298        )
10299        .await
10300    }
10301
10302    async fn get_treble(
10303        &self,
10304        request: rendering_control::GetTrebleRequest,
10305    ) -> Result<rendering_control::GetTrebleResponse> {
10306        self.action(&rendering_control::SERVICE_TYPE, "GetTreble", request)
10307            .await
10308    }
10309
10310    async fn get_volume(
10311        &self,
10312        request: rendering_control::GetVolumeRequest,
10313    ) -> Result<rendering_control::GetVolumeResponse> {
10314        self.action(&rendering_control::SERVICE_TYPE, "GetVolume", request)
10315            .await
10316    }
10317
10318    async fn get_volume_db(
10319        &self,
10320        request: rendering_control::GetVolumeDbRequest,
10321    ) -> Result<rendering_control::GetVolumeDbResponse> {
10322        self.action(&rendering_control::SERVICE_TYPE, "GetVolumeDB", request)
10323            .await
10324    }
10325
10326    async fn get_volume_db_range(
10327        &self,
10328        request: rendering_control::GetVolumeDbRangeRequest,
10329    ) -> Result<rendering_control::GetVolumeDbRangeResponse> {
10330        self.action(
10331            &rendering_control::SERVICE_TYPE,
10332            "GetVolumeDBRange",
10333            request,
10334        )
10335        .await
10336    }
10337
10338    async fn ramp_to_volume(
10339        &self,
10340        request: rendering_control::RampToVolumeRequest,
10341    ) -> Result<rendering_control::RampToVolumeResponse> {
10342        self.action(&rendering_control::SERVICE_TYPE, "RampToVolume", request)
10343            .await
10344    }
10345
10346    async fn reset_basic_eq(
10347        &self,
10348        request: rendering_control::ResetBasicEqRequest,
10349    ) -> Result<rendering_control::ResetBasicEqResponse> {
10350        self.action(&rendering_control::SERVICE_TYPE, "ResetBasicEQ", request)
10351            .await
10352    }
10353
10354    async fn reset_ext_eq(&self, request: rendering_control::ResetExtEqRequest) -> Result<()> {
10355        self.action(&rendering_control::SERVICE_TYPE, "ResetExtEQ", request)
10356            .await
10357    }
10358
10359    async fn restore_volume_prior_to_ramp(
10360        &self,
10361        request: rendering_control::RestoreVolumePriorToRampRequest,
10362    ) -> Result<()> {
10363        self.action(
10364            &rendering_control::SERVICE_TYPE,
10365            "RestoreVolumePriorToRamp",
10366            request,
10367        )
10368        .await
10369    }
10370
10371    async fn set_bass(&self, request: rendering_control::SetBassRequest) -> Result<()> {
10372        self.action(&rendering_control::SERVICE_TYPE, "SetBass", request)
10373            .await
10374    }
10375
10376    async fn set_channel_map(
10377        &self,
10378        request: rendering_control::SetChannelMapRequest,
10379    ) -> Result<()> {
10380        self.action(&rendering_control::SERVICE_TYPE, "SetChannelMap", request)
10381            .await
10382    }
10383
10384    async fn set_eq(&self, request: rendering_control::SetEqRequest) -> Result<()> {
10385        self.action(&rendering_control::SERVICE_TYPE, "SetEQ", request)
10386            .await
10387    }
10388
10389    async fn set_loudness(&self, request: rendering_control::SetLoudnessRequest) -> Result<()> {
10390        self.action(&rendering_control::SERVICE_TYPE, "SetLoudness", request)
10391            .await
10392    }
10393
10394    async fn set_mute(&self, request: rendering_control::SetMuteRequest) -> Result<()> {
10395        self.action(&rendering_control::SERVICE_TYPE, "SetMute", request)
10396            .await
10397    }
10398
10399    async fn set_output_fixed(
10400        &self,
10401        request: rendering_control::SetOutputFixedRequest,
10402    ) -> Result<()> {
10403        self.action(&rendering_control::SERVICE_TYPE, "SetOutputFixed", request)
10404            .await
10405    }
10406
10407    async fn set_relative_volume(
10408        &self,
10409        request: rendering_control::SetRelativeVolumeRequest,
10410    ) -> Result<rendering_control::SetRelativeVolumeResponse> {
10411        self.action(
10412            &rendering_control::SERVICE_TYPE,
10413            "SetRelativeVolume",
10414            request,
10415        )
10416        .await
10417    }
10418
10419    async fn set_room_calibration_status(
10420        &self,
10421        request: rendering_control::SetRoomCalibrationStatusRequest,
10422    ) -> Result<()> {
10423        self.action(
10424            &rendering_control::SERVICE_TYPE,
10425            "SetRoomCalibrationStatus",
10426            request,
10427        )
10428        .await
10429    }
10430
10431    async fn set_room_calibration_x(
10432        &self,
10433        request: rendering_control::SetRoomCalibrationXRequest,
10434    ) -> Result<()> {
10435        self.action(
10436            &rendering_control::SERVICE_TYPE,
10437            "SetRoomCalibrationX",
10438            request,
10439        )
10440        .await
10441    }
10442
10443    async fn set_treble(&self, request: rendering_control::SetTrebleRequest) -> Result<()> {
10444        self.action(&rendering_control::SERVICE_TYPE, "SetTreble", request)
10445            .await
10446    }
10447
10448    async fn set_volume(&self, request: rendering_control::SetVolumeRequest) -> Result<()> {
10449        self.action(&rendering_control::SERVICE_TYPE, "SetVolume", request)
10450            .await
10451    }
10452
10453    async fn set_volume_db(&self, request: rendering_control::SetVolumeDbRequest) -> Result<()> {
10454        self.action(&rendering_control::SERVICE_TYPE, "SetVolumeDB", request)
10455            .await
10456    }
10457}
10458
10459impl SystemProperties for SonosDevice {
10460    async fn add_account_x(
10461        &self,
10462        request: system_properties::AddAccountXRequest,
10463    ) -> Result<system_properties::AddAccountXResponse> {
10464        self.action(&system_properties::SERVICE_TYPE, "AddAccountX", request)
10465            .await
10466    }
10467
10468    async fn add_o_auth_account_x(
10469        &self,
10470        request: system_properties::AddOAuthAccountXRequest,
10471    ) -> Result<system_properties::AddOAuthAccountXResponse> {
10472        self.action(
10473            &system_properties::SERVICE_TYPE,
10474            "AddOAuthAccountX",
10475            request,
10476        )
10477        .await
10478    }
10479
10480    async fn do_post_update_tasks(&self) -> Result<()> {
10481        self.action(
10482            &system_properties::SERVICE_TYPE,
10483            "DoPostUpdateTasks",
10484            crate::soap::Unit {},
10485        )
10486        .await
10487    }
10488
10489    async fn edit_account_md(
10490        &self,
10491        request: system_properties::EditAccountMdRequest,
10492    ) -> Result<()> {
10493        self.action(&system_properties::SERVICE_TYPE, "EditAccountMd", request)
10494            .await
10495    }
10496
10497    async fn edit_account_password_x(
10498        &self,
10499        request: system_properties::EditAccountPasswordXRequest,
10500    ) -> Result<()> {
10501        self.action(
10502            &system_properties::SERVICE_TYPE,
10503            "EditAccountPasswordX",
10504            request,
10505        )
10506        .await
10507    }
10508
10509    async fn enable_rdm(&self, request: system_properties::EnableRdmRequest) -> Result<()> {
10510        self.action(&system_properties::SERVICE_TYPE, "EnableRDM", request)
10511            .await
10512    }
10513
10514    async fn get_rdm(&self) -> Result<system_properties::GetRdmResponse> {
10515        self.action(
10516            &system_properties::SERVICE_TYPE,
10517            "GetRDM",
10518            crate::soap::Unit {},
10519        )
10520        .await
10521    }
10522
10523    async fn get_string(
10524        &self,
10525        request: system_properties::GetStringRequest,
10526    ) -> Result<system_properties::GetStringResponse> {
10527        self.action(&system_properties::SERVICE_TYPE, "GetString", request)
10528            .await
10529    }
10530
10531    async fn get_web_code(
10532        &self,
10533        request: system_properties::GetWebCodeRequest,
10534    ) -> Result<system_properties::GetWebCodeResponse> {
10535        self.action(&system_properties::SERVICE_TYPE, "GetWebCode", request)
10536            .await
10537    }
10538
10539    async fn provision_credentialed_trial_account_x(
10540        &self,
10541        request: system_properties::ProvisionCredentialedTrialAccountXRequest,
10542    ) -> Result<system_properties::ProvisionCredentialedTrialAccountXResponse> {
10543        self.action(
10544            &system_properties::SERVICE_TYPE,
10545            "ProvisionCredentialedTrialAccountX",
10546            request,
10547        )
10548        .await
10549    }
10550
10551    async fn refresh_account_credentials_x(
10552        &self,
10553        request: system_properties::RefreshAccountCredentialsXRequest,
10554    ) -> Result<()> {
10555        self.action(
10556            &system_properties::SERVICE_TYPE,
10557            "RefreshAccountCredentialsX",
10558            request,
10559        )
10560        .await
10561    }
10562
10563    async fn remove(&self, request: system_properties::RemoveRequest) -> Result<()> {
10564        self.action(&system_properties::SERVICE_TYPE, "Remove", request)
10565            .await
10566    }
10567
10568    async fn remove_account(&self, request: system_properties::RemoveAccountRequest) -> Result<()> {
10569        self.action(&system_properties::SERVICE_TYPE, "RemoveAccount", request)
10570            .await
10571    }
10572
10573    async fn replace_account_x(
10574        &self,
10575        request: system_properties::ReplaceAccountXRequest,
10576    ) -> Result<system_properties::ReplaceAccountXResponse> {
10577        self.action(&system_properties::SERVICE_TYPE, "ReplaceAccountX", request)
10578            .await
10579    }
10580
10581    async fn reset_third_party_credentials(&self) -> Result<()> {
10582        self.action(
10583            &system_properties::SERVICE_TYPE,
10584            "ResetThirdPartyCredentials",
10585            crate::soap::Unit {},
10586        )
10587        .await
10588    }
10589
10590    async fn set_account_nickname_x(
10591        &self,
10592        request: system_properties::SetAccountNicknameXRequest,
10593    ) -> Result<()> {
10594        self.action(
10595            &system_properties::SERVICE_TYPE,
10596            "SetAccountNicknameX",
10597            request,
10598        )
10599        .await
10600    }
10601
10602    async fn set_string(&self, request: system_properties::SetStringRequest) -> Result<()> {
10603        self.action(&system_properties::SERVICE_TYPE, "SetString", request)
10604            .await
10605    }
10606}
10607
10608impl VirtualLineIn for SonosDevice {
10609    async fn next(&self, request: virtual_line_in::NextRequest) -> Result<()> {
10610        self.action(&virtual_line_in::SERVICE_TYPE, "Next", request)
10611            .await
10612    }
10613
10614    async fn pause(&self, request: virtual_line_in::PauseRequest) -> Result<()> {
10615        self.action(&virtual_line_in::SERVICE_TYPE, "Pause", request)
10616            .await
10617    }
10618
10619    async fn play(&self, request: virtual_line_in::PlayRequest) -> Result<()> {
10620        self.action(&virtual_line_in::SERVICE_TYPE, "Play", request)
10621            .await
10622    }
10623
10624    async fn previous(&self, request: virtual_line_in::PreviousRequest) -> Result<()> {
10625        self.action(&virtual_line_in::SERVICE_TYPE, "Previous", request)
10626            .await
10627    }
10628
10629    async fn set_volume(&self, request: virtual_line_in::SetVolumeRequest) -> Result<()> {
10630        self.action(&virtual_line_in::SERVICE_TYPE, "SetVolume", request)
10631            .await
10632    }
10633
10634    async fn start_transmission(
10635        &self,
10636        request: virtual_line_in::StartTransmissionRequest,
10637    ) -> Result<virtual_line_in::StartTransmissionResponse> {
10638        self.action(&virtual_line_in::SERVICE_TYPE, "StartTransmission", request)
10639            .await
10640    }
10641
10642    async fn stop(&self, request: virtual_line_in::StopRequest) -> Result<()> {
10643        self.action(&virtual_line_in::SERVICE_TYPE, "Stop", request)
10644            .await
10645    }
10646
10647    async fn stop_transmission(
10648        &self,
10649        request: virtual_line_in::StopTransmissionRequest,
10650    ) -> Result<()> {
10651        self.action(&virtual_line_in::SERVICE_TYPE, "StopTransmission", request)
10652            .await
10653    }
10654}
10655
10656impl ZoneGroupTopology for SonosDevice {
10657    async fn begin_software_update(
10658        &self,
10659        request: zone_group_topology::BeginSoftwareUpdateRequest,
10660    ) -> Result<()> {
10661        self.action(
10662            &zone_group_topology::SERVICE_TYPE,
10663            "BeginSoftwareUpdate",
10664            request,
10665        )
10666        .await
10667    }
10668
10669    async fn check_for_update(
10670        &self,
10671        request: zone_group_topology::CheckForUpdateRequest,
10672    ) -> Result<zone_group_topology::CheckForUpdateResponse> {
10673        self.action(
10674            &zone_group_topology::SERVICE_TYPE,
10675            "CheckForUpdate",
10676            request,
10677        )
10678        .await
10679    }
10680
10681    async fn get_zone_group_attributes(
10682        &self,
10683    ) -> Result<zone_group_topology::GetZoneGroupAttributesResponse> {
10684        self.action(
10685            &zone_group_topology::SERVICE_TYPE,
10686            "GetZoneGroupAttributes",
10687            crate::soap::Unit {},
10688        )
10689        .await
10690    }
10691
10692    async fn get_zone_group_state(&self) -> Result<zone_group_topology::GetZoneGroupStateResponse> {
10693        self.action(
10694            &zone_group_topology::SERVICE_TYPE,
10695            "GetZoneGroupState",
10696            crate::soap::Unit {},
10697        )
10698        .await
10699    }
10700
10701    async fn register_mobile_device(
10702        &self,
10703        request: zone_group_topology::RegisterMobileDeviceRequest,
10704    ) -> Result<()> {
10705        self.action(
10706            &zone_group_topology::SERVICE_TYPE,
10707            "RegisterMobileDevice",
10708            request,
10709        )
10710        .await
10711    }
10712
10713    async fn report_alarm_started_running(&self) -> Result<()> {
10714        self.action(
10715            &zone_group_topology::SERVICE_TYPE,
10716            "ReportAlarmStartedRunning",
10717            crate::soap::Unit {},
10718        )
10719        .await
10720    }
10721
10722    async fn report_unresponsive_device(
10723        &self,
10724        request: zone_group_topology::ReportUnresponsiveDeviceRequest,
10725    ) -> Result<()> {
10726        self.action(
10727            &zone_group_topology::SERVICE_TYPE,
10728            "ReportUnresponsiveDevice",
10729            request,
10730        )
10731        .await
10732    }
10733
10734    async fn submit_diagnostics(
10735        &self,
10736        request: zone_group_topology::SubmitDiagnosticsRequest,
10737    ) -> Result<zone_group_topology::SubmitDiagnosticsResponse> {
10738        self.action(
10739            &zone_group_topology::SERVICE_TYPE,
10740            "SubmitDiagnostics",
10741            request,
10742        )
10743        .await
10744    }
10745}
10746
10747/// The prelude makes it convenient to use the methods of `SonosDevice`.
10748/// Intended usage is `use sonos::prelude::*;` and then you don't have
10749/// to worry about importing the individual service traits.
10750pub mod prelude {
10751    pub use super::{
10752        AVTransport, AlarmClock, AudioIn, ConnectionManager, ContentDirectory, DeviceProperties,
10753        GroupManagement, GroupRenderingControl, HTControl, MusicServices, QPlay, Queue,
10754        RenderingControl, SystemProperties, VirtualLineIn, ZoneGroupTopology,
10755    };
10756}