1use std::collections::HashMap;
2use std::sync::Arc;
3use std::time::Duration;
4
5use async_channel::Sender;
6use smol::lock::Mutex;
7use smol_timeout::TimeoutExt;
8
9use crate::app::AppId;
10use crate::namespace::{
11 connection::*,
12 heartbeat::*,
13 receiver::{self, *},
14 NamespaceUrn,
15};
16use crate::{App, Response, Volume};
17
18use super::{Client, Error, Payload};
19
20#[derive(Debug, Clone)]
21pub struct Receiver {
22 client: Arc<Mutex<Option<Client>>>,
23 platform: App,
24
25 request_id: Arc<Mutex<u32>>,
27 requests: Arc<Mutex<HashMap<u32, Sender<Response>>>>,
28 receivers: Arc<Mutex<Vec<Sender<Response>>>>,
29}
30
31impl Receiver {
32 pub fn new() -> Self {
33 Self {
34 client: Arc::default(),
35 platform: App::receiver(),
36 request_id: Arc::default(),
37 requests: Arc::default(),
38 receivers: Arc::default(),
39 }
40 }
41
42 pub async fn connect(&self, addr: &str) -> Result<(), Error> {
43 let client = Client::connect(addr).await?;
44 self.client.lock().await.replace(client.clone());
45
46 self.send(&self.platform, Connection::Connect).await?;
48
49 self.send(&self.platform, Heartbeat::Ping).await?;
51 client.receive().await?;
52
53 let d = self.clone();
55 smol::spawn(async move {
56 loop {
57 if let Some(client) = d.client().await {
58 match client.receive().await {
59 Ok(response) => {
60 if let Err(err) = d.process_response(response).await {
61 warn!("Unable to process received message: {}", err)
62 }
63 }
64 Err(err) => {
65 error!("Unable to receive message: {}", err);
66 d.disconnect().await;
67 break;
68 }
69 }
70 } else {
71 debug!("No client available, stop receiving.");
72 break;
73 }
74 }
75 })
76 .detach();
77
78 Ok(())
79 }
80
81 pub async fn disconnect(&self) {
83 let _ = self.send(&self.platform, Connection::Close).await;
85
86 let mut client = self.client.lock().await;
87 *client = None;
88
89 *self.request_id.lock().await = 0;
91 }
92
93 pub async fn is_connected(&self) -> bool {
94 self.client().await.is_some()
95 }
96
97 pub async fn applications(&self) -> Result<Vec<App>, Error> {
99 Ok(self.status().await?.applications.unwrap_or_default())
100 }
101
102 pub async fn launch_app(&self, app_id: AppId) -> Result<App, Error> {
103 let response = self
104 .send_request(
105 &self.platform,
106 receiver::Receiver::launch_request(app_id.clone()),
107 )
108 .await?;
109
110 if let Payload::Receiver(payload) = response.payload {
111 if let receiver::Receiver::LaunchError(LaunchErrorResponse { reason }) = payload {
112 return Err(Error::LaunchError(reason));
113 }
114
115 if let receiver::Receiver::ReceiverStatus(ReceiverStatusResponse { status }) = payload
116 && let Some(apps) = status.applications {
117 for app in apps {
118 if app.app_id == app_id {
119 self.send(&app, Connection::Connect).await?;
121 return Ok(app);
122 }
123 }
124 }
125 }
126
127 Err(Error::NoResponse)
128 }
129
130 pub async fn stop_app(&self, app: &App) -> Result<(), Error> {
131 self.send_request(
132 &self.platform,
133 receiver::Receiver::stop_request(app.session_id.clone()),
134 )
135 .await?;
136 Ok(())
137 }
138
139 pub async fn volume(&self) -> Result<Volume, Error> {
140 Ok(self.status().await?.volume)
141 }
142
143 pub async fn set_volume(&self, level: f64, muted: bool) -> Result<(), Error> {
144 self.send_request(
145 &self.platform,
146 receiver::Receiver::set_volume_request(level, muted),
147 )
148 .await?;
149 Ok(())
150 }
151
152 pub async fn status(&self) -> Result<Status, Error> {
153 let response = self
154 .send_request(&self.platform, receiver::Receiver::GetStatus)
155 .await?;
156
157 if let Payload::Receiver(receiver::Receiver::ReceiverStatus(ReceiverStatusResponse {
158 status,
159 })) = response.payload
160 {
161 return Ok(status);
162 }
163
164 Err(Error::NoResponse)
165 }
166
167 pub async fn send<P: Into<Payload>>(&self, app: &App, payload: P) -> Result<(), Error> {
168 let payload: Payload = payload.into();
169 let namespace = payload.namespace();
170 if !app.namespaces.contains(&namespace) && namespace != NamespaceUrn::Connection {
171 debug!(
172 "Unsupported namespace {}, app supports: {:#?}",
173 namespace, app.namespaces
174 );
175 return Err(Error::UnsupportedNamespace);
176 }
177
178 let client = match self.client().await {
179 Some(client) => client,
180 None => {
181 return Err(Error::NoConnection);
182 }
183 };
184
185 client.send(app.transport_id.clone(), payload, None).await?;
186 Ok(())
187 }
188
189 pub async fn send_request<P: Into<Payload>>(
190 &self,
191 app: &App,
192 payload: P,
193 ) -> Result<Response, Error> {
194 let payload: Payload = payload.into();
195 let namespace = payload.namespace();
196 if !app.namespaces.contains(&namespace) && namespace != NamespaceUrn::Connection {
197 dbg!(&payload);
198 debug!(
199 "Unsupported namespace {}, app supports: {:#?}",
200 namespace, app.namespaces
201 );
202 return Err(Error::UnsupportedNamespace);
203 }
204
205 let client = match self.client().await {
206 Some(client) => client,
207 None => {
208 return Err(Error::NoConnection);
209 }
210 };
211
212 let (response_tx, response_rx) = async_channel::bounded(1);
213
214 let request_id = {
216 let mut id = self.request_id.lock().await;
217 *id += 1;
218 *id
219 };
220
221 let mut requests = self.requests.lock().await;
223 requests.insert(request_id, response_tx);
224 drop(requests);
225
226 client
227 .send(app.transport_id.clone(), payload, Some(request_id))
228 .await?;
229
230 let res = response_rx.recv().timeout(Duration::from_secs(10)).await;
232 match res {
233 Some(response) => Ok(response?),
234 None => {
235 let mut requests = self.requests.lock().await;
236 requests.remove(&request_id);
237 Err(Error::ResponseTimeout)
238 }
239 }
240 }
241
242 pub async fn receive(&self) -> Result<Response, Error> {
243 let (response_tx, response_rx) = async_channel::bounded(1);
244 let mut receivers = self.receivers.lock().await;
245 receivers.push(response_tx);
246 drop(receivers);
247
248 response_rx.recv().await.map_err(|_| Error::NoResponse)
249 }
250
251 async fn process_response(&self, response: Response) -> Result<(), Error> {
252 if let Some(request_id) = response.request_id
254 && request_id != 0 {
255 match self.requests.lock().await.remove(&request_id) {
256 Some(sender) => sender.send(response.clone()).await.map_err(Box::new)?,
257 None => debug!("Ignore payload with unknown requestId"),
258 }
259 }
260
261 if let Payload::Heartbeat(Heartbeat::Ping) = &response.payload {
262 self.send(&self.platform, Heartbeat::Pong).await?;
263 }
264
265 let mut receivers = self.receivers.lock().await;
266 for receiver in receivers.split_off(0) {
267 let _ = receiver.send(response.clone()).await;
268 }
269
270 Ok(())
271 }
272
273 async fn client(&self) -> Option<Client> {
274 self.client.lock().await.clone()
275 }
276}
277
278impl Default for Receiver {
279 fn default() -> Self {
280 Self::new()
281 }
282}