1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
use std::{error::Error, net::UdpSocket};
use rosc::{OscMessage, OscPacket};
pub struct OscServer {
socket: UdpSocket,
buf: Vec<u8>,
}
impl OscServer {
pub fn new(addr: &str) -> std::io::Result<Self> {
let socket = UdpSocket::bind(addr)?;
socket.set_nonblocking(true)?;
log::info!("listening for OSC on {}", addr);
Ok(Self {
socket,
buf: vec![0u8; 0x10000],
})
}
/// Drains all pending OSC messages, calling `on_message` for each.
/// Returns `true` if any messages were dispatched.
pub fn poll(
&mut self,
mut on_message: impl FnMut(OscMessage) -> Result<(), Box<dyn Error>>,
) -> bool {
let mut received = false;
loop {
match self.socket.recv_from(&mut self.buf) {
Ok((size, _addr)) => {
let data = &self.buf[..size];
let res = rosc::decoder::decode_udp(data)
.map_err(Box::from)
.and_then(|(_, packet)| dispatch(packet, &mut on_message));
if let Err(e) = res {
log::error!("{}", e);
};
received = true;
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
Err(e) => {
log::error!("OSC recv error: {}", e);
break;
}
}
}
received
}
/// Blocks until at least one OSC message arrives, then drains all pending.
pub fn recv(
&mut self,
mut on_message: impl FnMut(OscMessage) -> Result<(), Box<dyn Error>>,
) -> bool {
self.socket.set_nonblocking(false).expect("set blocking");
match self.socket.recv_from(&mut self.buf) {
Ok((size, _addr)) => {
let data = &self.buf[..size];
let res = rosc::decoder::decode_udp(data)
.map_err(Box::from)
.and_then(|(_, packet)| dispatch(packet, &mut on_message));
if let Err(e) = res {
log::error!("{}", e);
};
}
Err(e) => {
log::error!("OSC recv error: {}", e);
}
}
self.socket.set_nonblocking(true).expect("set nonblocking");
self.poll(on_message);
true
}
}
fn dispatch<E>(
packet: OscPacket,
on_message: &mut impl FnMut(OscMessage) -> Result<(), E>,
) -> Result<(), E> {
match packet {
OscPacket::Message(msg) => on_message(msg)?,
OscPacket::Bundle(bundle) => {
for p in bundle.content {
dispatch(p, on_message)?;
}
}
}
Ok(())
}
|