async_osc/osc.rs
1use async_std::net::{ToSocketAddrs, UdpSocket};
2use async_std::stream::Stream;
3use futures_lite::ready;
4use rosc::OscPacket;
5use std::io;
6use std::net::SocketAddr;
7use std::pin::Pin;
8use std::sync::Arc;
9use std::task::{Context, Poll};
10
11use crate::error::Error;
12use crate::prelude::IntoOscPacket;
13use crate::udp::UdpSocketStream;
14
15/// A UDP socket to send and receive OSC messages.
16#[derive(Debug)]
17pub struct OscSocket {
18 socket: UdpSocketStream,
19}
20
21impl OscSocket {
22 /// Creates a new OSC socket from a [`async_std::net::UdpSocket`].
23 pub fn new(socket: UdpSocket) -> Self {
24 let socket = UdpSocketStream::new(socket);
25 Self { socket }
26 }
27
28 /// Creates an OSC socket from the given address.
29 ///
30 /// Binding with a port number of 0 will request that the OS assigns a port to this socket.
31 /// The port allocated can be queried via [`local_addr`] method.
32 ///
33 /// [`local_addr`]: #method.local_addr
34 pub async fn bind<A: ToSocketAddrs>(addr: A) -> Result<Self, Error> {
35 let socket = UdpSocket::bind(addr).await?;
36 Ok(Self::new(socket))
37 }
38
39 /// Connects the UDP socket to a remote address.
40 ///
41 /// When connected, only messages from this address will be received and the [`send`] method
42 /// will use the specified address for sending.
43 ///
44 /// [`send`]: #method.send
45 ///
46 /// # Examples
47 ///
48 /// ```no_run
49 /// # fn main() -> async_osc::Result<()> { async_std::task::block_on(async {
50 /// #
51 /// use async_osc::{prelude::*, OscSocket, OscMessage};
52 ///
53 /// let socket = OscSocket::bind("127.0.0.1:0").await?;
54 /// socket.connect("127.0.0.1:8080").await?;
55 /// #
56 /// # Ok(()) }) }
57 /// ```
58 pub async fn connect<A: ToSocketAddrs>(&self, addrs: A) -> Result<(), Error> {
59 self.socket().connect(addrs).await?;
60 Ok(())
61 }
62
63 /// Sends an OSC packet on the socket to the given address.
64 ///
65 /// # Examples
66 ///
67 /// ```no_run
68 /// # fn main() -> async_osc::Result<()> { async_std::task::block_on(async {
69 /// #
70 /// use async_osc::{prelude::*, OscSocket, OscMessage};
71 ///
72 /// let socket = OscSocket::bind("127.0.0.1:0").await?;
73 /// let addr = "127.0.0.1:5010";
74 /// let message = OscMessage::new("/volume", (0.8,));
75 /// socket.send_to(message, &addr).await?;
76 /// #
77 /// # Ok(()) }) }
78 /// ```
79 pub async fn send_to<A: ToSocketAddrs, P: IntoOscPacket>(
80 &self,
81 packet: P,
82 addrs: A,
83 ) -> Result<(), Error> {
84 let buf = rosc::encoder::encode(&packet.into_osc_packet())?;
85 let n = self.socket().send_to(&buf[..], addrs).await?;
86 check_len(&buf[..], n)
87 }
88
89 /// Sends a packet on the socket to the remote address to which it is connected.
90 ///
91 /// The [`connect`] method will connect this socket to a remote address.
92 /// This method will fail if the socket is not connected.
93 ///
94 /// [`connect`]: #method.connect
95 ///
96 /// # Examples
97 ///
98 /// ```no_run
99 /// # fn main() -> async_osc::Result<()> { async_std::task::block_on(async {
100 /// #
101 /// use async_osc::{prelude::*, OscSocket, OscMessage};
102 ///
103 /// let socket = OscSocket::bind("127.0.0.1:34254").await?;
104 /// socket.connect("127.0.0.1:8080").await?;
105 /// socket.send(("/volume", (1.0f32,))).await?;
106 /// #
107 /// # Ok(()) }) }
108 /// ```
109 pub async fn send<P: IntoOscPacket>(&self, packet: P) -> Result<(), Error> {
110 let buf = rosc::encoder::encode(&packet.into_osc_packet())?;
111 let n = self.socket().send(&buf[..]).await?;
112 check_len(&buf[..], n)
113 }
114
115 /// Create a standalone sender for this socket.
116 ///
117 /// The sender can be moved to other threads or tasks.
118 pub fn sender(&self) -> OscSender {
119 OscSender::new(self.socket.clone_inner())
120 }
121
122 /// Get a reference to the underling [`UdpSocket`].
123 pub fn socket(&self) -> &UdpSocket {
124 self.socket.get_ref()
125 }
126
127 /// Returns the local address that this socket is bound to.
128 ///
129 /// This can be useful, for example, when binding to port 0 to figure out which port was
130 /// actually bound.
131 pub fn local_addr(&self) -> Result<SocketAddr, Error> {
132 let addr = self.socket().local_addr()?;
133 Ok(addr)
134 }
135}
136
137impl Stream for OscSocket {
138 type Item = Result<(OscPacket, SocketAddr), Error>;
139 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
140 let packet = ready!(Pin::new(&mut self.socket).poll_next(cx));
141 let message = match packet {
142 None => None,
143 Some(packet) => Some(match packet {
144 Err(err) => Err(err.into()),
145 Ok((buf, peer_addr)) => rosc::decoder::decode(&buf[..])
146 .map_err(|e| e.into())
147 .map(|p| (p, peer_addr)),
148 }),
149 };
150 Poll::Ready(message)
151 }
152}
153
154/// A sender to send messages over an OSC socket.
155///
156/// See [`OscSocket::sender`].
157#[derive(Clone, Debug)]
158pub struct OscSender {
159 socket: Arc<UdpSocket>,
160}
161
162impl OscSender {
163 fn new(socket: Arc<UdpSocket>) -> Self {
164 Self { socket }
165 }
166
167 /// Sends an OSC packet on the socket to the given address.
168 ///
169 /// See [`OscSocket::send_to`].
170 pub async fn send_to<A: ToSocketAddrs, P: IntoOscPacket>(
171 &self,
172 packet: P,
173 addrs: A,
174 ) -> Result<(), Error> {
175 let buf = rosc::encoder::encode(&packet.into_osc_packet())?;
176 let n = self.socket().send_to(&buf[..], addrs).await?;
177 check_len(&buf[..], n)
178 }
179
180 /// Sends an OSC packet on the connected socket.
181 ///
182 /// See [`OscSocket::send`].
183 pub async fn send<P: IntoOscPacket>(&self, packet: P) -> Result<(), Error> {
184 let buf = rosc::encoder::encode(&packet.into_osc_packet())?;
185 let n = self.socket().send(&buf[..]).await?;
186 check_len(&buf[..], n)
187 }
188
189 /// Get a reference to the underling [`UdpSocket`].
190 pub fn socket(&self) -> &UdpSocket {
191 &*self.socket
192 }
193}
194
195fn check_len(buf: &[u8], len: usize) -> Result<(), Error> {
196 if len != buf.len() {
197 Err(io::Error::new(io::ErrorKind::Interrupted, "UDP packet not fully sent").into())
198 } else {
199 Ok(())
200 }
201}