launchkey_sdk/launchkey/
manager.rs1use crate::launchkey::bitmap::LaunchkeyBitmap;
2use crate::launchkey::commands::LaunchkeyCommand;
3use crate::launchkey::constants::{LaunchKeySku, DISABLE_DAW_MODE, ENABLE_DAW_MODE};
4use crate::launchkey::modes::encoder_mode::EncoderMode;
5use crate::launchkey::modes::fader_mode::FaderMode;
6use crate::launchkey::modes::pad_mode::PadMode;
7use crate::launchkey::surface::display::{Arrangement, GlobalDisplayTarget};
8use midir::{MidiOutput, MidiOutputPort};
9use std::any::TypeId;
10use std::cell::RefCell;
11use std::marker::PhantomData;
12use std::rc::Rc;
13use crate::midi::to_hex::ToHexString;
14
15pub trait LaunchKeyState {}
17
18pub struct DAWMode;
20impl LaunchKeyState for DAWMode {}
21
22pub struct StandaloneMode;
24impl LaunchKeyState for StandaloneMode {}
25
26pub struct LaunchkeyManager<S: LaunchKeyState + 'static> {
29 conn_out: Rc<RefCell<midir::MidiOutputConnection>>,
30 sku: LaunchKeySku,
31 state: PhantomData<S>,
32}
33
34impl<S: LaunchKeyState> LaunchkeyManager<S> {
35 fn _enable_daw_mode(&mut self) -> Result<(), midir::SendError> {
37 println!("Enabling DAW Mode");
38 self._send_bytes(ENABLE_DAW_MODE.to_vec())
39 }
40
41 fn _disable_daw_mode(&mut self) -> Result<(), midir::SendError> {
43 println!("Disabling DAW Mode");
44 self._send_bytes(DISABLE_DAW_MODE.to_vec())
45 }
46
47 fn _send_command(&mut self, command: LaunchkeyCommand) -> Result<(), midir::SendError> {
49 match command {
50 LaunchkeyCommand::SetPadMode(ref pad_mode) => {
51 match pad_mode {
52 PadMode::Drum => self._send_command(LaunchkeyCommand::SetDrumDAWMode(false)),
53 PadMode::DrumDAW => self._send_command(LaunchkeyCommand::SetDrumDAWMode(true)),
54 _ => Ok(()),
55 }?;
56 self._send_bytes(command.as_bytes(&self.sku))
57 }
58 command => self._send_bytes(command.as_bytes(&self.sku)),
59 }
60 }
61
62 fn _send_bytes(&mut self, bytes: Vec<u8>) -> Result<(), midir::SendError> {
64 println!("Sending MIDI message: {}", &bytes.to_hex_string());
65 self.conn_out.borrow_mut().send(&bytes)?;
66 Ok(())
67 }
68}
69
70impl LaunchkeyManager<StandaloneMode> {
71 pub fn new(
73 midi_out: MidiOutput,
74 port: &MidiOutputPort,
75 sku: LaunchKeySku,
76 ) -> Result<Self, String> {
77 let conn_out = midi_out
78 .connect(port, "launchkey-manager")
79 .map_err(|_| "Failed to connect to MIDI output".to_string())?;
80 Ok(Self {
81 conn_out: Rc::new(RefCell::new(conn_out)),
82 sku,
83 state: PhantomData,
84 })
85 }
86
87 pub fn default() -> Result<Self, String> {
89 let midi_out = MidiOutput::new("Custom DAW")
91 .map_err(|_| "Failed to create MIDI output".to_string())?;
92
93 let ports = midi_out.ports();
94 if ports.is_empty() {
95 return Err("No MIDI output ports found".to_string());
96 }
97
98 let out_port = ports
100 .iter()
101 .find(|port| {
102 midi_out
103 .port_name(port)
104 .unwrap_or_default()
105 .contains("MIDIOUT2")
106 })
107 .ok_or_else(|| "Could not find MIDIOUT2 port".to_string())?;
108
109 Self::new(midi_out, out_port, LaunchKeySku::Mini)
110 }
111
112 pub fn set_screen_text_global(
114 &mut self,
115 target: GlobalDisplayTarget,
116 arrangement: Arrangement,
117 ) -> Result<(), midir::SendError> {
118 self._send_command(LaunchkeyCommand::SetScreenTextGlobal {
119 target,
120 arrangement,
121 })
122 }
123
124 pub fn send_screen_bitmap(
126 &mut self,
127 target: GlobalDisplayTarget,
128 bitmap: LaunchkeyBitmap,
129 ) -> Result<(), midir::SendError> {
130 self._send_command(LaunchkeyCommand::SendScreenBitmap {
131 target,
132 bitmap: Box::new(bitmap),
133 })
134 }
135
136 pub fn into_daw_mode(mut self) -> Result<LaunchkeyManager<DAWMode>, midir::SendError> {
138 self._enable_daw_mode()?;
139 Ok(LaunchkeyManager {
140 conn_out: self.conn_out.clone(),
141 sku: self.sku.clone(),
142 state: PhantomData,
143 })
144 }
145}
146
147impl LaunchkeyManager<DAWMode> {
148 pub fn into_standalone_mode(
150 mut self,
151 ) -> Result<LaunchkeyManager<StandaloneMode>, midir::SendError> {
152 self._disable_daw_mode()?;
153 Ok(LaunchkeyManager {
154 conn_out: self.conn_out.clone(),
155 sku: self.sku.clone(),
156 state: PhantomData,
157 })
158 }
159
160 pub fn setup_default_element_modes(&mut self) -> Result<(), midir::SendError> {
162 self.send_command(LaunchkeyCommand::SetPadMode(PadMode::DAW))?;
163 self.send_command(LaunchkeyCommand::SetEncoderMode(EncoderMode::Plugin))?;
164 self.send_command(LaunchkeyCommand::SetFaderMode(FaderMode::Volume))?;
165
166 Ok(())
167 }
168
169 pub fn send_command(&mut self, command: LaunchkeyCommand) -> Result<(), midir::SendError> {
171 self._send_command(command)
172 }
173
174 pub fn send_commands(&mut self, commands: &[LaunchkeyCommand]) -> Result<(), midir::SendError> {
176 for command in commands {
177 self._send_command((*command).clone())?;
178 }
179 Ok(()) }
181}
182
183impl<S: LaunchKeyState + 'static> Drop for LaunchkeyManager<S> {
184 fn drop(&mut self) {
185 if TypeId::of::<S>() == TypeId::of::<DAWMode>() {
187 if let Err(err) = self._disable_daw_mode() {
188 eprintln!("Failed to disable DAW mode during cleanup: {}", err);
189 }
190 }
191 }
192}