monome/
lib.rs

1#![deny(missing_docs)]
2
3//! Use monome devices (Grid or Arc) in rust.
4
5use std::fmt;
6use std::io;
7use std::net::{IpAddr, Ipv4Addr, SocketAddr};
8use std::sync::Arc;
9use std::thread;
10use std::time::{Duration, Instant};
11
12use futures::future::Either;
13use tokio::net::UdpSocket;
14use tokio::prelude::*;
15use tokio::timer::Delay;
16
17use futures::sync::mpsc::{UnboundedReceiver, UnboundedSender};
18
19use rosc::decoder::decode;
20use rosc::encoder::encode;
21use rosc::{OscMessage, OscPacket, OscType};
22
23use crossbeam::queue::ArrayQueue;
24
25use futures::*;
26use log::*;
27
28/// The default port at which serialosc is running.
29pub const SERIALOSC_PORT: u16 = 12002;
30
31/// Port from which this library will start searching for free port when needed.
32const START_PORT: u16 = 10_000;
33
34/// After this number of milliseconds without receiving a device info message from seriaolc, this
35/// library considers all the devices to have been received.
36const DEVICE_ENUMERATION_TIMEOUT_MS: u64 = 500;
37
38/// From a x and y position, and a stride, returns the offset at which the element is in an array.
39fn toidx(x: i32, y: i32, width: i32) -> usize {
40    (y * width + x) as usize
41}
42
43/// Returns an osc packet from a address and arguments
44fn build_osc_message(addr: &str, args: Vec<OscType>) -> OscPacket {
45    let message = OscMessage {
46        addr: addr.to_owned(),
47        args,
48    };
49    OscPacket::Message(message)
50}
51
52fn new_bound_socket() -> UdpSocket {
53    let mut port = START_PORT;
54    loop {
55        let server_addr = format!("127.0.0.1:{}", port).parse().unwrap();
56        let bind_result = UdpSocket::bind(&server_addr);
57        match bind_result {
58            Ok(socket) => break socket,
59            Err(e) => {
60                warn!("bind error: {}", e.to_string());
61                if port == 0 {
62                    panic!("Could not bind socket: port exhausted");
63                }
64            }
65        }
66        port += 1;
67    }
68}
69
70/// An enum filled when a device has been added or removed, along with its name.
71#[derive(Debug)]
72pub enum DeviceChangeEvent {
73    /// A device has been added on the host and recognized by serialosc, and is now available for use.
74    Added(String),
75    /// A device has been removed on the host and is now unavailable for use.
76    Removed(String),
77}
78
79#[derive(Debug)]
80struct MonomeInfo {
81    port: Option<i32>,
82    host: Option<String>,
83    prefix: Option<String>,
84    id: Option<String>,
85    size: Option<(i32, i32)>,
86    rotation: Option<i32>,
87}
88
89impl MonomeInfo {
90    fn new() -> MonomeInfo {
91        MonomeInfo {
92            port: None,
93            host: None,
94            prefix: None,
95            id: None,
96            size: None,
97            rotation: None,
98        }
99    }
100    fn complete(&self) -> bool {
101        self.port.is_some()
102            && self.host.is_some()
103            && self.prefix.is_some()
104            && self.id.is_some()
105            && self.size.is_some()
106            && self.rotation.is_some()
107    }
108    fn fill(&mut self, packet: OscPacket) {
109        match packet {
110            OscPacket::Message(message) => {
111                if message.addr.starts_with("/sys") {
112                    let args = message.args;
113                    if message.addr.starts_with("/sys/port") {
114                        if let OscType::Int(port) = args[0] {
115                            self.port = Some(port);
116                        }
117                    } else if message.addr.starts_with("/sys/host") {
118                        if let OscType::String(ref host) = args[0] {
119                            self.host = Some(host.to_string());
120                        }
121                    } else if message.addr.starts_with("/sys/id") {
122                        if let OscType::String(ref id) = args[0] {
123                            self.id = Some(id.to_string());
124                        }
125                    } else if message.addr.starts_with("/sys/prefix") {
126                        if let OscType::String(ref prefix) = args[0] {
127                            self.prefix = Some(prefix.to_string());
128                        }
129                    } else if message.addr.starts_with("/sys/rotation") {
130                        if let OscType::Int(rotation) = args[0] {
131                            self.rotation = Some(rotation);
132                        }
133                    } else if message.addr.starts_with("/sys/size") {
134                        if let OscType::Int(x) = args[0] {
135                            if let OscType::Int(y) = args[1] {
136                                self.size = Some((x, y));
137                            }
138                        }
139                    }
140                }
141            }
142            OscPacket::Bundle(_bundle) => {
143                error!("Bundle during setup!?");
144            }
145        }
146    }
147}
148
149/// `Transport` implements the network input and output to and from serialosc.
150struct Transport {
151    /// The address at which serialoscd is reachable.
152    addr: SocketAddr,
153    /// This is the socket with with we send and receive to and from the device.
154    socket: UdpSocket,
155    /// This is the channel we use to forward the received OSC messages to the client object.
156    tx: Arc<ArrayQueue<Vec<u8>>>,
157    /// This is where Transport receives the OSC messages to send.
158    rx: UnboundedReceiver<Vec<u8>>,
159}
160
161impl Transport {
162    pub fn new(
163        device_addr: IpAddr,
164        device_port: u16,
165        socket: UdpSocket,
166        tx: Arc<ArrayQueue<Vec<u8>>>,
167        rx: UnboundedReceiver<Vec<u8>>,
168    ) -> Transport {
169        let addr = SocketAddr::new(device_addr, device_port);
170        Transport {
171            addr,
172            socket,
173            tx,
174            rx,
175        }
176    }
177}
178
179impl Future for Transport {
180    type Item = ();
181    type Error = io::Error;
182
183    fn poll(&mut self) -> Poll<(), io::Error> {
184        loop {
185            match self.rx.poll() {
186                Ok(fut) => {
187                    match fut {
188                        Async::Ready(b) => {
189                            // This happens when shutting down usually
190                            if b.is_some() {
191                                let _amt =
192                                    try_ready!(self.socket.poll_send_to(&b.unwrap(), &self.addr));
193                            } else {
194                                break;
195                            }
196                        }
197                        Async::NotReady => {
198                            break;
199                        }
200                    }
201                }
202                Err(e) => {
203                    error!("Error on future::mpsc {:?}", e);
204                }
205            }
206        }
207
208        loop {
209            let mut buf = vec![0; 1024];
210            match self.socket.poll_recv(&mut buf) {
211                Ok(fut) => match fut {
212                    Async::Ready(_ready) => match self.tx.push(buf) {
213                        Ok(()) => {
214                            continue;
215                        }
216                        Err(e) => {
217                            error!("receive from monome, {:?}", e);
218                        }
219                    },
220                    Async::NotReady => {
221                        return Ok(Async::NotReady);
222                    }
223                },
224                Err(e) => {
225                    return Err(e);
226                }
227            }
228        }
229    }
230}
231
232/// The client object for a Monome grid device
233pub struct Monome {
234    /// The name of this device
235    name: String,
236    /// The type of this device
237    device_type: MonomeDeviceType,
238    /// The port at which this device is running at
239    port: u16,
240    /// The host for this device (usually localhost)
241    host: String,
242    /// The ID of this device
243    id: String,
244    /// The prefix set for this device
245    prefix: String,
246    /// The current rotation for this device. This can be 0, 90, 180 or 270.
247    rotation: i32,
248    /// THe x and y size for this device.
249    size: (i32, i32),
250    /// A channel that allows receiving serialized OSC messages from a device.
251    q: Arc<ArrayQueue<Vec<u8>>>,
252    /// A channel that allows sending serialized OSC messages to a device.
253    tx: UnboundedSender<Vec<u8>>,
254}
255
256/// Whether a key press is going up or down
257#[derive(Debug)]
258pub enum KeyDirection {
259    /// The key has been released.
260    Up,
261    /// The key has been pressed.
262    Down,
263}
264
265/// An event received from a monome device. This can be either a key press or release, a tilt
266/// event, an encoder rotation event, or an encoder press or release.
267pub enum MonomeEvent {
268    /// A key press or release
269    GridKey {
270        /// The horizontal offset at which the key has been pressed.
271        x: i32,
272        /// The vertical offset at which the key has been pressed.
273        y: i32,
274        /// Whether the key has been pressed (`Down`), or released (`Up`).
275        direction: KeyDirection,
276    },
277    /// A update about the tilt of this device.
278    Tilt {
279        /// Which sensor sent this tilt update.
280        n: i32,
281        /// The pitch of this device.
282        x: i32,
283        /// The roll of this device.
284        y: i32,
285        /// The yaw of this device.
286        z: i32,
287    },
288    /// An encoder delta information
289    EncoderDelta {
290        /// Which encoder is sending the event.
291        n: usize,
292        /// The delta of this movement on this encoder.
293        delta: i32,
294    },
295    /// A key press on an encoder (only available on some older devices).
296    EncoderKey {
297        /// Which encoder is sending the event.
298        n: usize,
299        /// Whether the encoder key has been pressed (`Down`), or released (`Up`).
300        direction: KeyDirection,
301    },
302}
303
304/// Converts an to a Monome method argument to a OSC address fragment and suitable OscType,
305/// performing an eventual conversion.
306pub trait IntoAddrAndArgs<'a, B> {
307    /// Converts an to a Monome method argument to a OSC address fragment and suitable OscType,
308    /// performing an eventual conversion.
309    fn as_addr_frag_and_args(&self) -> (String, B);
310}
311
312/// Used to make a call with an intensity value, adds the `"level/"` portion in the address.
313impl<'a> IntoAddrAndArgs<'a, OscType> for i32 {
314    fn as_addr_frag_and_args(&self) -> (String, OscType) {
315        ("level/".to_string(), OscType::Int(*self))
316    }
317}
318
319/// Used to make an on/off call, converts to 0 or 1.
320impl<'a> IntoAddrAndArgs<'a, OscType> for bool {
321    fn as_addr_frag_and_args(&self) -> (String, OscType) {
322        ("".to_string(), OscType::Int(if *self { 1 } else { 0 }))
323    }
324}
325
326impl<'a> IntoAddrAndArgs<'a, Vec<OscType>> for &'a [u8; 64] {
327    fn as_addr_frag_and_args(&self) -> (String, Vec<OscType>) {
328        // TODO: error handling both valid: either 64 or more intensity values, or 8 masks
329        let mut osctype_vec = Vec::with_capacity(64);
330        for item in self.iter().map(|i| OscType::Int(i32::from(*i))) {
331            osctype_vec.push(item);
332        }
333        ("level/".to_string(), osctype_vec)
334    }
335}
336
337impl<'a> IntoAddrAndArgs<'a, Vec<OscType>> for u8 {
338    fn as_addr_frag_and_args(&self) -> (String, Vec<OscType>) {
339        // TODO: error handling both valid: either 64 or more intensity values, or 8 masks
340        let mut osctype_vec = Vec::with_capacity(1);
341        osctype_vec.push(OscType::Int(i32::from(*self)));
342        ("".to_string(), osctype_vec)
343    }
344}
345
346impl<'a> IntoAddrAndArgs<'a, Vec<OscType>> for &'a [u8; 8] {
347    fn as_addr_frag_and_args(&self) -> (String, Vec<OscType>) {
348        // TODO: error handling both valid: either 64 or more intensity values, or 8 masks
349        let mut osctype_vec = Vec::with_capacity(8);
350        for item in self.iter().map(|i| OscType::Int(i32::from(*i))) {
351            osctype_vec.push(item);
352        }
353        ("".to_string(), osctype_vec)
354    }
355}
356
357/// Used to convert vectors of bools for on/off calls, packs into a 8-bit integer mask.
358impl<'a> IntoAddrAndArgs<'a, Vec<OscType>> for &'a [bool; 64] {
359    fn as_addr_frag_and_args(&self) -> (String, Vec<OscType>) {
360        // TODO: error handling
361        assert!(self.len() >= 64);
362        let mut masks = [0 as u8; 8];
363        for i in 0..8 {
364            // for each row
365            let mut mask: u8 = 0;
366            for j in (0..8).rev() {
367                // create mask
368                let idx = toidx(j, i, 8);
369                mask = mask.rotate_left(1) | if self[idx] { 1 } else { 0 };
370            }
371            masks[i as usize] = mask;
372        }
373        let mut osctype_vec = Vec::with_capacity(8);
374        for item in masks.iter().map(|i| OscType::Int(i32::from(*i))) {
375            osctype_vec.push(item);
376        }
377        ("".to_string(), osctype_vec)
378    }
379}
380
381/// A type of device, either Grid (of various size), Arc (with 2 or 4 encoders), or unknown.
382#[derive(PartialEq, Clone)]
383pub enum MonomeDeviceType {
384    /// The type for a monome grid.
385    Grid,
386    /// The type for a monome arc.
387    Arc,
388    /// Unknown device, please file an issue.
389    Unknown,
390}
391
392impl From<&str> for MonomeDeviceType {
393    fn from(string: &str) -> MonomeDeviceType {
394        if string.contains("arc") {
395            MonomeDeviceType::Arc
396        } else {
397            MonomeDeviceType::Grid
398        }
399    }
400}
401
402impl fmt::Display for MonomeDeviceType {
403    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404        write!(
405            f,
406            "{}",
407            if *self == MonomeDeviceType::Grid {
408                "grid"
409            } else {
410                "arc"
411            }
412        )
413    }
414}
415
416impl fmt::Debug for MonomeDeviceType {
417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418        write!(f, "{}", self)
419    }
420}
421
422#[derive(Debug)]
423/// A struct with basic informations about a Monome device, available without having set it up
424pub struct MonomeDevice {
425    /// Name of the device with serial number
426    name: String,
427    /// Device type
428    device_type: MonomeDeviceType,
429    /// Host of the serialosc this device is on.
430    addr: IpAddr,
431    /// Port at which this device is available
432    port: u16,
433}
434
435impl fmt::Display for MonomeDevice {
436    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
437        write!(f, "{}: {} ({})", self.name, self.device_type, self.port)
438    }
439}
440
441impl MonomeDevice {
442    fn new(name: &str, device_type: &str, addr: IpAddr, port: u16) -> MonomeDevice {
443        MonomeDevice {
444            name: name.to_string(),
445            device_type: device_type.into(),
446            addr,
447            port,
448        }
449    }
450    /// Return the device type.
451    pub fn device_type(&self) -> MonomeDeviceType {
452        self.device_type.clone()
453    }
454    /// Return the device name.
455    pub fn name(&self) -> String {
456        self.name.clone()
457    }
458    /// The host on which this device is attached.
459    pub fn host(&self) -> IpAddr {
460        self.addr
461    }
462    /// Return the port on which this device is.
463    pub fn port(&self) -> u16 {
464        self.port
465    }
466}
467
468impl Monome {
469    /// Register for device added/removed notifications, on a non-standard serialosc port
470    ///
471    /// # Arguments
472    ///
473    /// * `serialosc_port`: the port on which serialosc is running
474    /// - `callback`: a function that is called whenever a device is added or removed.
475    ///
476    /// # Example
477    ///
478    /// Print a message, on a machine where serialosc runs on the machine at 192.168.1.12, on port
479    /// 1234.
480    ///
481    /// ```no_run
482    /// # use monome::Monome;
483    /// # use monome::DeviceChangeEvent;
484    /// Monome::register_device_change_callback_with_host_and_port("192.168.1.12".parse().unwrap(), 1234, |event| {
485    ///     match event {
486    ///         DeviceChangeEvent::Added(id) => {
487    ///             println!("Device {} added", id);
488    ///         }
489    ///         DeviceChangeEvent::Removed(id) => {
490    ///             println!("Device {} removed", id);
491    ///         }
492    ///     }
493    /// });
494    /// ```
495    pub fn register_device_change_callback_with_host_and_port(
496        serialosc_addr: IpAddr,
497        serialosc_port: u16,
498        callback: fn(DeviceChangeEvent),
499    ) {
500        let mut socket = new_bound_socket();
501
502        thread::spawn(move || {
503            let server_port = socket.local_addr().unwrap().port();
504            let addr = SocketAddr::new(serialosc_addr, serialosc_port);
505            let packet = build_osc_message(
506                "/serialosc/notify",
507                vec![
508                    OscType::String("127.0.0.1".to_string()),
509                    OscType::Int(i32::from(server_port)),
510                ],
511            );
512            let mut bytes: Vec<u8>;
513            // True if we've received a add or remove message from serialosc recently, and we need
514            // to tell it to notify this program in the future.
515            // This is necessary, because other messages can be received on this socket, notably the
516            // undocumented /sys/connect and /sys/disconnect messages (without any arguments).
517            let mut need_notify_msg = true;
518            loop {
519                bytes = encode(&packet).unwrap();
520                if need_notify_msg {
521                    socket = socket
522                        .send_dgram(bytes, &addr)
523                        .wait()
524                        .map(|(s, _)| s)
525                        .unwrap();
526                    need_notify_msg = false;
527                }
528
529                socket = socket.recv_dgram(vec![0u8; 1024]).and_then(|(socket, data, _, _)| {
530                    match decode(&data).unwrap() {
531                        OscPacket::Message(message) => {
532                            if message.addr.starts_with("/serialosc/add") {
533                                need_notify_msg = true;
534                                if let OscType::String(ref id) = message.args[0] {
535                                    callback(DeviceChangeEvent::Added(id.to_string()));
536                                }
537                            } else if message.addr.starts_with("/serialosc/remove") {
538                                if let OscType::String(ref id) = message.args[0] {
539                                    need_notify_msg = true;
540                                    callback(DeviceChangeEvent::Removed(id.to_string()));
541                                }
542                            } else {
543                                debug!("⇦ Unexpected message receive on device change event socket {:?}", &message);
544                            }
545                        }
546                        _ => {
547                            debug!("⇦ Could not decode {:?}", data);
548                        }
549                    }
550                    Ok(socket)
551                })
552                .wait()
553                    .map(|socket| socket)
554                    .unwrap();
555            }
556        });
557    }
558    /// Register for device added/removed notifications, on the default serialosc port, when it runs
559    /// on localhost.
560    ///
561    /// # Arguments
562    ///
563    /// - `callback`: a function that is called whenever a device is added or removed.
564    ///
565    /// # Example
566    ///
567    /// ```no_run
568    /// # use monome::Monome;
569    /// # use monome::DeviceChangeEvent;
570    /// Monome::register_device_change_callback(|event| {
571    ///     match event {
572    ///         DeviceChangeEvent::Added(id) => {
573    ///             println!("Device {} added", id);
574    ///         }
575    ///         DeviceChangeEvent::Removed(id) => {
576    ///             println!("Device {} removed", id);
577    ///         }
578    ///     }
579    /// });
580    /// ```
581    pub fn register_device_change_callback(callback: fn(DeviceChangeEvent)) {
582        Monome::register_device_change_callback_with_host_and_port(
583            std::net::IpAddr::V4(<Ipv4Addr>::LOCALHOST),
584            SERIALOSC_PORT,
585            callback,
586        )
587    }
588    /// Register for device added/removed notifications, on the default serialosc port, passing in
589    /// the address at which serialoscd is reachable.
590    ///
591    /// # Arguments
592    ///
593    /// - `addr`: the address on which serialoscd is reachable.
594    /// - `callback`: a function that is called whenever a device is added or removed.
595    ///
596    /// # Example
597    ///
598    /// ```no_run
599    /// # use monome::Monome;
600    /// # use monome::DeviceChangeEvent;
601    /// Monome::register_device_change_callback_with_host("192.168.1.12".parse().unwrap(), |event| {
602    ///     match event {
603    ///         DeviceChangeEvent::Added(id) => {
604    ///             println!("Device {} added", id);
605    ///         }
606    ///         DeviceChangeEvent::Removed(id) => {
607    ///             println!("Device {} removed", id);
608    ///         }
609    ///     }
610    /// });
611    /// ```
612    pub fn register_device_change_callback_with_host(
613        addr: IpAddr,
614        callback: fn(DeviceChangeEvent),
615    ) {
616        Monome::register_device_change_callback_with_host_and_port(addr, SERIALOSC_PORT, callback)
617    }
618    /// Register for device added/removed notifications, on the specific serialosc port, when
619    /// serialoscd is running on localhost.
620    ///
621    /// # Arguments
622    ///
623    /// - `port`: the port at which serialoscd is.
624    /// - `callback`: a function that is called whenever a device is added or removed.
625    ///
626    /// # Example
627    ///
628    /// ```no_run
629    /// # use monome::Monome;
630    /// # use monome::DeviceChangeEvent;
631    /// Monome::register_device_change_callback_with_port(12012, |event| {
632    ///     match event {
633    ///         DeviceChangeEvent::Added(id) => {
634    ///             println!("Device {} added", id);
635    ///         }
636    ///         DeviceChangeEvent::Removed(id) => {
637    ///             println!("Device {} removed", id);
638    ///         }
639    ///     }
640    /// });
641    /// ```
642    pub fn register_device_change_callback_with_port(port: u16, callback: fn(DeviceChangeEvent)) {
643        Monome::register_device_change_callback_with_host_and_port(
644            std::net::IpAddr::V4(<Ipv4Addr>::LOCALHOST),
645            port,
646            callback,
647        )
648    }
649    fn setup<S>(
650        prefix: S,
651        device: &MonomeDevice,
652    ) -> Result<(MonomeInfo, UdpSocket, String, MonomeDeviceType, u16), String>
653    where
654        S: Into<String>,
655    {
656        let (name, device_type, port) = (
657            device.name.to_string(),
658            device.device_type.clone(),
659            device.port,
660        );
661
662        let addr = SocketAddr::new(device.host(), device.port());
663
664        let socket = new_bound_socket();
665        let server_port = socket.local_addr().unwrap().port();
666        let packet = build_osc_message("/sys/port", vec![OscType::Int(i32::from(server_port))]);
667        let bytes: Vec<u8> = encode(&packet).unwrap();
668        let socket = socket
669            .send_dgram(bytes, &addr)
670            .wait()
671            .map(|(s, _)| s)
672            .unwrap();
673
674        let local_addr = socket.local_addr().unwrap().ip();
675        let packet = build_osc_message("/sys/host", vec![OscType::String(local_addr.to_string())]);
676        let bytes: Vec<u8> = encode(&packet).unwrap();
677        let socket = socket
678            .send_dgram(bytes, &addr)
679            .wait()
680            .map(|(s, _)| s)
681            .unwrap();
682
683        let packet = build_osc_message("/sys/prefix", vec![OscType::String(prefix.into())]);
684        let bytes: Vec<u8> = encode(&packet).unwrap();
685        let socket = socket
686            .send_dgram(bytes, &addr)
687            .wait()
688            .map(|(s, _)| s)
689            .unwrap();
690
691        let packet = build_osc_message("/sys/info", vec![]);
692        let bytes: Vec<u8> = encode(&packet).unwrap();
693        let mut socket = socket
694            .send_dgram(bytes, &addr)
695            .wait()
696            .map(|(s, _)| s)
697            .unwrap();
698
699        let mut info = MonomeInfo::new();
700
701        // Loop until we've received all the /sys/info messages
702        let socket = loop {
703            socket = socket
704                .recv_dgram(vec![0u8; 1024])
705                .and_then(|(socket, data, _, _)| {
706                    let packet = decode(&data).unwrap();
707                    info.fill(packet);
708                    Ok(socket)
709                })
710                .wait()
711                .map(|socket| socket)
712                .unwrap();
713
714            if info.complete() {
715                break socket;
716            }
717        };
718
719        Ok((info, socket, name, device_type, port))
720    }
721    /// Enumerate all monome devices on a non-standard serialosc port, on a specific host.
722    ///
723    /// If successful, this returns a list of MonomeDevice, which contain basic informations about
724    /// the device: type, serial number, port allocated by serialosc.
725    ///
726    /// # Arguments
727    ///
728    /// * `serialosc_addr: the address of the host on which serialosc runs
729    /// * `serialosc_port`: the port on which serialosc is running
730    ///
731    /// # Example
732    ///
733    /// Enumerate and display all monome device on port 1234:
734    ///
735    /// ```no_run
736    /// # use monome::Monome;
737    /// let enumeration = Monome::enumerate_devices_with_host_and_port("192.168.1.12".parse().unwrap(), 1234);
738    /// match enumeration {
739    ///     Ok(devices) => {
740    ///         for device in &devices {
741    ///            println!("{}", device);
742    ///         }
743    ///     }
744    ///     Err(e) => {
745    ///         eprintln!("Error: {}", e);
746    ///     }
747    /// }
748    /// ```
749    pub fn enumerate_devices_with_host_and_port(
750        serialosc_addr: IpAddr,
751        serialosc_port: u16,
752    ) -> Result<Vec<MonomeDevice>, String> {
753        let socket = new_bound_socket();
754        let mut devices = Vec::<MonomeDevice>::new();
755        let server_port = socket.local_addr().unwrap().port();
756        let server_ip = socket.local_addr().unwrap().ip().to_string();
757
758        let packet = build_osc_message(
759            "/serialosc/list",
760            vec![
761                OscType::String(server_ip),
762                OscType::Int(i32::from(server_port)),
763            ],
764        );
765
766        let bytes: Vec<u8> = encode(&packet).unwrap();
767
768        let addr = SocketAddr::new(serialosc_addr, serialosc_port);
769        let (mut socket, _) = socket.send_dgram(bytes, &addr).wait().unwrap();
770        // loop until we find the device list message. It can be that some other messages are
771        // received in the meantime, for example, tilt messages, or keypresses. Ignore them
772        // here. If no message have been received for 500ms, consider we have all the messages and
773        // carry on.
774        loop {
775            let fut = socket.recv_dgram(vec![0u8; 1024]).select2(Delay::new(
776                Instant::now() + Duration::from_millis(DEVICE_ENUMERATION_TIMEOUT_MS),
777            ));
778            let task = tokio::runtime::current_thread::block_on_all(fut);
779            socket = match task {
780                Ok(Either::A(((s, data, _, _), _))) => {
781                    socket = s;
782                    let packet = decode(&data).unwrap();
783
784                    match packet {
785                        OscPacket::Message(message) => {
786                            if message.addr == "/serialosc/device" {
787                                let args = message.args;
788                                if let [OscType::String(ref name), OscType::String(ref device_type), OscType::Int(port)] =
789                                    args.as_slice()
790                                {
791                                    devices.push(MonomeDevice::new(
792                                        name,
793                                        device_type,
794                                        serialosc_addr,
795                                        (*port) as u16,
796                                    ));
797                                }
798                            }
799                        }
800                        OscPacket::Bundle(_bundle) => {
801                            eprintln!("Unexpected bundle received during setup");
802                        }
803                    };
804
805                    socket
806                }
807                Ok(Either::B(_)) => {
808                    // timeout
809                    break;
810                }
811                Err(e) => {
812                    panic!("{:?}", e);
813                }
814            };
815        }
816
817        Ok(devices)
818    }
819    /// Enumerate all monome devices on the standard port on which serialosc runs (12002).
820    ///
821    /// If successful, this returns a list of MonomeDevice, which contain basic informations about
822    /// the device: type, serial number, port allocated by serialosc.
823    ///
824    /// # Arguments
825    ///
826    /// * `serialosc_port`: the port on which serialosc is running
827    ///
828    /// # Example
829    ///
830    /// Enumerate and display all monome device on port 1234:
831    ///
832    /// ```no_run
833    /// # use monome::Monome;
834    /// let enumeration = Monome::enumerate_devices();
835    /// match enumeration {
836    ///     Ok(devices) => {
837    ///         for device in &devices {
838    ///            println!("{}", device);
839    ///         }
840    ///     }
841    ///     Err(e) => {
842    ///         eprintln!("Error: {}", e);
843    ///     }
844    /// }
845    /// ```
846    pub fn enumerate_devices() -> Result<Vec<MonomeDevice>, String> {
847        Monome::enumerate_devices_with_port(SERIALOSC_PORT)
848    }
849    /// Enumerate all monome devices on localhost, on a specific port.
850    ///
851    /// If successful, this returns a list of MonomeDevice, which contain basic informations about
852    /// the device: type, serial number, port allocated by serialosc.
853    ///
854    /// # Arguments
855    ///
856    /// * `port`: the port serialoscd is bound to.
857    ///
858    /// # Example
859    ///
860    /// Enumerate and display all monome device running on default port at a specific address.
861    ///
862    /// ```no_run
863    /// # use monome::Monome;
864    /// # let enumeration = Monome::enumerate_devices_with_port(12012);
865    /// match enumeration {
866    ///     Ok(devices) => {
867    ///         for device in &devices {
868    ///            println!("{}", device);
869    ///         }
870    ///     }
871    ///     Err(e) => {
872    ///         eprintln!("Error: {}", e);
873    ///     }
874    /// }
875    /// ```
876    pub fn enumerate_devices_with_port(port: u16) -> Result<Vec<MonomeDevice>, String> {
877        Monome::enumerate_devices_with_host_and_port(
878            std::net::IpAddr::V4(<Ipv4Addr>::LOCALHOST),
879            port,
880        )
881    }
882    /// Enumerate all monome devices on the standard port on which serialosc runs (12002), on a
883    /// specific address.
884    ///
885    /// If successful, this returns a list of MonomeDevice, which contain basic informations about
886    /// the device: type, serial number, port allocated by serialosc.
887    ///
888    /// # Arguments
889    ///
890    /// * `addr: the address at which serialosc is reachable
891    ///
892    /// # Example
893    ///
894    /// Enumerate and display all monome device running on default port at a specific addr.
895    ///
896    /// ```no_run
897    /// # use monome::Monome;
898    /// let enumeration = Monome::enumerate_devices_on_host("192.168.1.12".parse().unwrap());
899    /// match enumeration {
900    ///     Ok(devices) => {
901    ///         for device in &devices {
902    ///            println!("{}", device);
903    ///         }
904    ///     }
905    ///     Err(e) => {
906    ///         eprintln!("Error: {}", e);
907    ///     }
908    /// }
909    /// ```
910    pub fn enumerate_devices_on_host(host: IpAddr) -> Result<Vec<MonomeDevice>, String> {
911        Monome::enumerate_devices_with_host_and_port(host, SERIALOSC_PORT)
912    }
913    /// Sets up the "first" monome device, with a particular prefix. When multiple devices are
914    /// plugged in, it's unclear which one is activated, however this is rare.
915    ///
916    /// # Arguments
917    ///
918    /// * `prefix` - the prefix to use for this device and this application
919    ///
920    /// # Example
921    ///
922    /// Set up a monome, with a prefix of "/prefix":
923    ///
924    /// ```no_run
925    /// # use monome::Monome;
926    /// let m = Monome::new("/prefix");
927    ///
928    /// match m {
929    ///   Ok(monome) => {
930    ///     println!("{:?}", monome);
931    ///   }
932    ///   Err(s) => {
933    ///     println!("Could not setup the monome: {}", s);
934    ///   }
935    /// }
936    /// ```
937    pub fn new<S>(prefix: S) -> Result<Monome, String>
938    where
939        S: Into<String>,
940    {
941        Monome::new_with_port(prefix, SERIALOSC_PORT)
942    }
943    /// Sets up the "first" monome device, with a particular prefix and a non-standard port for
944    /// serialosc. When multiple devices are plugged in, it's unclear which one is activated,
945    /// however this is rare.
946    ///
947    /// # Arguments
948    ///
949    /// * `prefix` - the prefix to use for this device and this application
950    /// * `serialosc_port` - the port at which serialosc can be reached.
951    ///
952    /// # Example
953    ///
954    /// Set up a monome, with a prefix of "/prefix", and specify an explicit port on which
955    /// serialosc can be reached (here, the default of 12002):
956    ///
957    /// ```no_run
958    /// # use monome::Monome;
959    /// let m = Monome::new_with_port("/prefix", 12002);
960    ///
961    /// match m {
962    ///   Ok(monome) => {
963    ///     println!("{:?}", monome);
964    ///   }
965    ///   Err(s) => {
966    ///     println!("Could not setup the monome: {}", s);
967    ///   }
968    /// }
969    /// ```
970    pub fn new_with_port<S>(prefix: S, serialosc_port: u16) -> Result<Monome, String>
971    where
972        S: Into<String>,
973    {
974        let devices = Monome::enumerate_devices_with_port(serialosc_port)?;
975        if devices.is_empty() {
976            return Err("No devices detected".to_string());
977        }
978        Monome::from_device(&devices[0], prefix.into())
979    }
980    /// Get a monome instance on which to call commands, from a `MonomeDevice`.
981    ///
982    /// # Arguments
983    ///
984    /// * `device`: a `MonomeDevice` acquired through `enumerate_devices`.
985    /// * `prefix`: the prefix to use for this device and this application
986    ///
987    /// # Example
988    ///
989    /// ```no_run
990    /// # use monome::Monome;
991    /// let enumeration = Monome::enumerate_devices();
992    /// match enumeration {
993    ///     Ok(devices) => {
994    ///         for device in &devices {
995    ///             println!("{}", device);
996    ///             match Monome::from_device(device, "prefix") {
997    ///                 Ok(m) => {
998    ///                     println!("Monome setup:\n{}", m);
999    ///                 }
1000    ///                 Err(e) => {
1001    ///                     println!("Error setting up {} ({})", device, e);
1002    ///                 }
1003    ///             }
1004    ///         }
1005    ///     }
1006    ///     Err(e) => {
1007    ///         eprintln!("Error: {}", e);
1008    ///     }
1009    /// }
1010    /// ```
1011    pub fn from_device<S>(device: &MonomeDevice, prefix: S) -> Result<Monome, String>
1012    where
1013        S: Into<String>,
1014    {
1015        let prefix = prefix.into();
1016        let (info, socket, name, device_type, device_port) = Monome::setup(&*prefix, device)?;
1017
1018        let (sender, receiver) = futures::sync::mpsc::unbounded();
1019        let q = Arc::new(ArrayQueue::new(32));
1020        let q2 = q.clone();
1021        let t = Transport::new(device.host(), device_port, socket, q, receiver);
1022
1023        thread::spawn(move || {
1024            tokio::run(t.map_err(|e| error!("server error = {:?}", e)));
1025        });
1026
1027        Ok(Monome {
1028            tx: sender,
1029            q: q2,
1030            name,
1031            device_type,
1032            host: info.host.unwrap(),
1033            id: info.id.unwrap(),
1034            port: device_port,
1035            prefix,
1036            rotation: info.rotation.unwrap(),
1037            size: info.size.unwrap(),
1038        })
1039    }
1040
1041    /// Set a single led on a grid on or off.
1042    ///
1043    /// # Arguments
1044    ///
1045    /// - `x` - the horizontal position of the led to set.
1046    /// - `y` - the vertical positino of the led to set.
1047    /// - `arg` - either a bool, true to set a led On, false to set it Off, or a number between 0
1048    /// and 16, 0 being led off, 16 being full led brightness.
1049    ///
1050    /// # Example
1051    ///
1052    /// Set the led on the second row and second column to On, and also the third row and second
1053    /// column to mid-brightness:
1054    ///
1055    /// ```no_run
1056    /// # use monome::Monome;
1057    /// # let mut monome = Monome::new("/prefix").unwrap();
1058    /// monome.set(1 /* 2nd, 0-indexed */,
1059    ///            1 /* 2nd, 0-indexed */,
1060    ///            true);
1061    /// monome.set(1 /* 2nd, 0-indexed */,
1062    ///            2 /* 3nd, 0-indexed */,
1063    ///            8);
1064    /// ```
1065    pub fn set<'a, A>(&mut self, x: i32, y: i32, arg: A)
1066    where
1067        A: IntoAddrAndArgs<'a, OscType>,
1068    {
1069        if self.device_type != MonomeDeviceType::Grid {
1070            error!("Called grid method on something that is not an grid.");
1071            return;
1072        }
1073        let (frag, arg) = arg.as_addr_frag_and_args();
1074        self.send(
1075            &format!("/grid/led/{}set", frag),
1076            vec![OscType::Int(x), OscType::Int(y), arg],
1077        );
1078    }
1079
1080    /// Set all led of the grid to an intensity
1081    ///
1082    /// # Arguments
1083    ///
1084    /// * `intensity` - either a bool, true for led On or false for led Off, or a number between 0
1085    /// and 16, 0 being led off, and 16 being full led brightness.
1086    ///
1087    /// # Example
1088    ///
1089    /// On a grid, set all led to medium brightness, then turn it on:
1090    ///
1091    /// ```no_run
1092    /// # use monome::Monome;
1093    /// let mut monome = Monome::new("/prefix").unwrap();
1094    /// monome.all(8);
1095    /// monome.all(false);
1096    /// ```
1097    pub fn all<'a, A>(&mut self, arg: A)
1098    where
1099        A: IntoAddrAndArgs<'a, OscType>,
1100    {
1101        if self.device_type != MonomeDeviceType::Grid {
1102            error!("Called grid method on something that is not an grid.");
1103            return;
1104        }
1105        let (frag, arg) = arg.as_addr_frag_and_args();
1106        self.send(&format!("/grid/led/{}all", frag), vec![arg]);
1107    }
1108
1109    /// Set all the leds of a monome in one call.
1110    ///
1111    /// # Arguments
1112    ///
1113    /// * `leds` - a vector of 64 booleans for a monome 64, 128 elements for a monome 128, and 256
1114    /// elements for a monome 256, packed in row order.
1115    ///
1116    /// # Example
1117    ///
1118    /// One a monome 128, do a checkerboard pattern:
1119    ///
1120    /// ```no_run
1121    /// # use monome::Monome;
1122    /// let mut monome = Monome::new("/prefix").unwrap();
1123    /// let mut grid = [false; 128];
1124    /// for i in 0..128 {
1125    ///   grid[i] = (i + 1) % 2 == 0;
1126    /// }
1127    /// monome.set_all(&grid);
1128    /// ```
1129    pub fn set_all(&mut self, leds: &[bool]) {
1130        if self.device_type != MonomeDeviceType::Grid {
1131            error!("Called grid method on something that is not an grid.");
1132            return;
1133        }
1134        let width_in_quad = self.size.0 / 8;
1135        let height_in_quad = self.size.1 / 8;
1136        let width = self.size.0;
1137        let quad_size: i32 = 8;
1138
1139        let mut masks = [0 as u8; 8];
1140        for a in 0..height_in_quad {
1141            for b in 0..width_in_quad {
1142                for i in 0..8 {
1143                    // for each row
1144                    let mut mask: u8 = 0;
1145                    for j in (0..8).rev() {
1146                        // create mask
1147                        let idx = toidx(b * quad_size + j, a * quad_size + i, width);
1148                        mask = mask.rotate_left(1) | if leds[idx] { 1 } else { 0 };
1149                    }
1150                    masks[i as usize] = mask;
1151                }
1152                self.map(b * 8, a * 8, &masks);
1153            }
1154        }
1155    }
1156
1157    /// Set all the leds of a monome in one call.
1158    ///
1159    /// # Arguments
1160    ///
1161    /// * `leds` - a vector of 64 integers in [0, 15] for a monome 64, 128 elements for a monome
1162    /// 128, and 256 elements for a monome 256, packed in row order.
1163    ///
1164    /// # Example
1165    ///
1166    /// One a monome 128, do a gradient
1167    ///
1168    /// ```no_run
1169    /// # use monome::Monome;
1170    ///
1171    /// let mut m = Monome::new("/prefix").unwrap();
1172    /// let mut grid: Vec<u8> = vec!(0; 128);
1173    /// for i in 0..8 {
1174    ///     for j in 0..16 {
1175    ///         grid[i * 16 + j] = (2 * i) as u8;
1176    ///     }
1177    /// }
1178    /// m.set_all_intensity(&grid);
1179    /// ```
1180    pub fn set_all_intensity(&mut self, leds: &[u8]) {
1181        if self.device_type != MonomeDeviceType::Grid {
1182            error!("Called grid method on something that is not an grid.");
1183            return;
1184        }
1185        let width_in_quad = self.size.0 / 8;
1186        let height_in_quad = self.size.1 / 8;
1187        let width = self.size.0;
1188        let quad_size = 8;
1189
1190        let mut quad = [0 as u8; 64];
1191        for a in 0..height_in_quad {
1192            for b in 0..width_in_quad {
1193                // Get the quad into an array
1194                for i in 0..8 as i32 {
1195                    for j in 0..8 as i32 {
1196                        let idx = toidx(b * quad_size + j, a * quad_size + i, width);
1197                        quad[(i * 8 + j) as usize] = leds[idx];
1198                    }
1199                }
1200                self.map(b * 8, a * 8, &quad);
1201            }
1202        }
1203    }
1204
1205    /// Set the value an 8x8 quad of led on a monome grid.
1206    ///
1207    /// # Arguments
1208    ///
1209    /// * `x_offset` - at which offset, that must be a multiple of 8, to set the quad.
1210    /// * `y_offset` - at which offset, that must be a multiple of 8, to set the quad.
1211    /// * `masks` - a vector of 8 unsigned 8-bit integers that is a mask representing the leds to
1212    /// light up, or a vector of 64 bools, true for led On, false for led Off, packed in row order,
1213    /// or a vector of 64 integers between 0 and 15, for the brightness of each led, packed in
1214    /// row order.
1215    ///
1216    /// # Example
1217    ///
1218    /// On a monome 128, draw a triangle in the lower left half of the rightmost half, and a
1219    /// gradient on the leftmost half.
1220    /// ```no_run
1221    /// # extern crate monome;
1222    /// # use monome::Monome;
1223    /// let mut monome = Monome::new("/prefix").unwrap();
1224    /// let mut v = [0; 64];
1225    /// for i in 0..64 {
1226    ///     v[i] = (i / 4) as u8;
1227    /// }
1228    /// monome.map(0, 0, &v);
1229    /// monome.map(8, 0, &[1, 3, 7, 15, 32, 63, 127, 0b11111111]);
1230    /// ```
1231    pub fn map<'a, A>(&mut self, x_offset: i32, y_offset: i32, masks: A)
1232    where
1233        A: IntoAddrAndArgs<'a, Vec<OscType>> + Sized,
1234    {
1235        if self.device_type != MonomeDeviceType::Grid {
1236            error!("Called grid method on something that is not an grid.");
1237            return;
1238        }
1239        let (frag, mut arg) = masks.as_addr_frag_and_args();
1240
1241        let mut args = Vec::with_capacity(2 + arg.len());
1242
1243        args.push(OscType::Int(x_offset));
1244        args.push(OscType::Int(y_offset));
1245        args.append(&mut arg);
1246
1247        self.send(&format!("/grid/led/{}map", frag), args);
1248    }
1249
1250    /// Set a full row of a grid, using one or more 8-bit mask(s), or a vector containing booleans
1251    /// or integer intensity values.
1252    ///
1253    /// # Arguments
1254    ///
1255    /// * `x_offset` - at which 8 button offset to start setting the leds. This is always 0 for a
1256    /// 64, and can be 8 for a 128 or 256.
1257    /// * `y` - which row to set, 0-indexed. This must be lower than the number of rows of the
1258    /// device.
1259    /// * `leds` - either the list of masks that determine the pattern to light on for a particular
1260    /// 8 led long section, or a vector of either int or bool, one element for each led.
1261    ///
1262    /// # Example
1263    ///
1264    /// On a monome 128, light up every other led of the right half of the 3rd  row:
1265    ///
1266    /// ```no_run
1267    /// # use monome::Monome;
1268    /// let mut monome = Monome::new("/prefix").unwrap();
1269    /// monome.row(8 /* rightmost half */,
1270    ///            2 /* 3rd row, 0 indexed */,
1271    ///            &0b01010101u8 /* every other led, 85 in decimal */);
1272    /// ```
1273    pub fn row<'a, A>(&mut self, x_offset: i32, y: i32, leds: &A)
1274    where
1275        A: IntoAddrAndArgs<'a, Vec<OscType>>,
1276    {
1277        if self.device_type != MonomeDeviceType::Grid {
1278            error!("Called grid method on something that is not an grid.");
1279            return;
1280        }
1281        let (frag, arg) = leds.as_addr_frag_and_args();
1282
1283        let mut args = Vec::with_capacity((2 + arg.len()) as usize);
1284
1285        args.push(OscType::Int(x_offset));
1286        args.push(OscType::Int(y));
1287        args.append(&mut arg.to_vec());
1288
1289        self.send(&format!("/grid/led/{}row", frag), args);
1290    }
1291
1292    /// Set a full column of a grid, using one or more 8-bit mask(s), or a vector containing
1293    /// booleans or integer intensity values.
1294    ///
1295    /// # Arguments
1296    ///
1297    /// * `x` - which column to set 0-indexed. This must be lower than the number of columns of the
1298    /// device.
1299    /// * `y_offset` - at which 8 button offset to start setting the leds. This is always 0 for a
1300    /// 64, and can be 8 for a 128 or 256.
1301    /// * `leds` - either the list of masks that determine the pattern to light on for a particular
1302    /// 8 led long section, or a vector of either int or bool, one element for each led.
1303    ///
1304    /// # Example
1305    ///
1306    /// On a monome 256, light up every other led of the bottom half of the 3rd column from the
1307    /// right:
1308    ///
1309    /// ```no_run
1310    /// use monome::Monome;
1311    /// let mut monome = Monome::new("/prefix").unwrap();
1312    /// monome.col(2 /* 3rd column, 0-indexed */,
1313    ///            8 /* bottom half */,
1314    ///            &0b01010101u8 /* every other led, 85 in decimal */);
1315    /// ```
1316    pub fn col<'a, A>(&mut self, x: i32, y_offset: i32, leds: &A)
1317    where
1318        A: IntoAddrAndArgs<'a, Vec<OscType>>,
1319    {
1320        if self.device_type != MonomeDeviceType::Grid {
1321            error!("Called grid method on something that is not an grid.");
1322            return;
1323        }
1324        let (frag, mut arg) = leds.as_addr_frag_and_args();
1325
1326        let mut args = Vec::with_capacity((2 + arg.len()) as usize);
1327
1328        args.push(OscType::Int(x));
1329        args.push(OscType::Int(y_offset));
1330        args.append(&mut arg);
1331
1332        self.send(&format!("/grid/led/{}col", frag), args);
1333    }
1334
1335    /// Set a single led, with intensity, on an Arc.
1336    ///
1337    /// # Arguments
1338    ///
1339    /// - `n` - the encoder to set a led on, 0-indexed.
1340    /// - `index` - which led to set. 0 is the top led, and goes clockwise. This is modulo 64, so
1341    /// passing in 65 is the second led from the top, going clockwise.
1342    /// - `intensity` - the intensity of the led 0 being off, 15 full brightness.
1343    ///
1344    /// # Example
1345    ///
1346    /// On an arc, make a circular gradient on the first encoder:
1347    ///
1348    /// ```no_run
1349    /// use monome::Monome;
1350    /// let mut monome = Monome::new("/prefix").unwrap();
1351    /// for i in 0..64 {
1352    ///   monome.set(0, i, i / 4);
1353    /// }
1354    /// ```
1355    pub fn ring_set(&mut self, n: usize, index: u32, intensity: u32) {
1356        if self.device_type != MonomeDeviceType::Arc {
1357            error!("Called arc method on something that is not an arc.");
1358            return;
1359        }
1360        let mut args = Vec::with_capacity(3);
1361        args.push(OscType::Int(n as i32));
1362        args.push(OscType::Int(index as i32));
1363        args.push(OscType::Int(intensity as i32));
1364
1365        self.send("/ring/set", args);
1366    }
1367
1368    /// Set all the led on an encoder to a particular intensity.
1369    ///
1370    /// # Arguments
1371    ///
1372    /// - `n` - the encoder to set the leds on, 0-indexed.
1373    /// - `intensity` - the intensity of the leds: 0 being off, 15 full brightness.
1374    ///
1375    /// # Example
1376    ///
1377    /// On an arc, make a gradient accross all four encoders:
1378    ///
1379    /// ```no_run
1380    /// use monome::Monome;
1381    /// let mut monome = Monome::new("/prefix").unwrap();
1382    /// for i in 0..4 {
1383    ///   monome.ring_all(i, (i * 4) as u32);
1384    /// }
1385    /// ```
1386    pub fn ring_all(&mut self, n: usize, intensity: u32) {
1387        if self.device_type != MonomeDeviceType::Arc {
1388            error!("Called arc method on something that is not an arc.");
1389            return;
1390        }
1391        let mut args = Vec::with_capacity(2);
1392        args.push(OscType::Int(n as i32));
1393        args.push(OscType::Int(intensity as i32));
1394
1395        self.send("/ring/all", args);
1396    }
1397
1398    /// Set a range of led to a particular intensity.
1399    ///
1400    /// # Arguments
1401    ///
1402    /// - `n` - the encoder to set the leds on, 0-indexed.
1403    /// - `start_offset` - the encoder to start setting the led from, 0-indexed, modulo 64.
1404    /// - `end_offset` - the encoder to end setting the led at 0-indexed, inclusive, modulo 64.
1405    /// - `intensity` - the intensity of the leds: 0 being off, 15 full brightness.
1406    ///
1407    /// # Example
1408    ///
1409    /// On an arc, lit up halves:
1410    ///
1411    /// ```no_run
1412    /// use monome::Monome;
1413    /// let mut monome = Monome::new("/prefix").unwrap();
1414    /// monome.ring_range(0, 0, 32, 15);
1415    /// monome.ring_range(1, 32, 64, 15);
1416    /// monome.ring_range(2, 16, 48, 15);
1417    /// monome.ring_range(3, 48, 16, 15);
1418    /// ```
1419    pub fn ring_range(&mut self, n: usize, start_offset: usize, end_offset: usize, intensity: u32) {
1420        if self.device_type != MonomeDeviceType::Arc {
1421            error!("Called arc method on something that is not an arc.");
1422            return;
1423        }
1424        let mut args = Vec::with_capacity(4);
1425        args.push(OscType::Int(n as i32));
1426        args.push(OscType::Int(start_offset as i32));
1427        args.push(OscType::Int(end_offset as i32));
1428        args.push(OscType::Int(intensity as i32));
1429
1430        self.send("/ring/range", args);
1431    }
1432
1433    /// Set all leds on an encoder to specific values.
1434    ///
1435    /// # Arguments
1436    ///
1437    /// - `n` - the encoder to set the leds on, 0-indexed.
1438    /// - `values` - an array of 64 values between 0 an 16, one for each led.
1439    ///
1440    /// # Example
1441    ///
1442    /// On an arc, make a gradient on an encoder.
1443    ///
1444    /// ```no_run
1445    /// use monome::Monome;
1446    /// let mut monome = Monome::new("/prefix").unwrap();
1447    /// let mut v: [u8; 64] = [0; 64];
1448    ///
1449    /// for i in 0..64 {
1450    ///     v[i] = (i / 4) as u8;
1451    /// }
1452    /// monome.ring_map(0, &v);
1453    /// ```
1454    pub fn ring_map(&mut self, n: usize, values: &[u8; 64]) {
1455        let mut args = Vec::with_capacity(65);
1456        args.push(OscType::Int(n as i32));
1457        for v in values.iter() {
1458            args.push(OscType::Int(i32::from(*v)));
1459        }
1460
1461        self.send("/ring/map", args);
1462    }
1463
1464    /// Enable or disable all tilt sensors (usually, there is only one), which allows receiving the
1465    /// `/<prefix>/tilt/` events, with the n,x,y,z coordinates as parameters.
1466    pub fn tilt_all(&mut self, on: bool) {
1467        self.send(
1468            "/tilt/set",
1469            vec![OscType::Int(0), OscType::Int(if on { 1 } else { 0 })],
1470        );
1471    }
1472
1473    /// Set the rotation for this device. This is either 0, 90, 180 or 270
1474    pub fn set_rotation(&mut self, rotation: i32) {
1475        self.send_no_prefix("/sys/rotation", vec![OscType::Int(rotation)]);
1476        self.rotation = rotation;
1477    }
1478
1479    /// Set the prefix for this device.
1480    pub fn set_prefix(&mut self, prefix: String) {
1481        self.send_no_prefix("/sys/prefix", vec![OscType::String(prefix.clone())]);
1482        self.prefix = prefix;
1483    }
1484
1485    /// Get the name of this device.
1486    pub fn name(&self) -> String {
1487        self.name.clone()
1488    }
1489
1490    /// Get the type for this device (for example `"monome 128"`).
1491    pub fn device_type(&self) -> MonomeDeviceType {
1492        self.device_type.clone()
1493    }
1494
1495    /// Get the port for this device.
1496    pub fn port(&self) -> u16 {
1497        self.port
1498    }
1499
1500    /// Get the host for this device is at.
1501    pub fn host(&self) -> String {
1502        self.host.clone()
1503    }
1504
1505    /// Get the id of this device.
1506    pub fn id(&self) -> String {
1507        self.id.clone()
1508    }
1509
1510    /// Get the current prefix of this device.
1511    pub fn prefix(&self) -> String {
1512        self.prefix.clone()
1513    }
1514
1515    /// Get the current rotation of this device.
1516    pub fn rotation(&self) -> i32 {
1517        self.rotation
1518    }
1519
1520    /// Get the size of this device, as a `(width, height)`.
1521    pub fn size(&self) -> (i32, i32) {
1522        self.size
1523    }
1524    /// Get the width of this device.
1525    pub fn width(&self) -> usize {
1526        self.size.0 as usize
1527    }
1528
1529    /// Get the height of this device.
1530    pub fn height(&self) -> usize {
1531        self.size.1 as usize
1532    }
1533
1534    /// Adds the prefix, packs the OSC message into an u8 vector and sends it to the transport.
1535    fn send(&mut self, addr: &str, args: Vec<OscType>) {
1536        let with_prefix = format!("{}{}", self.prefix, addr);
1537        self.send_no_prefix(&with_prefix, args);
1538    }
1539
1540    /// Packs the OSC message into an u8 vector and sends it to the transport.
1541    fn send_no_prefix(&mut self, addr: &str, args: Vec<OscType>) {
1542        let message = OscMessage {
1543            addr: addr.to_owned(),
1544            args,
1545        };
1546        let packet = OscPacket::Message(message);
1547        debug!("⇨ {:?}", packet);
1548        let bytes: Vec<u8> = encode(&packet).unwrap();
1549        match self.tx.unbounded_send(bytes) {
1550            Ok(()) => {}
1551            Err(_) => {
1552                error!("Send channel disconnected");
1553            }
1554        }
1555    }
1556
1557    /// Receives a MonomeEvent, from a connected monome, which can be a grid key press, an event
1558    /// from the tilt sensor, or a delta from an encoder, on an Arc. Only the events from the set
1559    /// `prefix` will be received.
1560    ///
1561    /// # Example
1562    ///
1563    /// ```no_run
1564    /// # extern crate monome;
1565    ///
1566    /// use monome::{Monome, MonomeEvent, KeyDirection};
1567    /// let mut m = Monome::new("/prefix").unwrap();
1568    ///
1569    /// loop {
1570    ///     match m.poll() {
1571    ///         Some(MonomeEvent::GridKey{x, y, direction}) => {
1572    ///             match direction {
1573    ///                 KeyDirection::Down => {
1574    ///                     println!("Key pressed: {}x{}", x, y);
1575    ///                 }
1576    ///                 KeyDirection::Up => {
1577    ///                     println!("Key released: {}x{}", x, y);
1578    ///                 }
1579    ///             }
1580    ///         }
1581    ///         Some(MonomeEvent::Tilt{n: _n, x, y, z: _z}) => {
1582    ///           println!("tilt update: pitch: {}, roll {}", x, y);
1583    ///         }
1584    ///         _ => {
1585    ///           break;
1586    ///         }
1587    ///     }
1588    /// }
1589    /// ```
1590    pub fn poll(&mut self) -> Option<MonomeEvent> {
1591        match self.q.pop() {
1592            Some(buf) => self.parse(&buf),
1593            None => None,
1594        }
1595    }
1596
1597    fn parse_serialosc(&self, message: rosc::OscMessage) {
1598        if message.addr == "/serialosc/device" {
1599            info!("/serialosc/device");
1600        } else if message.addr == "/serialosc/add" {
1601            let args = message.args;
1602            if let OscType::String(ref device_name) = args[0] {
1603                info!("device added: {}", device_name);
1604            } else {
1605                warn!("unexpected message for prefix {}", &message.addr);
1606            }
1607        } else if message.addr == "/serialosc/remove" {
1608            let args = &message.args;
1609            if let OscType::String(ref device_name) = args[0] {
1610                info!("device removed: {}", device_name);
1611            } else {
1612                warn!("unexpected message for prefix {}", &message.addr);
1613            }
1614        };
1615    }
1616
1617    fn parse_app_message(&self, message: rosc::OscMessage) -> Option<MonomeEvent> {
1618        if message
1619            .addr
1620            .starts_with(&format!("{}/grid/key", self.prefix))
1621        {
1622            if let [OscType::Int(x), OscType::Int(y), OscType::Int(v)] = message.args.as_slice() {
1623                info!("Key: {}:{} {}", *x, *y, *v);
1624                let direction = if *v == 1 {
1625                    KeyDirection::Down
1626                } else {
1627                    KeyDirection::Up
1628                };
1629                return Some(MonomeEvent::GridKey {
1630                    x: *x,
1631                    y: *y,
1632                    direction,
1633                });
1634            }
1635            error!("Invalid /grid/key message received {:?}.", message.clone());
1636        } else if message.addr.starts_with(&format!("{}/tilt", self.prefix)) {
1637            if let [OscType::Int(n), OscType::Int(x), OscType::Int(y), OscType::Int(z)] =
1638                message.args.as_slice()
1639            {
1640                info!("Tilt {} {},{},{}", *n, *x, *y, *z);
1641                return Some(MonomeEvent::Tilt {
1642                    n: *n,
1643                    x: *x,
1644                    y: *y,
1645                    z: *z,
1646                });
1647            }
1648            error!("Invalid /tilt message received {:?}.", message);
1649        } else if message
1650            .addr
1651            .starts_with(&format!("{}/enc/delta", self.prefix))
1652        {
1653            if let [OscType::Int(n), OscType::Int(delta)] = message.args.as_slice() {
1654                info!("Encoder delta {} {}", n, delta);
1655                return Some(MonomeEvent::EncoderDelta {
1656                    n: *n as usize,
1657                    delta: *delta,
1658                });
1659            }
1660            error!("Invalid /end/delta message received {:?}.", message);
1661        } else if message
1662            .addr
1663            .starts_with(&format!("{}/enc/key", self.prefix))
1664        {
1665            if let [OscType::Int(n), OscType::Int(direction)] = message.args.as_slice() {
1666                info!("Encoder key {} {}", n, direction);
1667                return Some(MonomeEvent::EncoderKey {
1668                    n: *n as usize,
1669                    direction: if *direction == 1 {
1670                        KeyDirection::Down
1671                    } else {
1672                        KeyDirection::Up
1673                    },
1674                });
1675            }
1676            error!("Invalid /end/key message received {:?}.", message);
1677        } else {
1678            error!("not handled: {:?}", message.addr);
1679        }
1680        None
1681    }
1682
1683    fn parse(&self, buf: &[u8]) -> Option<MonomeEvent> {
1684        let packet = decode(buf).unwrap();
1685        debug!("⇦ {:?}", packet);
1686
1687        match packet {
1688            OscPacket::Message(message) => {
1689                if message.addr.starts_with("/serialosc") {
1690                    self.parse_serialosc(message);
1691                } else if message.addr.starts_with("/sys") {
1692                    // This should only be received during the setup phase
1693                    debug!("/sys received: {:?}", message);
1694                } else if message.addr.starts_with(&self.prefix) {
1695                    return self.parse_app_message(message);
1696                }
1697                None
1698            }
1699            OscPacket::Bundle(_bundle) => {
1700                panic!("wtf.");
1701            }
1702        }
1703    }
1704}
1705
1706impl fmt::Debug for Monome {
1707    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1708        let rv = write!(
1709            f,
1710            "Monome {}\n\ttype: {}\n\tport: {}\n\thost: {}\n\t\
1711            id: {}\n\tprefix: {}\n\trotation: {}",
1712            self.name, self.device_type, self.port, self.host, self.id, self.prefix, self.rotation
1713        );
1714        if self.device_type == MonomeDeviceType::Grid {
1715            return write!(f, "\n\tsize: {}:{}", self.size.0, self.size.1);
1716        }
1717        rv
1718    }
1719}
1720
1721impl fmt::Display for Monome {
1722    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1723        write!(f, "{:?}", self)
1724    }
1725}
1726
1727#[cfg(test)]
1728mod tests {
1729    use crate::build_osc_message;
1730    use crate::Monome;
1731    use crate::SERIALOSC_PORT;
1732    use rosc::decoder::decode;
1733    use rosc::encoder::encode;
1734    use rosc::{OscPacket, OscType};
1735    use std::sync::{Arc, Condvar, Mutex};
1736    use std::thread;
1737    use tokio::net::UdpSocket;
1738    use tokio::prelude::*;
1739
1740    #[test]
1741    fn setup() {
1742        let pair = Arc::new((Mutex::new(false), Condvar::new()));
1743        let pair2 = pair.clone();
1744
1745        thread::spawn(move || {
1746            let fake_device_port = 1234;
1747            let device_addr = format!("127.0.0.1:{}", fake_device_port).parse().unwrap();
1748            let device_socket = UdpSocket::bind(&device_addr).unwrap();
1749
1750            // Avoid failing if serialocs is running on the default port.
1751            let serialosc_addr = format!("127.0.0.1:{}", SERIALOSC_PORT + 1).parse().unwrap();
1752            let serialosc_socket = UdpSocket::bind(&serialosc_addr).unwrap();
1753
1754            {
1755                let &(ref lock, ref cvar) = &*pair2;
1756                let mut started = lock.lock().unwrap();
1757                *started = true;
1758                cvar.notify_all();
1759            }
1760
1761            let (socket, data, _, _) = serialosc_socket.recv_dgram(vec![0u8; 1024]).wait().unwrap();
1762            let packet = decode(&data).unwrap();
1763
1764            let msg = match packet {
1765                OscPacket::Message(m) => m,
1766                OscPacket::Bundle(_b) => panic!("unexpected bundle"),
1767            };
1768            assert!(msg.addr == "/serialosc/list");
1769            assert!(!msg.args.is_empty());
1770
1771            let app_port = if let OscType::Int(port) = msg.args[1] {
1772                port
1773            } else {
1774                panic!("bad message");
1775            };
1776
1777            let packet = build_osc_message(
1778                "/serialosc/device",
1779                vec![
1780                    OscType::String("monome grid test".into()),
1781                    OscType::String("m123123".into()),
1782                    OscType::Int(1234),
1783                ],
1784            );
1785
1786            let bytes: Vec<u8> = encode(&packet).unwrap();
1787
1788            let app_addr = format!("127.0.0.1:{}", app_port).parse().unwrap();
1789            let (mut socket, _) = socket.send_dgram(bytes, &app_addr).wait().unwrap();
1790
1791            fn receive_from_app_and_expect(
1792                socket: UdpSocket,
1793                expected_addr: String,
1794            ) -> (UdpSocket, Vec<OscType>) {
1795                let (socket, data, _, _) = socket.recv_dgram(vec![0u8; 1024]).wait().unwrap();
1796                let packet = decode(&data).unwrap();
1797
1798                let msg = match packet {
1799                    OscPacket::Message(m) => m,
1800                    OscPacket::Bundle(_b) => panic!("unexpected bundle"),
1801                };
1802
1803                assert!(msg.addr == expected_addr);
1804
1805                (socket, msg.args)
1806            }
1807
1808            let (device_socket, args) =
1809                receive_from_app_and_expect(device_socket, "/sys/port".into());
1810            let port = if let OscType::Int(port) = args[0] {
1811                assert!(port == 10000);
1812                port
1813            } else {
1814                panic!("bad port");
1815            };
1816            assert!(port == 10000);
1817            let (device_socket, args) =
1818                receive_from_app_and_expect(device_socket, "/sys/host".into());
1819            let host = if let OscType::String(ref host) = args[0] {
1820                host
1821            } else {
1822                panic!("bad host");
1823            };
1824            assert!(host == "127.0.0.1");
1825            let (device_socket, args) =
1826                receive_from_app_and_expect(device_socket, "/sys/prefix".into());
1827            let prefix = if let OscType::String(ref prefix) = args[0] {
1828                prefix
1829            } else {
1830                panic!("bad prefix");
1831            };
1832            assert!(prefix == "/plop");
1833            let (_device_socket, args) =
1834                receive_from_app_and_expect(device_socket, "/sys/info".into());
1835            assert!(args.is_empty());
1836
1837            let message_addrs = vec![
1838                "/sys/port",
1839                "/sys/host",
1840                "/sys/id",
1841                "/sys/prefix",
1842                "/sys/rotation",
1843                "/sys/size",
1844            ];
1845
1846            let message_args = vec![
1847                vec![OscType::Int(fake_device_port)],
1848                vec![OscType::String("127.0.0.1".into())],
1849                vec![OscType::String("monome blabla".into())],
1850                vec![OscType::String("/plop".into())],
1851                vec![OscType::Int(0)],
1852                vec![OscType::Int(16), OscType::Int(8)],
1853            ];
1854
1855            assert!(message_addrs.len() == message_args.len());
1856
1857            for i in 0..message_addrs.len() {
1858                let packet = build_osc_message(message_addrs[i], message_args[i].clone());
1859                let bytes: Vec<u8> = encode(&packet).unwrap();
1860                socket = socket
1861                    .send_dgram(bytes, &app_addr)
1862                    .map(|(socket, _)| socket)
1863                    .wait()
1864                    .unwrap();
1865            }
1866        });
1867
1868        let &(ref lock, ref cvar) = &*pair;
1869        let mut started = lock.lock().unwrap();
1870        while !*started {
1871            started = cvar.wait(started).unwrap();
1872        }
1873
1874        // use another port in case serialosc is running on the local machine
1875        let _m = Monome::new_with_port("/plop".to_string(), SERIALOSC_PORT + 1).unwrap();
1876    }
1877}