This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

1use super::{Probe, beacon::connect_to_beacon, probe::Datapoint}; 2use anyhow::Result; 3use nih_plug::params::FloatParam; 4use std::{fmt::Display, net::TcpStream}; 5use tungstenite::{WebSocket, stream::MaybeTlsStream}; 6 7pub struct RemoteProbe { 8 pub id: u32, 9 pub out: WebSocket<MaybeTlsStream<TcpStream>>, 10 pub pointsbuffer: Vec<Datapoint>, 11} 12 13impl RemoteProbe { 14 pub fn new(id: u32) -> Self { 15 Self { 16 id, 17 out: connect_to_beacon().unwrap(), 18 pointsbuffer: Vec::new(), 19 } 20 } 21 22 pub fn register(&mut self) -> Result<()> { 23 let probe = Probe { 24 id: self.id, 25 ..Default::default() 26 }; 27 28 self.out 29 .send( 30 format!( 31 "? hi {}", 32 serde_json::to_string(&probe) 33 .expect("Failed to serialize probe") 34 ) 35 .into(), 36 ) 37 .expect("Failed to send register probe message"); 38 39 Ok(()) 40 } 41 42 pub fn update(&mut self, probe: Probe) -> Result<()> { 43 self.out 44 .send( 45 format!( 46 "{} hi {}", 47 self.id, 48 serde_json::to_string(&probe) 49 .expect("Failed to serialize probe") 50 ) 51 .into(), 52 ) 53 .expect("Failed to send update probe message"); 54 Ok(()) 55 } 56 57 pub fn timestamp() -> usize { 58 std::time::SystemTime::now() 59 .duration_since(std::time::UNIX_EPOCH) 60 .unwrap() 61 .as_millis() as usize 62 } 63 64 /// Store a automation data point. 65 pub fn store_automation( 66 &mut self, 67 timestamp: usize, 68 param_id: usize, 69 param: &FloatParam, 70 ) -> Result<()> { 71 self.store(Datapoint::Automation(timestamp, param_id, param.value())) 72 } 73 74 /// Store a audio data point. 75 pub fn store_audio( 76 &mut self, 77 timestamp: usize, 78 samples: Vec<f32>, 79 ) -> Result<()> { 80 self.store(Datapoint::Audio(timestamp, samples)) 81 } 82 83 /// Store a midi data point. 84 pub fn store_midi(&mut self, timestamp: usize, data: &[u8]) -> Result<()> { 85 self.store(Datapoint::Midi(timestamp, data.to_vec())) 86 } 87 88 /// Store a data point. 89 pub fn say(&mut self, msg: impl Display) -> Result<()> { 90 self.out 91 .write(format!("{} say {}", self.id, msg).into()) 92 .expect("Failed to send say message"); 93 Ok(()) 94 } 95 96 pub fn store(&mut self, datapoint: Datapoint) -> Result<()> { 97 self.pointsbuffer.push(datapoint); 98 if self.pointsbuffer.len() >= 100 { 99 self.say("flushing buffer of datapoints")?; 100 for datapoint in self.pointsbuffer.drain(..) { 101 self.out 102 .write( 103 format!( 104 "{} {}", 105 self.id, 106 match &datapoint { 107 Datapoint::Automation(ts, param_id, value) => { 108 format!("{ts} % {} {}", param_id, value) 109 } 110 Datapoint::Midi(ts, data) => { 111 format!( 112 "{ts} # 0 {}", 113 data.iter() 114 .map(|b| b.to_string()) 115 .collect::<Vec<String>>() 116 .join(" ") 117 ) 118 } 119 Datapoint::Audio(ts, data) => { 120 format!( 121 "{ts} ~ {}", 122 data.iter() 123 .map(|f| f.to_string()) 124 .collect::<Vec<String>>() 125 .join(" ") 126 ) 127 } 128 } 129 ) 130 .into(), 131 ) 132 .expect("Failed to send store datapoint message"); 133 } 134 self.out.flush().expect("Failed to flush probe connection"); 135 } 136 137 Ok(()) 138 } 139} 140 141impl Drop for RemoteProbe { 142 fn drop(&mut self) { 143 self.out 144 .close(None) 145 .expect("Failed to close probe connection"); 146 } 147}