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}