1use std::net::UdpSocket;
2use rosc::{OscPacket, OscMessage as RoscMessage};
3use crossbeam_channel::{Sender, Receiver};
4use crate::nodes::OscMessage;
5use crate::{EngineCommand, ParameterUpdate, StableId};
6
7pub struct OscHandler {
8 command_tx: Sender<EngineCommand>,
9}
10
11impl OscHandler {
12 pub fn new(command_tx: Sender<EngineCommand>) -> Self {
13 Self { command_tx }
14 }
15
16 pub fn spawn_input_thread(&self, addr: &str) {
17 let command_tx = self.command_tx.clone();
18 let addr = addr.to_string();
19 std::thread::spawn(move || {
20 let socket = match UdpSocket::bind(&addr) {
21 Ok(s) => s,
22 Err(e) => {
23 tracing::error!("Failed to bind OSC input socket to {}: {}", addr, e);
24 return;
25 }
26 };
27 let mut buf = [0u8; 4096];
28 loop {
29 match socket.recv_from(&mut buf) {
30 Ok((size, _)) => {
31 if let Ok((_, packet)) = rosc::decoder::decode_udp(&buf[..size]) {
32 if let OscPacket::Message(msg) = packet {
33 Self::handle_message(&command_tx, msg);
34 }
35 }
36 }
37 Err(e) => {
38 tracing::error!("OSC input recv error: {}", e);
39 break;
40 }
41 }
42 }
43 });
44 }
45
46 fn handle_message(command_tx: &Sender<EngineCommand>, msg: RoscMessage) {
47 let parts: Vec<&str> = msg.addr.split('/').filter(|s: &&str| !s.is_empty()).collect();
48 if parts.len() == 3 && parts[0] == "node" {
49 if let (Ok(node_id), Some(val)) = (parts[1].parse::<StableId>(), msg.args.first()) {
50 let float_val = match val {
51 &rosc::OscType::Float(f) => f,
52 &rosc::OscType::Double(d) => d as f32,
53 &rosc::OscType::Int(i) => i as f32,
54 _ => 0.0,
55 };
56 let _ = command_tx.send(EngineCommand::UpdateParameter(ParameterUpdate {
57 node_id,
58 param: parts[2].to_string(),
59 value: float_val,
60 provenance: vec!["osc".to_string()],
61 }));
62 }
63 }
64 }
65
66 pub fn spawn_output_thread(rx: Receiver<OscMessage>, target_addr: String) {
67 std::thread::spawn(move || {
68 let socket = match UdpSocket::bind("0.0.0.0:0") {
69 Ok(s) => s,
70 Err(e) => {
71 tracing::error!("Failed to bind OSC output socket: {}", e);
72 return;
73 }
74 };
75 while let Ok(msg) = rx.recv() {
76 let packet = OscPacket::Message(RoscMessage { addr: msg.addr, args: msg.args });
77 if let Ok(bytes) = rosc::encoder::encode(&packet) {
78 let b: Vec<u8> = bytes;
79 let _ = socket.send_to(&b, &target_addr);
80 }
81 }
82 });
83 }
84}