diff options
| author | s-ol <s+removethis@s-ol.nu> | 2026-04-16 10:24:24 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2026-05-14 14:46:13 +0000 |
| commit | 6a67c23a5029aceea1498f892c3424946b152cdc (patch) | |
| tree | 5d1b2a7283818e8807caaa211d22641b467386ba /src/osc.rs | |
| parent | initial commit (diff) | |
| download | wgsl-view-6a67c23a5029aceea1498f892c3424946b152cdc.tar.gz wgsl-view-6a67c23a5029aceea1498f892c3424946b152cdc.zip | |
refactor
Diffstat (limited to 'src/osc.rs')
| -rw-r--r-- | src/osc.rs | 140 |
1 files changed, 26 insertions, 114 deletions
@@ -2,17 +2,16 @@ use std::net::UdpSocket; use rosc::{OscMessage, OscPacket, OscType}; -use crate::uniform::{UniformCache, UniformError, UniformRef}; +pub enum OscCommand { + Shader(String), + Uniform { path: String, args: Vec<OscType> }, +} pub struct OscServer { socket: UdpSocket, buf: Vec<u8>, } -pub enum OscCommand { - Shader(String), -} - impl OscServer { pub fn new(addr: &str) -> std::io::Result<Self> { let socket = UdpSocket::bind(addr)?; @@ -24,16 +23,13 @@ impl OscServer { }) } - pub fn poll(&mut self, cache: &mut UniformCache) -> Vec<OscCommand> { - let mut commands = Vec::new(); + pub fn poll(&mut self, mut on_command: impl FnMut(OscCommand)) { loop { match self.socket.recv_from(&mut self.buf) { Ok((size, _addr)) => { let data = &self.buf[..size]; match rosc::decoder::decode_udp(data) { - Ok((_, packet)) => { - self.handle_packet(packet, cache, &mut commands); - } + Ok((_, packet)) => dispatch(packet, &mut on_command), Err(e) => log::warn!("OSC decode error: {}", e), } } @@ -44,118 +40,34 @@ impl OscServer { } } } - commands - } - - fn handle_packet( - &self, - packet: OscPacket, - cache: &mut UniformCache, - commands: &mut Vec<OscCommand>, - ) { - match packet { - OscPacket::Message(msg) => self.handle_message(msg, cache, commands), - OscPacket::Bundle(bundle) => { - for p in bundle.content { - self.handle_packet(p, cache, commands); - } - } - } } +} - fn handle_message( - &self, - msg: OscMessage, - cache: &mut UniformCache, - commands: &mut Vec<OscCommand>, - ) { - let path = &msg.addr; - - if path == "/shader" { - match &msg.args[..] { - [OscType::String(code)] => commands.push(OscCommand::Shader(code.clone())), - _ => log::warn!("/shader: unexpected arguments"), - } - } else if let Some(rest) = path.strip_prefix("/uniform/") { - if let Err(e) = handle_uniform(rest, &msg.args, cache) { - log::warn!("error handling {}: {}", path, e); +fn dispatch(packet: OscPacket, on_command: &mut impl FnMut(OscCommand)) { + match packet { + OscPacket::Message(msg) => dispatch_message(msg, on_command), + OscPacket::Bundle(bundle) => { + for p in bundle.content { + dispatch(p, on_command); } - } else { - log::debug!("unhandled OSC message: {}", path); } } } -fn handle_uniform( - path: &str, - args: &[OscType], - cache: &mut UniformCache, -) -> Result<(), Box<dyn std::error::Error>> { - let mut parts = path.split('/'); - let name = parts.next().ok_or("missing uniform name")?; - - let mut uref = cache.get(name).ok_or("uniform not found")?; - - for component in parts { - let i = match component { - "x" | "r" | "s" => 0, - "y" | "g" | "t" => 1, - "z" | "b" | "p" => 2, - "w" | "a" | "q" => 3, - s => s.parse::<usize>()?, - }; - uref = uref.index(i)?; - } - - write_osc_values(uref, args)?; - Ok(()) -} - -/// Write OSC argument values into a UniformRef, converting OSC types -/// to match the uniform's expected scalar type. -fn write_osc_values(uref: UniformRef<'_>, args: &[OscType]) -> Result<(), UniformError> { - if args.is_empty() { - return Err(UniformError::SizeMismatch); - } +fn dispatch_message(msg: OscMessage, on_command: &mut impl FnMut(OscCommand)) { + let path = &msg.addr; - let scalar = uref.leaf_scalar()?; - match scalar.kind { - naga::ScalarKind::Float => { - let values: Result<Vec<f32>, _> = args - .iter() - .map(|a| match a { - OscType::Float(f) => Ok(*f), - OscType::Double(d) => Ok(*d as f32), - OscType::Int(i) => Ok(*i as f32), - _ => Err(UniformError::TypeMismatch), - }) - .collect(); - uref.set_f32(&values?) - } - naga::ScalarKind::Sint => { - let values: Result<Vec<i32>, _> = args - .iter() - .map(|a| match a { - OscType::Int(i) => Ok(*i), - OscType::Float(f) => Ok(*f as i32), - OscType::Double(d) => Ok(*d as i32), - _ => Err(UniformError::TypeMismatch), - }) - .collect(); - uref.set_i32(&values?) - } - naga::ScalarKind::Uint => { - let values: Result<Vec<u32>, _> = args - .iter() - .map(|a| match a { - OscType::Int(i) => Ok(*i as u32), - OscType::Float(f) => Ok(*f as u32), - OscType::Double(d) => Ok(*d as u32), - _ => Err(UniformError::TypeMismatch), - }) - .collect(); - uref.set_u32(&values?) + if path == "/shader" { + match &msg.args[..] { + [OscType::String(code)] => on_command(OscCommand::Shader(code.clone())), + _ => log::warn!("/shader: expected single string argument"), } - _ => Err(UniformError::TypeMismatch), + } else if let Some(rest) = path.strip_prefix("/uniform/") { + on_command(OscCommand::Uniform { + path: rest.to_string(), + args: msg.args, + }); + } else { + log::debug!("unhandled OSC message: {}", path); } } |
