summaryrefslogtreecommitdiffstats
path: root/src/osc.rs
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2026-04-16 10:24:24 +0000
committers-ol <s+removethis@s-ol.nu>2026-05-14 14:46:13 +0000
commit6a67c23a5029aceea1498f892c3424946b152cdc (patch)
tree5d1b2a7283818e8807caaa211d22641b467386ba /src/osc.rs
parentinitial commit (diff)
downloadwgsl-view-6a67c23a5029aceea1498f892c3424946b152cdc.tar.gz
wgsl-view-6a67c23a5029aceea1498f892c3424946b152cdc.zip
refactor
Diffstat (limited to 'src/osc.rs')
-rw-r--r--src/osc.rs140
1 files changed, 26 insertions, 114 deletions
diff --git a/src/osc.rs b/src/osc.rs
index 73f0f35..6759704 100644
--- a/src/osc.rs
+++ b/src/osc.rs
@@ -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);
}
}