launchkey_sdk/launchkey/surface/
buttons.rs

1use crate::bidirectional_enum_mappings;
2use std::ops::Deref;
3use wmidi::ControlValue;
4
5/// Enumeration of all supported Launchkey buttons that can be programmatically controlled.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum LaunchKeyButton {
8    Shift,
9    PreviousTrack,
10    NextTrack,
11    EncoderMoveUp,
12    EncoderMoveDown,
13    PadBankUp,
14    PadBankDown,
15    SceneLaunch,
16    Function,
17    CaptureMIDI,
18    UndoRedo,
19    Quantise,
20    Metronome,
21    Stop,
22    Loop,
23    Play,
24    Record,
25}
26
27bidirectional_enum_mappings!(LaunchKeyButton, u8, {
28    Shift => 0x3F,
29    PreviousTrack => 0x67,
30    NextTrack => 0x66,
31    EncoderMoveUp => 0x33,
32    EncoderMoveDown => 0x34,
33    PadBankUp => 0x6A,
34    PadBankDown => 0x6B,
35    SceneLaunch => 0x68,
36    Function => 0x69,
37    CaptureMIDI => 0x4A,
38    UndoRedo => 0x4D,
39    Quantise => 0x4B,
40    Metronome => 0x4C,
41    Stop => 0x74,
42    Loop => 0x76,
43    Play => 0x73,
44    Record => 0x75,
45});
46
47/// A wrapper for `LaunchKeyButton` limited to the subset of buttons available on the Launchkey Mini model.
48pub struct MiniLaunchKeyButton(pub LaunchKeyButton);
49
50impl MiniLaunchKeyButton {
51    pub const SUPPORTED: [LaunchKeyButton; 9] = [
52        LaunchKeyButton::Shift,
53        LaunchKeyButton::Play,
54        LaunchKeyButton::Record,
55        LaunchKeyButton::EncoderMoveUp,
56        LaunchKeyButton::EncoderMoveDown,
57        LaunchKeyButton::PadBankUp,
58        LaunchKeyButton::PadBankDown,
59        LaunchKeyButton::SceneLaunch,
60        LaunchKeyButton::Function,
61    ];
62
63    /// Converts a `LaunchKeyButton` to a `MiniLaunchKeyButton` if it is supported on the Mini model.
64    pub fn from_launchkey_button(button: LaunchKeyButton) -> Option<Self> {
65        if Self::SUPPORTED.contains(&button) {
66            Some(MiniLaunchKeyButton(button))
67        } else {
68            None
69        }
70    }
71}
72
73impl Deref for MiniLaunchKeyButton {
74    type Target = LaunchKeyButton;
75
76    fn deref(&self) -> &Self::Target {
77        &self.0
78    }
79}
80
81/// A wrapper for `LaunchKeyButton` representing buttons available on the full-size Launchkey model.
82pub struct RegularLaunchKeyButton(pub LaunchKeyButton);
83
84impl RegularLaunchKeyButton {
85    pub const SUPPORTED: [LaunchKeyButton; 17] = [
86        LaunchKeyButton::Shift,
87        LaunchKeyButton::PreviousTrack,
88        LaunchKeyButton::NextTrack,
89        LaunchKeyButton::EncoderMoveUp,
90        LaunchKeyButton::EncoderMoveDown,
91        LaunchKeyButton::PadBankUp,
92        LaunchKeyButton::PadBankDown,
93        LaunchKeyButton::SceneLaunch,
94        LaunchKeyButton::Function,
95        LaunchKeyButton::CaptureMIDI,
96        LaunchKeyButton::UndoRedo,
97        LaunchKeyButton::Quantise,
98        LaunchKeyButton::Metronome,
99        LaunchKeyButton::Stop,
100        LaunchKeyButton::Loop,
101        LaunchKeyButton::Play,
102        LaunchKeyButton::Record,
103    ];
104
105    /// Converts a `LaunchKeyButton` to a `RegularLaunchKeyButton` if it is supported on the regular model.
106    pub fn from_launchkey_button(button: LaunchKeyButton) -> Option<Self> {
107        if Self::SUPPORTED.contains(&button) {
108            Some(RegularLaunchKeyButton(button))
109        } else {
110            None
111        }
112    }
113}
114
115impl Deref for RegularLaunchKeyButton {
116    type Target = LaunchKeyButton;
117
118    fn deref(&self) -> &Self::Target {
119        &self.0
120    }
121}
122
123/// Represents the current state of a button — either pressed or released.
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125pub enum ButtonState {
126    Pressed,
127    Released,
128}
129
130impl TryFrom<ControlValue> for ButtonState {
131    type Error = ();
132
133    fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
134        match value.into() {
135            127 => Ok(ButtonState::Pressed),
136            0 => Ok(ButtonState::Released),
137            _ => Err(()),
138        }
139    }
140}
141
142/// A strongly-typed wrapper around brightness values (0–127), used for setting LED brightness.
143#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
144pub struct Brightness(u8);
145
146impl Brightness {
147    pub const MIN: u8 = 0x00;
148    pub const MAX: u8 = 0x7F;
149
150    /// Tries to create a new `Brightness`, returning `None` if out of range.
151    pub fn new(value: u8) -> Option<Self> {
152        if value <= Self::MAX {
153            Some(Self(value))
154        } else {
155            None
156        }
157    }
158
159    /// Returns the minimum brightness (off).
160    pub fn min() -> Self {
161        Self(Self::MIN)
162    }
163
164    /// Returns the maximum brightness (full brightness).
165    pub fn max() -> Self {
166        Self(Self::MAX)
167    }
168
169    /// Returns the inner `u8` value.
170    pub fn value(self) -> u8 {
171        self.0
172    }
173}
174
175impl TryFrom<u8> for Brightness {
176    type Error = &'static str;
177
178    /// Brightness must be in the range 0–127 (0x00–0x7F in HEX).
179    fn try_from(value: u8) -> Result<Self, Self::Error> {
180        if value <= 127 {
181            Ok(Brightness(value))
182        } else {
183            Err("Brightness must be in the range 0–127 (0x00–0x7F in HEX).")
184        }
185    }
186}