use log::debug;
use midir::MidiOutputConnection;
use super::Button;
use crate::OutputDevice;
pub use crate::protocols::double_buffering::*;
pub use crate::protocols::query::*;
pub struct Output {
connection: MidiOutputConnection,
}
impl crate::OutputDevice for Output {
const MIDI_CONNECTION_NAME: &'static str = "Launchy MIDI 1 output";
const MIDI_DEVICE_KEYWORD: &'static str = "Launchpad";
fn from_connection(connection: MidiOutputConnection) -> Result<Self, crate::MidiError> {
Ok(Self { connection })
}
fn send(&mut self, bytes: &[u8]) -> Result<(), crate::MidiError> {
self.connection.send(bytes)?;
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);
debug!(
"Setting button: {:?}, color: {:?}, double_buffering: {:?}",
button, 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])?;
}
}
Ok(())
}
pub fn set_button_rapid(
&mut self,
color1: Color,
dbb1: DoubleBufferingBehavior,
color2: Color,
dbb2: DoubleBufferingBehavior,
) -> Result<(), crate::MidiError> {
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,
};
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 {
self.send(&[0xB0, 30, 16 * (numerator - 1) + (denominator - 3)])
} else {
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;
self.send(&[0xB0, 0, last_byte])
}
pub fn request_device_inquiry(&mut self, query: DeviceIdQuery) -> Result<(), crate::MidiError> {
request_device_inquiry(self, query)
}
pub fn request_version_inquiry(&mut self) -> Result<(), crate::MidiError> {
request_version_inquiry(self)
}
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();
self.send(bytes)
}
pub fn reset(&mut self) -> Result<(), crate::MidiError> {
self.turn_on_all_leds(Brightness::Off)
}
pub fn set_all_buttons(
&mut self,
color: Color,
dbb: DoubleBufferingBehavior,
) -> Result<(), crate::MidiError> {
for _ in 0..40 {
self.set_button_rapid(color, dbb, color, dbb)?;
}
Ok(())
}
pub fn light(&mut self, button: Button, color: Color) -> Result<(), crate::MidiError> {
self.set_button(button, color, DoubleBufferingBehavior::Copy)
}
pub fn light_all_rapid(&mut self, color: Color) -> Result<(), crate::MidiError> {
self.set_all_buttons(color, DoubleBufferingBehavior::Copy)
}
}