open-sound-module 0.1.0

A crate providing a client for the Rebel Tech Open Sound Module
//! The **client** module provides a UDP client for the Open Sound Module
//! that can send an individual **osm::Msg* as well as **Sequence**s.

use crate::OscMessage;
use crate::OscMessageSequencer;
use std::net::UdpSocket;

pub struct OscClient {
    sock: UdpSocket,
    addr: String,
}

/// OscClient is an Open Sound Module UDP client that can send messages
/// and sequences to a Rebel Tech Open Sound Module.
/// ```rust
/// use open_sound_module::OscClient;
/// use open_sound_module::OscMessage;
/// use open_sound_module::CvMessage;
/// use open_sound_module::CvAddress;
///
/// fn main() -> Result<(), failure::Error> {
///   let client = OscClient::new("127.0.0.1:8888".to_string())?;
///
///   let msg = CvMessage::new(CvAddress::B, -1.0);
///   client.send_osc_message(OscMessage::CvMessage(msg))?;
///
///   Ok(())
/// }
/// ```
impl OscClient {
    /// Create a new client from an IP address and port string
    pub fn new(addr: String) -> Result<OscClient, failure::Error> {
        let sock = UdpSocket::bind("0.0.0.0:0")?;
        Ok(OscClient {
            sock: sock,
            addr: addr,
        })
    }

    /// Send a OscMessage encoded into open sound control protocol over UDP
    pub fn send_osc_message(&self, msg: OscMessage) -> Result<usize, failure::Error> {
        let sz = self.sock.send_to(&msg.to_vec(), &self.addr)?;
        return Ok(sz);
    }

    pub fn send_sequence(&self, seq: &mut impl OscMessageSequencer) -> Result<(), failure::Error> {
        let mut done = false;
        while !done {
            let msg = seq.next();
            match msg {
                Some(v) => {
                    let _n = self.send_osc_message(v)?;
                }
                None => {
                    done = true;
                }
            }
            seq.delay();
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::CvAddress;
    use crate::CvMessage;
    use std::net::UdpSocket;
    use std::{thread, time};

    #[test]
    fn client_send_osc_message() -> Result<(), failure::Error> {
        let handle = thread::spawn(move || {
            let socket = UdpSocket::bind("127.0.0.1:8888").unwrap();
            let mut buf: [u8; 1024] = [0; 1024];

            let (n, _src) = socket.recv_from(&mut buf).unwrap();
            let msg = Vec::from(&buf[0..n]);
            msg
        });

        thread::sleep(time::Duration::from_secs(1));

        let msg = CvMessage::new(CvAddress::B, -1.0);
        println!("{}", msg.to_string());

        let client = OscClient::new("127.0.0.1:8888".to_string())?;
        client.send_osc_message(OscMessage::CvMessage(msg))?;

        println!("Waiting");
        let received = handle.join().unwrap();

        assert!(received.len() == 20);
        println!("{:?}", received);
        Ok(())
    }
}