1use std::sync::atomic::{AtomicBool, Ordering};
13use std::sync::{Arc, OnceLock};
14use std::time::Duration;
15
16use mx_remote::{BayUid, Config, DeviceUid, EventHandler, Remote};
17
18static CLIENT: OnceLock<Arc<Remote>> = OnceLock::new();
24
25struct Printer;
26
27impl EventHandler for Printer {
28 fn on_device_update(&self, device: DeviceUid) {
29 let Some(remote) = CLIENT.get() else { return };
30 let Some(info) = remote.device(device) else {
31 return;
32 };
33 println!(
34 " {device} {:<16} {:<12} {:<16} protocol {:#04x}, {} bays{}",
35 info.model,
36 info.serial,
37 info.name,
38 info.supported_protocol,
39 info.bays.len(),
40 if info.online { "" } else { " (offline)" },
41 );
42 }
43
44 fn on_bay_update(&self, bay: BayUid) {
45 let Some(remote) = CLIENT.get() else { return };
46 let Some(info) = remote.bay(bay) else { return };
47 println!(
48 " bay {} {:<16} {}",
49 bay.port,
50 info.user_name,
51 match info.signal_detected {
52 Some(true) => "signal",
53 _ => "no signal",
54 },
55 );
56 }
57}
58
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}
92
93fn ctrl_c(f: impl FnOnce() + Send + 'static) {
98 static HANDLER: OnceLock<()> = OnceLock::new();
99 let _ = HANDLER.set(());
100 std::thread::spawn(move || {
101 let mut line = String::new();
102 let _ = std::io::stdin().read_line(&mut line);
106 f();
107 });
108}