# launchy
[![docs.rs](https://docs.rs/launchy/badge.svg)](https://docs.rs/launchy)
[![crates.io](https://img.shields.io/crates/v/launchy)](https://crates.io/crates/launchy)
[![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/kangalioo/launchy/blob/master/LICENSE)
An exhaustive Rust API for the Novation Launchpad devices, optimized for maximum expressiveness and minimum boilerplate!
---
Launchy is a library for the Novation Launchpad MIDI devices, for the Rust programming language.
## Features
- the **Canvas API** provides a powerful and concise way to control your Launchpads, for games or small lightshows
- the **direct Input/Output API** provides absolute control over your device and fine-grained access to the entire MIDI API of your device
- it's possible to chain multiple Launchpads together and use them as if it was one single big device
- optional support for [`embedded-graphics`](https://github.com/jamwaffles/embedded-graphics)
- very modular design: it's very easy to add support for new devices, or to add new features to [`Canvas`]
## Supported devices
- [ ] Launchpad
- [x] Launchpad S
- [x] Launchpad Mini
- [x] Launchpad Control
- [x] Launchpad Control XL
- [ ] Launchpad Pro
- [x] Launchpad MK2
- [ ] Launchpad X
- [ ] Launchpad Mini MK3
- [ ] Launchpad Pro MK2
## Canvas API
Launchy provides a `Canvas` trait that allows you to abstract over the hardware-specific details of your Launchpad and write concise, performant and
Launchpad-agnostic code.
The `Canvas` API even allows you to chain multiple Launchpads together and use them as if they were a single device. See `CanvasLayout` for that.
## Direct Input/Output API
In cases where you need direct access to your device's API, the abstraction provided by the `Canvas` API gets in your way.
Say if you wanted to programmatically retrieve the firmware version of your Launchpad MK2:
```rust
let input = launchy::mk2::Input::guess_polling()?;
let mut output = launchy::mk2::Output::guess()?;
output.request_version_inquiry()?;
for msg in input.iter() {
if let launchy::mk2::Message::VersionInquiry { firmware_version, .. } = msg {
println!("The firmware version is {}", firmware_version);
}
}
```
## Examples
### Satisfying pulse light effect
```rust
// Setup devices
let (mut canvas, poller) = launchy::CanvasLayout::new_polling();
canvas.add_by_guess_rotated::(0, 14, launchy::Rotation::Right)?;
canvas.add_by_guess_rotated::(10, 18, launchy::Rotation::UpsideDown)?;
canvas.add_by_guess_rotated::(2, 8, launchy::Rotation::Right)?;
let mut canvas = canvas.into_padded();
// Do the actual animation
for color in (0u64..).map(|f| Color::red_green_color(f as f32 / 60.0 / 2.5)) {
for msg in poller.iter_for_millis(17).filter(|msg| msg.is_press()) {
canvas[msg.pad()] = color * 60.0;
}
canvas.flush()?;
for pad in canvas.iter() {
let surrounding_color = pad.neighbors_5().iter()
.map(|&p| canvas.get(p).unwrap_or(Color::BLACK))
.sum::() / 5.0 / 1.05;
canvas[pad] = canvas[pad].mix(surrounding_color, 0.4);
}
}
```
### Seamless text scrolling across multiple Launchpads (leveraging `embedded_graphics`)
(This image shows the first three letters of the word "Hello")
```rust
use embedded_graphics::{fonts::{Font6x8, Text}, prelude::{Drawable, Point}, style::TextStyle};
// Setup the Launchpad layout
let mut canvas = launchy::CanvasLayout::new(|_msg| {});
canvas.add_by_guess_rotated::(0, 14, launchy::Rotation::Right)?;
canvas.add_by_guess_rotated::(10, 18, launchy::Rotation::UpsideDown)?;
canvas.add_by_guess_rotated::(2, 8, launchy::Rotation::Right)?;
// Do the text scrolling
let mut x_offset = 19;
loop {
canvas.clear();
let t = Text::new("Hello world! :)", Point::new(x_offset, 3))
.into_styled(TextStyle::new(Font6x8, Color::RED.into()))
.draw(&mut canvas).unwrap();
canvas.flush()?;
sleep(100);
x_offset -= 1;
}
```
## Why not just use [launch-rs](https://github.com/jamesmunns/launch-rs)?
- Last commit in 2017
- Only supports Launchpad MK2
- Only low-level access to the Launchpad is provided. There is no way to write high-level, concise interfacing code
- Uses the [PortMidi](https://github.com/musitdev/portmidi-rs) crate which is not as actively developed as [midir](https://github.com/Boddlnagg/midir), which Launchy uses
- Doesn't have any of the advanced features that Launchy provides