This repository has no description
1extern crate env_logger;
2
3use crate::vst::probe::Datapoint;
4
5use super::Probe;
6use anyhow::Result;
7use once_cell::sync::Lazy;
8use std::sync::{Mutex, MutexGuard};
9use tungstenite;
10
11const BEACON_PORT: u16 = 8080;
12
13#[inline]
14pub fn beacon_url() -> String {
15 return format!("ws://localhost:{BEACON_PORT}");
16}
17
18pub fn connect_to_beacon() -> Result<
19 tungstenite::WebSocket<
20 tungstenite::stream::MaybeTlsStream<std::net::TcpStream>,
21 >,
22> {
23 println!("Connecting to beacon at {}", beacon_url());
24 let (socket, _response) = tungstenite::connect(beacon_url())?;
25 Ok(socket)
26}
27
28#[derive(Default)]
29pub struct Beacon {
30 pub probes: Vec<Probe>,
31}
32
33static BEACON: Lazy<Mutex<Beacon>> = Lazy::new(|| Mutex::new(Beacon::new()));
34
35pub fn get_beacon() -> MutexGuard<'static, Beacon> {
36 return BEACON.lock().unwrap();
37}
38
39impl Beacon {
40 pub fn new() -> Self {
41 return Self::default();
42 }
43
44 pub fn start() -> Result<()> {
45 ws::listen(format!("127.0.0.1:{BEACON_PORT}"), |out| {
46 println!("Opening beacon connection with a probe...");
47 move |msg| {
48 println!("Received message: {:?}", msg);
49 match msg {
50 ws::Message::Text(text) => match text.split3() {
51 ("?", "hi", probe_json) => {
52 match serde_json::from_str::<Probe>(probe_json) {
53 Ok(probe) => {
54 let mut beacon = get_beacon();
55 beacon.probes.push(probe);
56 out.send("{} probe added!")
57 }
58 Err(_) => out.send("? invalid JSON :/"),
59 }
60 }
61 (id_str, "hi", probe_json) => {
62 match serde_json::from_str::<Probe>(probe_json) {
63 Ok(probe) => {
64 let mut beacon = get_beacon();
65 let probe_index =
66 beacon.probes.iter().position(|p| {
67 p.id == id_str.parse::<u32>().unwrap()
68 });
69 if let None = probe_index {
70 return out.send(format!(
71 "{} not found :/",
72 probe.id
73 ));
74 }
75 beacon.probes[probe_index.unwrap()] = probe;
76 out.send("{} probe added!")
77 }
78 Err(_) => out.send("? invalid JSON :/"),
79 }
80 }
81 (id_str, "byebye", "") => {
82 let id = id_str.parse::<u32>().unwrap();
83 let mut beacon = get_beacon();
84 let probe_index = beacon
85 .probes
86 .iter()
87 .position(|probe| probe.id == id);
88 match probe_index {
89 Some(probe_index) => {
90 let removed_probe =
91 beacon.probes.remove(probe_index);
92 out.send(format!(
93 "{} probe removed!",
94 removed_probe.id
95 ))
96 }
97 None => out.send(format!("{id} not found :/")),
98 }
99 }
100 ("*", "wtf", "") => {
101 let beacon = get_beacon();
102 let body =
103 serde_json::to_string(&beacon.probes).unwrap();
104 out.send(body)
105 }
106 (id_str, "wtf", "") => {
107 let id = id_str.parse::<u32>().unwrap();
108 let beacon = get_beacon();
109 let probe =
110 beacon.probes.iter().find(|probe| probe.id == id);
111 match probe {
112 Some(probe) => {
113 out.send(format!(
114 "probe {} with {} datapoints stored",
115 probe.id,
116 probe.datapoints.len()
117 ))?;
118 out.send(
119 serde_json::to_string(probe).unwrap(),
120 )
121 }
122 None => out.send(format!("{id} not found :/")),
123 }
124 }
125 (id_str, "say", msg) => {
126 let id = id_str.parse::<u32>().unwrap();
127 let beacon = get_beacon();
128 let probe =
129 beacon.probes.iter().find(|probe| probe.id == id);
130 match probe {
131 Some(probe) => {
132 println!("probe {}: {}", probe.id, msg);
133 out.send("ok")
134 }
135 None => out.send(format!("{id} not found :/")),
136 }
137 }
138 (probe_id, timestamp, msg) => {
139 let id = probe_id.parse::<u32>().unwrap();
140 let mut beacon = get_beacon();
141 let probe = beacon
142 .probes
143 .iter_mut()
144 .find(|probe| probe.id == id);
145
146 if let None = probe {
147 return out.send(format!("{id} not found :/"));
148 }
149
150 let probe = probe.unwrap();
151 let timestamp: usize =
152 timestamp.parse().expect(&format!(
153 "{timestamp} to be a number (timestamp)"
154 ));
155
156 match msg.split2() {
157 ("%", data) => match data.split2() {
158 (paramname, paramvalue) => {
159 probe.store(Datapoint::Automation(
160 timestamp,
161 paramname.parse().expect(&format!(
162 "{paramname} to be a number"
163 )),
164 paramvalue.parse().expect(&format!(
165 "{paramvalue} to be a number"
166 )),
167 ))
168 }
169 },
170 ("#", data) => probe.store(Datapoint::Midi(
171 timestamp,
172 data.as_bytes().to_vec(),
173 )),
174 ("~", data) => probe.store(Datapoint::Audio(
175 timestamp,
176 data.split(' ')
177 .map(|f| f.parse().unwrap())
178 .collect(),
179 )),
180 _ => {
181 return out.send("invalid command :/");
182 }
183 }
184
185 out.send("gotchu!")
186 }
187 },
188 ws::Message::Binary(_) => todo!(),
189 }
190 }
191 })?;
192 Ok(())
193 }
194}
195
196trait FixedSplits {
197 fn split3(&self) -> (&str, &str, &str);
198 fn split2(&self) -> (&str, &str);
199}
200impl FixedSplits for str {
201 fn split3(&self) -> (&str, &str, &str) {
202 let mut parts = self.splitn(3, ' ');
203 let first = parts.next().unwrap_or_default();
204 let second = parts.next().unwrap_or_default();
205 let third = parts.next().unwrap_or_default();
206 return (first, second, third);
207 }
208
209 fn split2(&self) -> (&str, &str) {
210 let mut parts = self.splitn(2, ' ');
211 let first = parts.next().unwrap_or_default();
212 let second = parts.next().unwrap_or_default();
213 return (first, second);
214 }
215}