1#![cfg(feature = "discover")]
2use crate::error::Error;
3use std::any::Any;
4use std::sync::Arc;
5use std::time::Duration;
6use tokio::sync::mpsc::{self, Receiver};
7use zeroconf::prelude::*;
8use zeroconf::{MdnsBrowser, ServiceDiscovery, ServiceType};
9
10pub struct DiscoveredBluOSDevice {
11 pub name: String,
12 pub hostname: String,
13 pub port: u16,
14}
15
16pub struct Discovery {
17 cancel: Option<std::sync::mpsc::Sender<bool>>,
18}
19
20impl Discovery {
21 pub fn new() -> Discovery {
22 Discovery { cancel: None }
23 }
24 pub async fn discover(&mut self) -> Result<Receiver<DiscoveredBluOSDevice>, Error> {
29 if self.cancel.is_some() {
31 return Err(Error::AlreadyDiscovering);
32 }
33
34 let (tx, rx) = mpsc::channel(200);
35 let (ctx, crx): (
36 std::sync::mpsc::Sender<bool>,
37 std::sync::mpsc::Receiver<bool>,
38 ) = std::sync::mpsc::channel();
39 self.cancel = Some(ctx);
40
41 tokio::task::spawn_blocking(move || {
42 let mut browser = MdnsBrowser::new(ServiceType::new("musc", "tcp").unwrap());
43
44 browser.set_service_discovered_callback(Box::new(
45 move |result: zeroconf::Result<ServiceDiscovery>,
46 _context: Option<Arc<dyn Any>>| {
47 let res = result.unwrap();
48 let _ = tx.blocking_send(DiscoveredBluOSDevice {
49 name: res.name().clone(),
50 hostname: res.address().clone(),
51 port: *res.port(),
52 });
53 },
54 ));
55
56 let event_loop = browser.browse_services().unwrap();
57
58 loop {
59 event_loop.poll(Duration::from_millis(500)).unwrap();
60
61 match crx.try_recv() {
62 Ok(_) => return,
63 Err(e) => match e {
64 std::sync::mpsc::TryRecvError::Empty => {}
65 std::sync::mpsc::TryRecvError::Disconnected => return,
66 },
67 }
68 }
69 });
70
71 Ok(rx)
72 }
73 pub async fn discover_one() -> Result<DiscoveredBluOSDevice, Error> {
76 let mut d = Discovery::new();
77 let mut c = d.discover().await?;
78
79 let m = c.recv().await.ok_or(Error::NoBluOSError)?;
80
81 Ok(m)
82 }
83}
84
85impl Drop for Discovery {
86 fn drop(&mut self) {
87 match &self.cancel {
88 Some(c) => {
89 let _ = c.send(true);
90 }
91 None => {}
92 }
93 }
94}