use midir::MidiOutputConnection;
use crate::OutputDevice;
use super::Button;
pub use crate::protocols::double_buffering::*;
pub struct Output {
connection: MidiOutputConnection,
}
impl crate::OutputDevice for Output {
const MIDI_CONNECTION_NAME: &'static str = "Launchy S output";
const MIDI_DEVICE_KEYWORD: &'static str = "Launchpad S";
fn from_connection(connection: MidiOutputConnection) -> Result<Self, crate::MidiError> {
return Ok(Self { connection });
}
fn send(&mut self, bytes: &[u8]) -> Result<(), crate::MidiError> {
self.connection.send(bytes)?;
return Ok(());
}
}
impl Output {
pub fn set_button(&mut self, button: Button, color: Color, d: DoubleBufferingBehavior)
-> Result<(), crate::MidiError> {
let light_code = make_color_code(color, d);
match button {
Button::GridButton { x, y } => {
let button_code = y * 16 + x;
self.send(&[0x90, button_code, light_code])?;
},
Button::ControlButton { index } => {
let button_code = 104 + index;
self.send(&[0xB0, button_code, light_code])?;
}
}
return Ok(());
}
pub fn set_button_rapid(&mut self,
color1: Color, dbb1: DoubleBufferingBehavior,
color2: Color, dbb2: DoubleBufferingBehavior,
) -> Result<(), crate::MidiError> {
return self.send(&[0x92, make_color_code(color1, dbb1), make_color_code(color2, dbb2)]);
}
pub fn turn_on_all_leds(&mut self, brightness: Brightness) -> Result<(), crate::MidiError> {
let brightness_code = match brightness {
Brightness::Off => 0,
Brightness::Low => 125,
Brightness::Medium => 126,
Brightness::Full => 127,
};
return self.send(&[0xB0, 0, brightness_code]);
}
pub fn set_duty_cycle(&mut self, numerator: u8, denominator: u8) -> Result<(), crate::MidiError> {
assert!(numerator >= 1);
assert!(numerator <= 16);
assert!(denominator >= 3);
assert!(denominator <= 18);
if numerator < 9 {
return self.send(&[0xB0, 30, 16 * (numerator - 1) + (denominator - 3)]);
} else {
return self.send(&[0xB0, 31, 16 * (numerator - 9) + (denominator - 3)]);
}
}
pub fn control_double_buffering(&mut self, d: DoubleBuffering) -> Result<(), crate::MidiError> {
let last_byte = 0b00100000
| ((d.copy as u8) << 4)
| ((d.flash as u8) << 3)
| ((d.edited_buffer as u8) << 2)
| d.displayed_buffer as u8;
return self.send(&[0xB0, 0, last_byte]);
}
pub fn scroll_text(&mut self, text: &[u8], color: Color, should_loop: bool)
-> Result<(), crate::MidiError> {
let color_code = make_color_code_loopable(color, should_loop);
let bytes = &[
&[240, 0, 32, 41, 9, color_code],
text,
&[247]
].concat();
return self.send(bytes);
}
pub fn reset(&mut self) -> Result<(), crate::MidiError> {
return self.turn_on_all_leds(Brightness::Off);
}
pub fn light(&mut self, button: Button, color: Color) -> Result<(), crate::MidiError> {
return self.set_button(button, color, DoubleBufferingBehavior::Copy);
}
pub fn light_all_rapid(&mut self, color: Color) -> Result<(), crate::MidiError> {
let dbb = DoubleBufferingBehavior::None;
for _ in 0..40 {
self.set_button_rapid(color, dbb, color, dbb)?;
}
return Ok(());
}
}
fn make_color_code_loopable(color: Color, should_loop: bool)
-> u8 {
return ((should_loop as u8) << 6) | (color.green() << 4) | color.red();
}