1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::sync::Arc;
use crate::{
http_client::HttpClient,
media_container::devices::{DevicesMediaContainer, Feature},
url::{MYPLEX_DEVICES, MYPLEX_RESOURCES},
Error, Player, Result, Server,
};
use futures::{future::select_ok, FutureExt};
use http::StatusCode;
use isahc::AsyncReadResponseExt;
pub struct DeviceManager {
pub client: Arc<HttpClient>,
}
impl DeviceManager {
pub fn new(client: Arc<HttpClient>) -> Self {
Self { client }
}
pub async fn get_devices_internal<'a, 'b>(&'a self, url: &'b str) -> Result<Vec<Device<'a>>> {
let mut response = self
.client
.get(url)
.header("Accept", "application/xml")
.send()
.await?;
match response.status() {
StatusCode::OK => {
let response_text = response.text().await?;
let container: DevicesMediaContainer = quick_xml::de::from_str(&response_text)?;
Ok(container
.devices
.into_iter()
.map(|device| Device {
inner: device,
client: &self.client,
})
.collect())
}
_ => Err(crate::Error::from_response(response).await),
}
}
pub async fn get_devices(&self) -> Result<Vec<Device<'_>>> {
self.get_devices_internal(MYPLEX_DEVICES).await
}
pub async fn get_resources(&self) -> Result<Vec<Device<'_>>> {
self.get_devices_internal(MYPLEX_RESOURCES).await
}
}
#[derive(Debug, Clone)]
pub struct Device<'a> {
inner: crate::media_container::devices::Device,
client: &'a HttpClient,
}
impl Device<'_> {
pub async fn connect(&self) -> Result<DeviceConnection> {
if !self.inner.provides.contains(&Feature::Server)
&& !self.inner.provides.contains(&Feature::Player)
{
return Err(Error::DeviceConnectionNotSupported);
}
if let Some(connections) = &self.inner.connections {
if self.inner.provides.contains(&Feature::Server) {
let futures = connections
.iter()
.map(|connection| {
crate::Server::new(&connection.uri, self.client.to_owned()).boxed()
})
.collect::<Vec<_>>();
let (server, _) = select_ok(futures).await?;
Ok(DeviceConnection::Server(Box::new(server)))
} else {
let futures = connections
.iter()
.map(|connection| {
crate::Player::new(&connection.uri, self.client.to_owned()).boxed()
})
.collect::<Vec<_>>();
let (player, _) = select_ok(futures).await?;
Ok(DeviceConnection::Player(Box::new(player)))
}
} else {
Err(Error::DeviceConnectionsIsEmpty)
}
}
}
#[derive(Debug, Clone)]
pub enum DeviceConnection {
Server(Box<Server>),
Player(Box<Player>),
}