+1
-1
Cargo.toml
+1
-1
Cargo.toml
+4
-4
README.md
+4
-4
README.md
···
42
42
43
43
#[tokio::main]
44
44
async fn main() -> Result<(), Box<dyn std::error::Error>> {
45
-
let devices = discover_pnp_locations();
45
+
let devices = discover_pnp_locations().await?;
46
46
tokio::pin!(devices);
47
47
48
48
while let Some(device) = devices.next().await {
···
107
107
108
108
#[tokio::main]
109
109
async fn main() -> Result<(), Box<dyn std::error::Error>> {
110
-
let devices = discover_pnp_locations();
110
+
let devices = discover_pnp_locations().await?;
111
111
tokio::pin!(devices);
112
112
113
113
let mut kodi_device: Option<Device> = None;
···
120
120
}
121
121
122
122
let kodi_device = kodi_device.unwrap();
123
-
let device_client = DeviceClient::new(&kodi_device.location).connect().await?;
123
+
let device_client = DeviceClient::new(&kodi_device.location)?.connect().await?;
124
124
let media_renderer = MediaRendererClient::new(device_client);
125
125
126
126
let options = LoadOptions {
···
164
164
- [UPnP AV ContentDirectory v3 Service](http://upnp.org/specs/av/UPnP-av-ContentDirectory-v3-Service.pdf)
165
165
166
166
### License
167
-
MIT
167
+
MIT
+13
-19
src/device_client.rs
+13
-19
src/device_client.rs
···
1
-
use std::{
2
-
collections::HashMap,
3
-
env,
4
-
net::TcpListener,
5
-
sync::{
6
-
Arc,
7
-
},
8
-
time::Duration,
9
-
};
1
+
use std::{collections::HashMap, env, net::TcpListener, sync::Arc, time::Duration};
10
2
11
3
use crate::{
12
4
parser::{
···
110
102
111
103
for (name, value) in params {
112
104
let mut param = XMLElement::new(name.as_str());
113
-
param.add_text(value)?;
114
-
action.add_child(param)?;
105
+
param.add_text(value).map_err(|e| anyhow!("{:?}", e))?;
106
+
action.add_child(param).map_err(|e| anyhow!("{:?}", e))?;
115
107
}
116
108
117
-
body.add_child(action)?;
118
-
envelope.add_child(body)?;
109
+
body.add_child(action).map_err(|e| anyhow!("{:?}", e))?;
110
+
envelope.add_child(body).map_err(|e| anyhow!("{:?}", e))?;
119
111
120
112
xml.set_root_element(envelope);
121
113
122
114
let mut writer: Vec<u8> = Vec::new();
123
-
xml.generate(&mut writer)?;
115
+
xml.generate(&mut writer).map_err(|e| anyhow!("{:?}", e))?;
124
116
let xml = String::from_utf8(writer)?;
125
117
126
118
let soap_action = format!("\"{}#{}\"", service.service_type, action_name);
···
136
128
.send()
137
129
.await
138
130
.map_err(|e| anyhow!(e.to_string()))?;
139
-
res
140
-
.body_string()
141
-
.await
142
-
.map_err(|e| anyhow!(e.to_string()))
131
+
res.body_string().await.map_err(|e| anyhow!(e.to_string()))
143
132
}
144
133
145
134
async fn get_service_description(&self, service_id: &str) -> Result<Service> {
···
148
137
.services
149
138
.iter()
150
139
.find(|s| s.service_id == service_id)
151
-
.ok_or_else(|| anyhow!("Service with requested service_id {} does not exist", service_id))?;
140
+
.ok_or_else(|| {
141
+
anyhow!(
142
+
"Service with requested service_id {} does not exist",
143
+
service_id
144
+
)
145
+
})?;
152
146
return Ok(service.clone());
153
147
}
154
148
Err(anyhow!("Device not connected"))
+20
-8
src/parser.rs
+20
-8
src/parser.rs
···
93
93
Some(element) => {
94
94
return Ok(element.text().to_string());
95
95
}
96
-
None => {
97
-
Ok("".to_string())
98
-
}
96
+
None => Ok("".to_string()),
99
97
}
100
98
}
101
99
None => Ok("".to_string()),
···
373
371
let parser = EventReader::from_str(xml_root);
374
372
let mut current_play_mode: Option<String> = None;
375
373
for e in parser.into_iter().flatten() {
376
-
if let XmlEvent::StartElement { name, attributes, .. } = e {
374
+
if let XmlEvent::StartElement {
375
+
name, attributes, ..
376
+
} = e
377
+
{
377
378
if name.local_name == "CurrentPlayMode" {
378
379
for attr in attributes {
379
380
if attr.name.local_name == "val" {
···
390
391
let parser = EventReader::from_str(xml_root);
391
392
let mut transport_state: Option<String> = None;
392
393
for e in parser.into_iter().flatten() {
393
-
if let XmlEvent::StartElement { name, attributes, .. } = e {
394
+
if let XmlEvent::StartElement {
395
+
name, attributes, ..
396
+
} = e
397
+
{
394
398
if name.local_name == "TransportState" {
395
399
for attr in attributes {
396
400
if attr.name.local_name == "val" {
···
407
411
let parser = EventReader::from_str(xml_root);
408
412
let mut av_transport_uri_metadata: Option<String> = None;
409
413
for e in parser.into_iter().flatten() {
410
-
if let XmlEvent::StartElement { name, attributes, .. } = e {
414
+
if let XmlEvent::StartElement {
415
+
name, attributes, ..
416
+
} = e
417
+
{
411
418
if name.local_name == "AVTransportURIMetaData" {
412
419
for attr in attributes {
413
420
if attr.name.local_name == "val" {
···
424
431
let parser = EventReader::from_str(xml_root);
425
432
let mut current_track_metadata: Option<String> = None;
426
433
for e in parser.into_iter().flatten() {
427
-
if let XmlEvent::StartElement { name, attributes, .. } = e {
434
+
if let XmlEvent::StartElement {
435
+
name, attributes, ..
436
+
} = e
437
+
{
428
438
if name.local_name == "CurrentTrackMetaData" {
429
439
for attr in attributes {
430
440
if attr.name.local_name == "val" {
···
778
788
</device>
779
789
</root>"#;
780
790
781
-
let result = parse_services("http://xxxxxx:1337/", XML_ROOT).await;
791
+
let result = parse_services("http://xxxxxx:1337/", XML_ROOT)
792
+
.await
793
+
.unwrap();
782
794
assert_eq!(result.len(), 0);
783
795
}
784
796
}