this repo has no description
1// https://gist.github.com/phaze-the-dumb/634daacb5141eae2f846e20987dba7a8
2use std::net::UdpSocket;
3
4use crossbeam_channel::Sender;
5use serde::Serialize;
6
7use crate::structs::parameter_types::ParameterType;
8
9#[derive(Debug, Clone, Serialize)]
10pub struct OSCMessage {
11 pub address: String,
12 pub values: Vec<ParameterType>,
13}
14
15impl PartialEq for OSCMessage {
16 // Technically this isn't exactly equal, but the only time i'm checking if OSCMessage's are equal
17 // Is when i'm checking for the "address" value
18
19 fn eq(&self, other: &Self) -> bool {
20 self.address == other.address
21 }
22
23 fn ne(&self, other: &Self) -> bool {
24 self.address != other.address
25 }
26}
27
28// TODO: Implement osc bundles
29pub fn start_server(sender: Sender<OSCMessage>, addr: &str) {
30 let socket = UdpSocket::bind(addr).unwrap();
31
32 loop {
33 let mut buf = [0; 1024];
34 let (amt, _src) = socket.recv_from(&mut buf).unwrap();
35
36 let buf = &mut buf[..amt];
37 if buf[0] != 0x2F {
38 panic!("Packet is not an OSC Message");
39 }
40
41 let mut addr: Vec<u8> = Vec::new();
42 let mut value_start = 0;
43
44 loop {
45 let byte = buf[value_start];
46 if byte == 0x00 {
47 break;
48 }
49
50 value_start += 1;
51 addr.push(byte);
52 }
53
54 loop {
55 let byte = buf[value_start];
56 value_start += 1;
57
58 if byte == 0x2C {
59 break;
60 }
61 }
62
63 let mut types: Vec<u8> = Vec::new();
64
65 loop {
66 let byte = buf[value_start];
67 if byte == 0x00 {
68 break;
69 }
70
71 types.push(byte);
72 value_start += 1;
73 }
74
75 value_start = ((value_start as f32 / 4.0).ceil() * 4.0) as usize;
76 let mut values = Vec::new();
77
78 for tp in types {
79 match tp {
80 0x69 => {
81 let val_buf = &buf[value_start..value_start + 4];
82
83 let bytes = <&[u8; 4]>::try_from(val_buf).unwrap().clone();
84 let int = i32::from_be_bytes(bytes);
85
86 values.push(ParameterType::Int(int));
87 value_start += 4;
88 }
89 0x66 => {
90 let val_buf = &buf[value_start..value_start + 4];
91
92 let bytes = <&[u8; 4]>::try_from(val_buf).unwrap().clone();
93 let float = f32::from_be_bytes(bytes);
94
95 values.push(ParameterType::Float(float));
96 value_start += 4;
97 }
98 0x54 => values.push(ParameterType::Boolean(true)),
99 0x46 => values.push(ParameterType::Boolean(false)),
100 _ => {}
101 }
102 }
103
104 let message = OSCMessage {
105 address: String::from_utf8(addr.clone()).unwrap(),
106 values: values,
107 };
108
109 sender.send(message).unwrap();
110 }
111}
112
113pub fn send_message(address: &str, values: Vec<ParameterType>, ip_addr: &str) {
114 let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
115 let mut buf: Vec<u8> = Vec::new();
116
117 buf.append(&mut address.as_bytes().to_vec());
118
119 let rounded_len = ((((buf.len() as f64) + 1.0) / 4.0).ceil() * 4.0) as usize;
120 let original_len = buf.len();
121
122 for _i in original_len..rounded_len {
123 buf.push(0);
124 }
125
126 buf.push(0x2C);
127
128 let mut value_count = 1;
129 for value in values.clone() {
130 match value {
131 ParameterType::Boolean(val) => buf.push(if val { 0x54 } else { 0x46 }),
132 ParameterType::Float(_) => buf.push(0x66),
133 ParameterType::Int(_) => buf.push(0x69),
134 ParameterType::String(_) => buf.push(0x73),
135 _ => {}
136 };
137
138 value_count += 1;
139 }
140
141 for _i in 0..4 - (value_count % 4) {
142 buf.push(0);
143 }
144
145 for value in values {
146 match value {
147 ParameterType::Float(val) => buf.append(&mut val.to_be_bytes().to_vec()),
148 ParameterType::Int(val) => buf.append(&mut val.to_be_bytes().to_vec()),
149 ParameterType::String(val) => {
150 let mut str_buf = val.as_bytes().to_vec();
151 let buf_len = str_buf.len().clone();
152
153 buf.append(&mut str_buf);
154
155 for _i in 0..4 - (buf_len % 4) {
156 buf.push(0);
157 }
158 }
159 _ => {}
160 }
161 }
162
163 socket.send_to(&buf, ip_addr).unwrap();
164}