mirror of
https://github.com/OpenActionAPI/rust-elgato-streamdeck.git
synced 2026-10-28 09:44:56 +00:00
refactor: remove Mirabox device support in lieu of @4ndv's new mirajazz crate
This commit is contained in:
1 parent
ff8566546d
commit
03cd301ab9
8 files changed
+23
-809
No files matched your search
@@ -8,16 +8,6 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0086", MODE="0660",
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="008f", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0090", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="009a", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6667", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6670", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6672", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="5548", ATTR{idProduct}=="6674", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1001", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1010", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="1020", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0300", ATTR{idProduct}=="3002", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="6603", ATTR{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
@@ -29,16 +19,6 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0086", MODE="0660"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="008f", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0090", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="009a", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6667", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6670", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6672", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6674", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1001", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1010", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1020", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="3002", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="6603", ATTRS{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0060", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0063", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
@@ -50,16 +30,6 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="008f", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="0090", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0fd9", ATTR{idProduct}=="009a", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6667", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6670", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6672", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="5548", ATTR{idProduct}=="6674", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1001", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1010", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="1020", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="0300", ATTR{idProduct}=="3002", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTR{idVendor}=="6603", ATTR{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
@@ -71,13 +41,3 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="008f", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0090", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="009a", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6667", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6670", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6672", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5548", ATTRS{idProduct}=="6674", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1001", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1010", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="1020", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0300", ATTRS{idProduct}=="3002", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="6603", ATTRS{idProduct}=="1003", MODE="0660", TAG+="uaccess", GROUP="plugdev"
|
||||
@@ -63,7 +63,7 @@ if device.updated {
|
||||
- [x] Reading buttons with async
|
||||
|
||||
## Supported Devices
|
||||
As it stands, this library should support the following devices. Please note that non-Elgato devices are only supported by consumers of this library that enable the support for them.
|
||||
As it stands, this library should support the following devices.
|
||||
- Stream Deck Original
|
||||
- Stream Deck Original V2
|
||||
- Stream Deck XL
|
||||
@@ -74,13 +74,5 @@ As it stands, this library should support the following devices. Please note tha
|
||||
- Stream Deck Pedal
|
||||
- Stream Deck Plus (thanks to [node-elgato-stream-deck](https://github.com/Julusian/node-elgato-stream-deck))
|
||||
- Stream Deck Neo (thanks to [@ejiektpobehuk](https://github.com/ejiektpobehuk), [@AkechiShiro](https://github.com/AkechiShiro) and [node-elgato-stream-deck](https://github.com/Julusian/node-elgato-stream-deck))
|
||||
- Ajazz AKP153 (thanks to [@ZCube](https://github.com/ZCube))
|
||||
- Ajazz AKP153E (thanks to [@teras](https://github.com/teras))
|
||||
- Ajazz AKP153R (thanks to [@teras](https://github.com/teras), [@damnkrat](https://github.com/damnkrat) and [@4ndv](https://github.com/4ndv))
|
||||
- Ajazz AKP815 (thanks to [@teras](https://github.com/teras))
|
||||
- Ajazz AKP03 (thanks to [@4ndv](https://github.com/4ndv) and [@happyme531](https://github.com/happyme531))
|
||||
- Ajazz AKP03E (thanks to [@4ndv](https://github.com/4ndv) and [@geekosaurusR3x](https://github.com/geekosaurusR3x))
|
||||
- Ajazz AKP03R (thanks to [@4ndv](https://github.com/4ndv))
|
||||
- MiraBox HSV293S (thanks to [@czyz](https://github.com/czyz))
|
||||
- MiraBox DK0108D (thanks to [@ikegam](https://github.com/ikegam))
|
||||
- MiraBox N3EN (thanks to [@JensHeinrich](https://github.com/JensHeinrich))
|
||||
|
||||
Support for non-Elgato (Mirabox/Ajazz) devices has been removed in v0.11. If you wish to use these devices, please use the `mirajazz` crate, or use v0.10.2 of this crate.
|
||||
@@ -11,7 +11,7 @@ async fn main() {
|
||||
match new_hidapi() {
|
||||
Ok(hid) => {
|
||||
// Refresh device list
|
||||
for (kind, serial) in list_devices(&hid, false) {
|
||||
for (kind, serial) in list_devices(&hid) {
|
||||
println!("{:?} {} {}", kind, serial, kind.product_id());
|
||||
|
||||
// Connect to the device
|
||||
@@ -26,8 +26,6 @@ async fn main() {
|
||||
let image = open("no-place-like-localhost.jpg").unwrap();
|
||||
let alternative = image.grayscale().brighten(-50);
|
||||
|
||||
// device.set_logo_image(image.clone()).await.unwrap();
|
||||
|
||||
println!("Key count: {}", kind.key_count());
|
||||
// Write it to the device
|
||||
for i in 0..kind.key_count() as u8 {
|
||||
@@ -134,8 +132,6 @@ async fn main() {
|
||||
}
|
||||
|
||||
drop(reader);
|
||||
|
||||
device.shutdown().await.ok();
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Failed to create HidApi instance: {}", e),
|
||||
|
||||
@@ -11,7 +11,7 @@ fn main() {
|
||||
match new_hidapi() {
|
||||
Ok(hid) => {
|
||||
// Refresh device list
|
||||
for (kind, serial) in list_devices(&hid, false) {
|
||||
for (kind, serial) in list_devices(&hid) {
|
||||
println!("{:?} {} {}", kind, serial, kind.product_id());
|
||||
|
||||
// Connect to the device
|
||||
@@ -24,8 +24,6 @@ fn main() {
|
||||
// Use image-rs to load an image
|
||||
let image = open("no-place-like-localhost.jpg").unwrap();
|
||||
|
||||
// device.set_logo_image(image.clone()).unwrap();
|
||||
|
||||
println!("Key count: {}", kind.key_count());
|
||||
// Write it to the device
|
||||
for i in 0..kind.key_count() as u8 {
|
||||
@@ -112,8 +110,6 @@ fn main() {
|
||||
|
||||
drop(reader);
|
||||
}
|
||||
|
||||
device.shutdown().ok();
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Failed to create HidApi instance: {}", e),
|
||||
|
||||
+4
-38
@@ -23,8 +23,8 @@ pub fn refresh_device_list_async(hidapi: &mut HidApi) -> HidResult<()> {
|
||||
/// can be safely ran inside [multi_thread](tokio::runtime::Builder::new_multi_thread) runtime
|
||||
///
|
||||
/// **WARNING:** To refresh the list, use [refresh_device_list]
|
||||
pub fn list_devices_async(hidapi: &HidApi, only_elgato: bool) -> Vec<(Kind, String)> {
|
||||
block_in_place(move || list_devices(hidapi, only_elgato))
|
||||
pub fn list_devices_async(hidapi: &HidApi) -> Vec<(Kind, String)> {
|
||||
block_in_place(move || list_devices(hidapi))
|
||||
}
|
||||
|
||||
/// Stream Deck interface suitable to be used in async, uses [block_in_place](block_in_place)
|
||||
@@ -156,36 +156,12 @@ impl AsyncStreamDeck {
|
||||
block_in_place(move || device.write_image(key, &image))
|
||||
}
|
||||
|
||||
/// Set logo image
|
||||
pub async fn set_logo_image(&self, image: DynamicImage) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
block_in_place(move || device.set_logo_image(image))
|
||||
}
|
||||
|
||||
/// Sets specified touch point's led strip color
|
||||
pub async fn set_touchpoint_color(&self, point: u8, red: u8, green: u8, blue: u8) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
block_in_place(move || device.set_touchpoint_color(point, red, green, blue))
|
||||
}
|
||||
|
||||
/// Sleeps the device
|
||||
pub async fn sleep(&self) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
block_in_place(move || device.sleep())
|
||||
}
|
||||
|
||||
/// Make periodic events to the device, to keep it alive
|
||||
pub async fn keep_alive(&self) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
block_in_place(move || device.keep_alive())
|
||||
}
|
||||
|
||||
/// Shutdown the device
|
||||
pub async fn shutdown(&self) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
block_in_place(move || device.shutdown())
|
||||
}
|
||||
|
||||
/// Flushes the button's image to the device
|
||||
pub async fn flush(&self) -> Result<(), StreamDeckError> {
|
||||
let device = self.device.lock().await;
|
||||
@@ -221,12 +197,7 @@ impl AsyncDeviceStateReader {
|
||||
match input {
|
||||
StreamDeckInput::ButtonStateChange(buttons) => {
|
||||
for (index, (their, mine)) in zip(buttons.iter(), my_states.buttons.iter()).enumerate() {
|
||||
if self.device.kind.is_mirabox() && self.device.kind != Kind::MiraBoxN3EN {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::ButtonDown(index as u8));
|
||||
updates.push(DeviceStateUpdate::ButtonUp(index as u8));
|
||||
}
|
||||
} else if *their != *mine {
|
||||
if *their != *mine {
|
||||
if index < self.device.kind.key_count() as usize {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::ButtonDown(index as u8));
|
||||
@@ -246,12 +217,7 @@ impl AsyncDeviceStateReader {
|
||||
|
||||
StreamDeckInput::EncoderStateChange(encoders) => {
|
||||
for (index, (their, mine)) in zip(encoders.iter(), my_states.encoders.iter()).enumerate() {
|
||||
if self.device.kind.is_mirabox() && self.device.kind != Kind::MiraBoxN3EN {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
|
||||
updates.push(DeviceStateUpdate::EncoderUp(index as u8));
|
||||
}
|
||||
} else if *their != *mine {
|
||||
if *their != *mine {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
|
||||
} else {
|
||||
|
||||
+2
-170
@@ -22,46 +22,7 @@ pub const PID_STREAMDECK_PEDAL: u16 = 0x0086;
|
||||
/// Product ID of Stream Deck Plus
|
||||
pub const PID_STREAMDECK_PLUS: u16 = 0x0084;
|
||||
|
||||
/// A Mirabox vendor ID
|
||||
pub const MIRABOX_VENDOR_ID_1: u16 = 0x5548;
|
||||
|
||||
/// Product ID of Ajazz AKP153
|
||||
pub const PID_AJAZZ_AKP153: u16 = 0x6674;
|
||||
|
||||
/// Product ID of Ajazz AKP815
|
||||
pub const PID_AJAZZ_AKP815: u16 = 0x6672;
|
||||
|
||||
/// Product ID of the "FHOOU" (front label) and "MiraBox HSV293S" (rear label). Seems just like an AKP153.
|
||||
pub const PID_MIRABOX_HSV293S: u16 = 0x6670;
|
||||
|
||||
/// Product ID of MiraBox DK0108D
|
||||
pub const PID_MIRABOX_DK0108D: u16 = 0x6667;
|
||||
|
||||
/// A Mirabox vendor ID
|
||||
pub const MIRABOX_VENDOR_ID_2: u16 = 0x0300;
|
||||
|
||||
/// Product ID of Ajazz AKP153E
|
||||
pub const PID_AJAZZ_AKP153E: u16 = 0x1010;
|
||||
|
||||
/// Product ID of Ajazz AKP153R
|
||||
pub const PID_AJAZZ_AKP153R: u16 = 0x1020;
|
||||
|
||||
/// Product ID of Ajazz AKP03
|
||||
pub const PID_AJAZZ_AKP03: u16 = 0x1001;
|
||||
|
||||
/// Product ID of Ajazz AKP03E
|
||||
pub const PID_AJAZZ_AKP03E: u16 = 0x3002;
|
||||
|
||||
/// Product ID of Ajazz AKP03R
|
||||
pub const PID_AJAZZ_AKP03R: u16 = 0x1003;
|
||||
|
||||
/// A Mirabox vendor ID
|
||||
pub const MIRABOX_VENDOR_ID_3: u16 = 0x6603;
|
||||
|
||||
/// Product ID of the "FHOOU" (front label) and "MiraBox N3" (rear label) and "MiraBox N3EN" as per Mirabox's repository. Seems just like an AKP03.
|
||||
pub const PID_MIRABOX_N3EN: u16 = 0x1003;
|
||||
|
||||
const RECOGNIZED_VENDORS: [u16; 4] = [ELGATO_VENDOR_ID, MIRABOX_VENDOR_ID_1, MIRABOX_VENDOR_ID_2, MIRABOX_VENDOR_ID_3];
|
||||
const RECOGNIZED_VENDORS: [u16; 1] = [ELGATO_VENDOR_ID];
|
||||
|
||||
/// Returns true for vendors IDs that are recognized by the library
|
||||
pub fn is_vendor_familiar(vendor: &u16) -> bool {
|
||||
@@ -91,26 +52,6 @@ pub enum Kind {
|
||||
Pedal,
|
||||
/// Stream Deck Plus
|
||||
Plus,
|
||||
/// Ajazz AKP153
|
||||
Akp153,
|
||||
/// Ajazz AKP153E
|
||||
Akp153E,
|
||||
/// Ajazz AKP153R
|
||||
Akp153R,
|
||||
/// Ajazz AKP815
|
||||
Akp815,
|
||||
/// Ajazz AKP03
|
||||
Akp03,
|
||||
/// Ajazz AKP03E
|
||||
Akp03E,
|
||||
/// Ajazz AKP03R
|
||||
Akp03R,
|
||||
/// MiraBox HSV293S
|
||||
MiraBoxHSV293S,
|
||||
/// MiraBox DK0108D
|
||||
MiraBoxDK0108D,
|
||||
/// MiraBox N3EN
|
||||
MiraBoxN3EN,
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
@@ -130,29 +71,6 @@ impl Kind {
|
||||
PID_STREAMDECK_PLUS => Some(Kind::Plus),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
MIRABOX_VENDOR_ID_1 => match pid {
|
||||
PID_AJAZZ_AKP153 => Some(Kind::Akp153),
|
||||
PID_AJAZZ_AKP815 => Some(Kind::Akp815),
|
||||
PID_MIRABOX_HSV293S => Some(Kind::MiraBoxHSV293S),
|
||||
PID_MIRABOX_DK0108D => Some(Kind::MiraBoxDK0108D),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
MIRABOX_VENDOR_ID_2 => match pid {
|
||||
PID_AJAZZ_AKP153E => Some(Kind::Akp153E),
|
||||
PID_AJAZZ_AKP153R => Some(Kind::Akp153R),
|
||||
PID_AJAZZ_AKP03 => Some(Kind::Akp03),
|
||||
PID_AJAZZ_AKP03E => Some(Kind::Akp03E),
|
||||
PID_AJAZZ_AKP03R => Some(Kind::Akp03R),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
MIRABOX_VENDOR_ID_3 => match pid {
|
||||
PID_MIRABOX_N3EN => Some(Kind::MiraBoxN3EN),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -170,16 +88,6 @@ impl Kind {
|
||||
Kind::Neo => PID_STREAMDECK_NEO,
|
||||
Kind::Pedal => PID_STREAMDECK_PEDAL,
|
||||
Kind::Plus => PID_STREAMDECK_PLUS,
|
||||
Kind::Akp153 => PID_AJAZZ_AKP153,
|
||||
Kind::Akp153E => PID_AJAZZ_AKP153E,
|
||||
Kind::Akp153R => PID_AJAZZ_AKP153R,
|
||||
Kind::Akp815 => PID_AJAZZ_AKP815,
|
||||
Kind::Akp03 => PID_AJAZZ_AKP03,
|
||||
Kind::Akp03E => PID_AJAZZ_AKP03E,
|
||||
Kind::Akp03R => PID_AJAZZ_AKP03R,
|
||||
Kind::MiraBoxHSV293S => PID_MIRABOX_HSV293S,
|
||||
Kind::MiraBoxDK0108D => PID_MIRABOX_DK0108D,
|
||||
Kind::MiraBoxN3EN => PID_MIRABOX_N3EN,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,16 +104,6 @@ impl Kind {
|
||||
Kind::Neo => ELGATO_VENDOR_ID,
|
||||
Kind::Pedal => ELGATO_VENDOR_ID,
|
||||
Kind::Plus => ELGATO_VENDOR_ID,
|
||||
Kind::Akp153 => MIRABOX_VENDOR_ID_1,
|
||||
Kind::Akp153E => MIRABOX_VENDOR_ID_2,
|
||||
Kind::Akp153R => MIRABOX_VENDOR_ID_2,
|
||||
Kind::Akp815 => MIRABOX_VENDOR_ID_1,
|
||||
Kind::Akp03 => MIRABOX_VENDOR_ID_2,
|
||||
Kind::Akp03E => MIRABOX_VENDOR_ID_2,
|
||||
Kind::Akp03R => MIRABOX_VENDOR_ID_2,
|
||||
Kind::MiraBoxHSV293S => MIRABOX_VENDOR_ID_1,
|
||||
Kind::MiraBoxDK0108D => MIRABOX_VENDOR_ID_1,
|
||||
Kind::MiraBoxN3EN => MIRABOX_VENDOR_ID_3,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,10 +115,6 @@ impl Kind {
|
||||
Kind::Xl | Kind::XlV2 => 32,
|
||||
Kind::Pedal => 3,
|
||||
Kind::Neo | Kind::Plus => 8,
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 15 + 3,
|
||||
Kind::Akp815 => 15,
|
||||
Kind::Akp03 | Kind::Akp03E | Kind::Akp03R | Kind::MiraBoxN3EN => 6 + 3,
|
||||
Kind::MiraBoxDK0108D => 12,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +126,6 @@ impl Kind {
|
||||
Kind::Xl | Kind::XlV2 => 4,
|
||||
Kind::Pedal => 1,
|
||||
Kind::Neo | Kind::Plus => 2,
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 3,
|
||||
Kind::Akp815 => 5,
|
||||
Kind::Akp03 | Kind::Akp03E | Kind::Akp03R | Kind::MiraBoxN3EN => 3,
|
||||
Kind::MiraBoxDK0108D => 3,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,10 +137,6 @@ impl Kind {
|
||||
Kind::Xl | Kind::XlV2 => 8,
|
||||
Kind::Pedal => 3,
|
||||
Kind::Neo | Kind::Plus => 4,
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => 6,
|
||||
Kind::Akp815 => 3,
|
||||
Kind::Akp03 | Kind::Akp03E | Kind::Akp03R | Kind::MiraBoxN3EN => 3,
|
||||
Kind::MiraBoxDK0108D => 4,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +144,6 @@ impl Kind {
|
||||
pub fn encoder_count(&self) -> u8 {
|
||||
match self {
|
||||
Kind::Plus => 4,
|
||||
Kind::Akp03 | Kind::Akp03E | Kind::Akp03R | Kind::MiraBoxN3EN => 3,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
@@ -276,9 +161,6 @@ impl Kind {
|
||||
match self {
|
||||
Kind::Plus => Some((800, 100)),
|
||||
Kind::Neo => Some((248, 58)),
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => Some((854, 480)),
|
||||
Kind::Akp815 => Some((800, 480)),
|
||||
Kind::MiraBoxDK0108D => Some((800, 480)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -332,41 +214,6 @@ impl Kind {
|
||||
},
|
||||
|
||||
Kind::Pedal => ImageFormat::default(),
|
||||
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => ImageFormat {
|
||||
mode: ImageMode::JPEG,
|
||||
size: (85, 85),
|
||||
rotation: ImageRotation::Rot90,
|
||||
mirror: ImageMirroring::Both,
|
||||
},
|
||||
|
||||
Kind::Akp815 => ImageFormat {
|
||||
mode: ImageMode::JPEG,
|
||||
size: (100, 100),
|
||||
rotation: ImageRotation::Rot180,
|
||||
mirror: ImageMirroring::None,
|
||||
},
|
||||
|
||||
Kind::Akp03 | Kind::Akp03E | Kind::Akp03R => ImageFormat {
|
||||
mode: ImageMode::JPEG,
|
||||
size: (60, 60),
|
||||
rotation: ImageRotation::Rot0,
|
||||
mirror: ImageMirroring::None,
|
||||
},
|
||||
|
||||
Kind::MiraBoxN3EN => ImageFormat {
|
||||
mode: ImageMode::JPEG,
|
||||
size: (60, 60),
|
||||
rotation: ImageRotation::Rot90,
|
||||
mirror: ImageMirroring::None,
|
||||
},
|
||||
|
||||
Kind::MiraBoxDK0108D => ImageFormat {
|
||||
mode: ImageMode::JPEG,
|
||||
size: (72, 72),
|
||||
rotation: ImageRotation::Rot180,
|
||||
mirror: ImageMirroring::Both,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,24 +347,9 @@ impl Kind {
|
||||
0xd9,
|
||||
],
|
||||
|
||||
_ => vec![],
|
||||
Kind::Pedal => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true for Mirabox devices with 512 byte packet length
|
||||
pub fn is_mirabox_v1(&self) -> bool {
|
||||
matches!(self, Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::Akp815 | Kind::MiraBoxHSV293S | Kind::MiraBoxDK0108D)
|
||||
}
|
||||
|
||||
/// Returns true for Mirabox devices with 1024 byte packet length
|
||||
pub fn is_mirabox_v2(&self) -> bool {
|
||||
matches!(self, Kind::Akp03 | Kind::Akp03E | Kind::Akp03R | Kind::MiraBoxN3EN)
|
||||
}
|
||||
|
||||
/// Returns true for Mirabox devices
|
||||
pub fn is_mirabox(&self) -> bool {
|
||||
self.is_mirabox_v1() || self.is_mirabox_v2()
|
||||
}
|
||||
}
|
||||
|
||||
/// Image format used by the Stream Deck
|
||||
|
||||
+12
-395
@@ -12,7 +12,6 @@ use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::iter::zip;
|
||||
use std::str::Utf8Error;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{Arc, Mutex, PoisonError};
|
||||
use std::time::Duration;
|
||||
@@ -22,10 +21,7 @@ use hidapi::{HidApi, HidDevice, HidError, HidResult};
|
||||
use image::{DynamicImage, ImageError};
|
||||
|
||||
use crate::info::{is_vendor_familiar, Kind};
|
||||
use crate::util::{
|
||||
ajazz03_read_input, mirabox_extend_packet, ajazz153_to_elgato_input, elgato_to_ajazz153, extract_str, flip_key_index, get_feature_report, inverse_key_index, read_button_states, read_data,
|
||||
read_encoder_input, read_lcd_input, send_feature_report, write_data,
|
||||
};
|
||||
use crate::util::{extract_str, flip_key_index, get_feature_report, read_button_states, read_data, read_encoder_input, read_lcd_input, send_feature_report, write_data};
|
||||
|
||||
/// Various information about Stream Deck devices
|
||||
pub mod info;
|
||||
@@ -57,11 +53,11 @@ pub fn refresh_device_list(hidapi: &mut HidApi) -> HidResult<()> {
|
||||
/// Returns a list of devices as (Kind, Serial Number) that could be found using HidApi.
|
||||
///
|
||||
/// **WARNING:** To refresh the list, use [refresh_device_list]
|
||||
pub fn list_devices(hidapi: &HidApi, only_elgato: bool) -> Vec<(Kind, String)> {
|
||||
pub fn list_devices(hidapi: &HidApi) -> Vec<(Kind, String)> {
|
||||
hidapi
|
||||
.device_list()
|
||||
.filter_map(|d| {
|
||||
if (only_elgato && d.vendor_id() != info::ELGATO_VENDOR_ID) || !is_vendor_familiar(&d.vendor_id()) {
|
||||
if !is_vendor_familiar(&d.vendor_id()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -116,8 +112,6 @@ pub struct StreamDeck {
|
||||
device: HidDevice,
|
||||
/// Temporarily cache the image before sending it to the device
|
||||
image_cache: RwLock<Vec<ImageCache>>,
|
||||
/// Device needs to be initialized
|
||||
initialized: AtomicBool,
|
||||
}
|
||||
|
||||
struct ImageCache {
|
||||
@@ -135,7 +129,6 @@ impl StreamDeck {
|
||||
kind,
|
||||
device,
|
||||
image_cache: RwLock::new(vec![]),
|
||||
initialized: false.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -160,20 +153,6 @@ impl StreamDeck {
|
||||
/// Returns serial number of the device
|
||||
pub fn serial_number(&self) -> Result<String, StreamDeckError> {
|
||||
match self.kind {
|
||||
kind if kind.is_mirabox() => {
|
||||
let serial = self.device.get_serial_number_string()?;
|
||||
match serial {
|
||||
Some(serial) => {
|
||||
if serial.is_empty() {
|
||||
Ok("Unknown".to_string())
|
||||
} else {
|
||||
Ok(serial)
|
||||
}
|
||||
}
|
||||
None => Ok("Unknown".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
Kind::Original | Kind::Mini => {
|
||||
let bytes = get_feature_report(&self.device, 0x03, 17)?;
|
||||
Ok(extract_str(&bytes[5..])?)
|
||||
@@ -200,11 +179,6 @@ impl StreamDeck {
|
||||
Ok(extract_str(&bytes[5..])?)
|
||||
}
|
||||
|
||||
kind if kind.is_mirabox() => {
|
||||
let bytes = get_feature_report(&self.device, 0x01, 20)?;
|
||||
Ok(extract_str(&bytes[0..])?)
|
||||
}
|
||||
|
||||
_ => {
|
||||
let bytes = get_feature_report(&self.device, 0x05, 32)?;
|
||||
Ok(extract_str(&bytes[6..])?)
|
||||
@@ -212,30 +186,8 @@ impl StreamDeck {
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the device
|
||||
fn initialize(&self) -> Result<(), StreamDeckError> {
|
||||
if self.initialized.load(Ordering::Acquire) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.initialized.store(true, Ordering::Release);
|
||||
|
||||
if self.kind.is_mirabox() {
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x44, 0x49, 0x53];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x00, 0x00, 0x00, 0x00];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reads all possible input from Stream Deck device
|
||||
pub fn read_input(&self, timeout: Option<Duration>) -> Result<StreamDeckInput, StreamDeckError> {
|
||||
self.initialize()?;
|
||||
match &self.kind {
|
||||
Kind::Plus => {
|
||||
let data = read_data(&self.device, 14.max(5 + self.kind.encoder_count() as usize), timeout)?;
|
||||
@@ -255,51 +207,6 @@ impl StreamDeck {
|
||||
}
|
||||
}
|
||||
|
||||
kind if kind.is_mirabox_v1() => {
|
||||
let data = read_data(&self.device, 512, timeout)?;
|
||||
|
||||
if data[0] == 0 {
|
||||
return Ok(StreamDeckInput::NoData);
|
||||
}
|
||||
|
||||
let mut states = vec![0x01];
|
||||
states.extend(vec![0u8; (self.kind.key_count() + 1) as usize]);
|
||||
|
||||
if data[9] != 0 {
|
||||
let key = match self.kind {
|
||||
Kind::Akp815 => inverse_key_index(&self.kind, data[9] - 1),
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => ajazz153_to_elgato_input(&self.kind, data[9] - 1),
|
||||
Kind::MiraBoxDK0108D => data[9] - 1,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
// This device can slide its view, and as it does, it sends events for keys 48, 49 and 50.
|
||||
// This functionality is not yet implemented in this library. So, for now, drop related events.
|
||||
if self.kind == Kind::MiraBoxDK0108D && key > self.kind.key_count() {
|
||||
return Ok(StreamDeckInput::NoData);
|
||||
}
|
||||
|
||||
states[(key + 1) as usize] = 0x1u8;
|
||||
}
|
||||
|
||||
Ok(StreamDeckInput::ButtonStateChange(read_button_states(&self.kind, &states)))
|
||||
}
|
||||
|
||||
kind if kind.is_mirabox_v2() => {
|
||||
let data = read_data(&self.device, 512, timeout)?;
|
||||
|
||||
if data[0] == 0 {
|
||||
return Ok(StreamDeckInput::NoData);
|
||||
}
|
||||
|
||||
if self.kind == Kind::MiraBoxN3EN {
|
||||
ajazz03_read_input(&self.kind, data[9], data[10])
|
||||
} else {
|
||||
// Devices not returning a state for the input
|
||||
ajazz03_read_input(&self.kind, data[9], 0x01)
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
let data = match self.kind {
|
||||
Kind::Original | Kind::Mini | Kind::MiniMk2 => read_data(&self.device, 1 + self.kind.key_count() as usize, timeout),
|
||||
@@ -317,7 +224,6 @@ impl StreamDeck {
|
||||
|
||||
/// Resets the device
|
||||
pub fn reset(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
match self.kind {
|
||||
Kind::Original | Kind::Mini | Kind::MiniMk2 => {
|
||||
let mut buf = vec![0x0B, 0x63];
|
||||
@@ -327,12 +233,6 @@ impl StreamDeck {
|
||||
Ok(send_feature_report(&self.device, buf.as_slice())?)
|
||||
}
|
||||
|
||||
kind if kind.is_mirabox() => {
|
||||
self.set_brightness(100)?;
|
||||
self.clear_all_button_images()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
_ => {
|
||||
let mut buf = vec![0x03, 0x02];
|
||||
|
||||
@@ -345,7 +245,6 @@ impl StreamDeck {
|
||||
|
||||
/// Sets brightness of the device, value range is 0 - 100
|
||||
pub fn set_brightness(&self, percent: u8) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
let percent = percent.clamp(0, 100);
|
||||
|
||||
match self.kind {
|
||||
@@ -357,16 +256,6 @@ impl StreamDeck {
|
||||
Ok(send_feature_report(&self.device, buf.as_slice())?)
|
||||
}
|
||||
|
||||
kind if kind.is_mirabox() => {
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x49, 0x47, 0x00, 0x00, percent];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
_ => {
|
||||
let mut buf = vec![0x03, 0x08, percent];
|
||||
|
||||
@@ -382,43 +271,12 @@ impl StreamDeck {
|
||||
return Err(StreamDeckError::InvalidKeyIndex);
|
||||
}
|
||||
|
||||
let key = if let Kind::Original = self.kind {
|
||||
flip_key_index(&self.kind, key)
|
||||
} else if let Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S = self.kind {
|
||||
elgato_to_ajazz153(&self.kind, key)
|
||||
} else if let Kind::Akp815 = self.kind {
|
||||
inverse_key_index(&self.kind, key)
|
||||
} else {
|
||||
key
|
||||
};
|
||||
let key = if let Kind::Original = self.kind { flip_key_index(&self.kind, key) } else { key };
|
||||
|
||||
if !self.kind.is_visual() {
|
||||
return Err(StreamDeckError::NoScreen);
|
||||
}
|
||||
|
||||
if self.kind.is_mirabox() {
|
||||
let mut buf = vec![
|
||||
0x00,
|
||||
0x43,
|
||||
0x52,
|
||||
0x54,
|
||||
0x00,
|
||||
0x00,
|
||||
0x42,
|
||||
0x41,
|
||||
0x54,
|
||||
0x00,
|
||||
0x00,
|
||||
(image_data.len() >> 8) as u8,
|
||||
image_data.len() as u8,
|
||||
key + 1,
|
||||
];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
}
|
||||
|
||||
self.write_image_data_reports(
|
||||
image_data,
|
||||
WriteImageParameters::for_key(self.kind, image_data.len()),
|
||||
@@ -427,8 +285,6 @@ impl StreamDeck {
|
||||
|
||||
Kind::Mini | Kind::MiniMk2 => vec![0x02, 0x01, page_number as u8, 0, if last_package { 1 } else { 0 }, key + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
|
||||
kind if kind.is_mirabox() => vec![0x00],
|
||||
|
||||
_ => vec![
|
||||
0x02,
|
||||
0x07,
|
||||
@@ -447,15 +303,7 @@ impl StreamDeck {
|
||||
/// Writes image data to Stream Deck device, changes must be flushed with `.flush()` before
|
||||
/// they will appear on the device!
|
||||
pub fn write_image(&self, key: u8, image_data: &[u8]) -> Result<(), StreamDeckError> {
|
||||
// Key count is 9 for AKP03x, but only the first 6 (0-5) have screens, so don't output anything for keys 6, 7, 8
|
||||
if matches!(self.kind, Kind::Akp03 | Kind::Akp03E | Kind::Akp03R) && key >= 6 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let cache_entry = ImageCache {
|
||||
key,
|
||||
image_data: image_data.to_vec(), // Convert &[u8] to Vec<u8>
|
||||
};
|
||||
let cache_entry = ImageCache { key, image_data: image_data.to_vec() };
|
||||
|
||||
self.image_cache.write()?.push(cache_entry);
|
||||
|
||||
@@ -465,7 +313,6 @@ impl StreamDeck {
|
||||
/// Writes image data to Stream Deck device's lcd strip/screen as region.
|
||||
/// Only Stream Deck Plus supports writing LCD regions, for Stream Deck Neo use write_lcd_fill
|
||||
pub fn write_lcd(&self, x: u16, y: u16, rect: &ImageRect) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
match self.kind {
|
||||
Kind::Plus => (),
|
||||
_ => return Err(StreamDeckError::UnsupportedOperation),
|
||||
@@ -509,7 +356,6 @@ impl StreamDeck {
|
||||
/// device.write_lcd_fill(&image_data);
|
||||
/// ```
|
||||
pub fn write_lcd_fill(&self, image_data: &[u8]) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
match self.kind {
|
||||
Kind::Neo => self.write_image_data_reports(
|
||||
image_data,
|
||||
@@ -570,184 +416,28 @@ impl StreamDeck {
|
||||
/// Sets button's image to blank, changes must be flushed with `.flush()` before
|
||||
/// they will appear on the device!
|
||||
pub fn clear_button_image(&self, key: u8) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if self.kind.is_mirabox() {
|
||||
let key = match self.kind {
|
||||
Kind::Akp815 => inverse_key_index(&self.kind, key),
|
||||
Kind::Akp153 | Kind::Akp153E | Kind::Akp153R | Kind::MiraBoxHSV293S => elgato_to_ajazz153(&self.kind, key),
|
||||
_ => key,
|
||||
};
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x00, if key == 0xff { 0xff } else { key + 1 }];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.send_image(key, &self.kind.blank_image())?)
|
||||
}
|
||||
self.send_image(key, &self.kind.blank_image())
|
||||
}
|
||||
|
||||
/// Sets blank images to every button, changes must be flushed with `.flush()` before
|
||||
/// they will appear on the device!
|
||||
pub fn clear_all_button_images(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
match self.kind {
|
||||
kind if kind.is_mirabox_v1() => self.clear_button_image(0xff),
|
||||
kind if kind.is_mirabox_v2() => {
|
||||
self.clear_button_image(0xFF)?;
|
||||
|
||||
// Mirabox "v2" requires STP to commit clearing the screen
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x53, 0x54, 0x50];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
for i in 0..self.kind.key_count() {
|
||||
self.clear_button_image(i)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
for i in 0..self.kind.key_count() {
|
||||
self.clear_button_image(i)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets specified button's image, changes must be flushed with `.flush()` before
|
||||
/// they will appear on the device!
|
||||
pub fn set_button_image(&self, key: u8, image: DynamicImage) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
let image_data = convert_image(self.kind, image)?;
|
||||
self.write_image(key, &image_data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set logo image
|
||||
pub fn set_logo_image(&self, image: DynamicImage) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if !self.kind.is_mirabox() {
|
||||
return Err(StreamDeckError::UnsupportedOperation);
|
||||
}
|
||||
|
||||
if self.kind.lcd_strip_size().is_none() {
|
||||
return Err(StreamDeckError::UnsupportedOperation);
|
||||
}
|
||||
// 854 * 480 * 3
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x4c, 0x4f, 0x47, 0x00, 0x12, 0xc3, 0xc0, 0x01];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
let mut image_buffer: DynamicImage = DynamicImage::new_rgb8(854, 480);
|
||||
|
||||
let ratio = 854.0 / 480.0;
|
||||
|
||||
let mode = "cover";
|
||||
|
||||
match mode {
|
||||
"contain" => {
|
||||
let (image_w, image_h) = (image.width(), image.height());
|
||||
let image_ratio = image_w as f32 / image_h as f32;
|
||||
|
||||
let (ws, hs) = if image_ratio > ratio {
|
||||
(854, (854.0 / image_ratio) as u32)
|
||||
} else {
|
||||
((480.0 * image_ratio) as u32, 480)
|
||||
};
|
||||
|
||||
let resized_image = image.resize(ws, hs, image::imageops::FilterType::Nearest);
|
||||
image::imageops::overlay(
|
||||
&mut image_buffer,
|
||||
&resized_image,
|
||||
((854 - resized_image.width()) / 2) as i64,
|
||||
((480 - resized_image.height()) / 2) as i64,
|
||||
);
|
||||
}
|
||||
"cover" => {
|
||||
let resized_image = image.resize_to_fill(854, 480, image::imageops::FilterType::Nearest);
|
||||
image::imageops::overlay(
|
||||
&mut image_buffer,
|
||||
&resized_image,
|
||||
((854 - resized_image.width()) / 2) as i64,
|
||||
((480 - resized_image.height()) / 2) as i64,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let (image_w, image_h) = (image.width(), image.height());
|
||||
let image_ratio = image_w as f32 / image_h as f32;
|
||||
|
||||
let (ws, hs) = if image_ratio > ratio {
|
||||
((480.0 * image_ratio) as u32, 480)
|
||||
} else {
|
||||
(854, (854.0 / image_ratio) as u32)
|
||||
};
|
||||
|
||||
let resized_image = image.resize(ws, hs, image::imageops::FilterType::Nearest);
|
||||
image::imageops::overlay(
|
||||
&mut image_buffer,
|
||||
&resized_image,
|
||||
((854 - resized_image.width()) / 2) as i64,
|
||||
((480 - resized_image.height()) / 2) as i64,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut image_data = image_buffer.rotate90().fliph().flipv().into_rgb8().to_vec();
|
||||
for x in (0..image_data.len()).step_by(3) {
|
||||
(image_data[x], image_data[x + 2]) = (image_data[x + 2], image_data[x])
|
||||
}
|
||||
|
||||
let image_report_length = match self.kind {
|
||||
Kind::Original => 8191,
|
||||
kind if kind.is_mirabox_v1() => 513,
|
||||
kind if kind.is_mirabox_v2() => 1025,
|
||||
_ => 1024,
|
||||
};
|
||||
|
||||
let image_report_header_length = match self.kind {
|
||||
Kind::Original | Kind::Mini | Kind::MiniMk2 => 16,
|
||||
kind if kind.is_mirabox() => 1,
|
||||
_ => 8,
|
||||
};
|
||||
|
||||
let image_report_payload_length = match self.kind {
|
||||
Kind::Original => image_data.len() / 2,
|
||||
_ => image_report_length - image_report_header_length,
|
||||
};
|
||||
|
||||
let mut page_number = 0;
|
||||
let mut bytes_remaining = image_data.len();
|
||||
|
||||
while bytes_remaining > 0 {
|
||||
let this_length = bytes_remaining.min(image_report_payload_length);
|
||||
let bytes_sent = page_number * image_report_payload_length;
|
||||
|
||||
// Create buffer with Report ID as first byte
|
||||
let mut buf: Vec<u8> = vec![0x00];
|
||||
|
||||
// Selecting header based on device
|
||||
buf.extend(&image_data[bytes_sent..bytes_sent + this_length]);
|
||||
|
||||
// Adding padding
|
||||
buf.extend(vec![0u8; image_report_length - buf.len()]);
|
||||
|
||||
write_data(&self.device, &buf)?;
|
||||
|
||||
bytes_remaining -= this_length;
|
||||
page_number += 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets specified touch point's led strip color
|
||||
pub fn set_touchpoint_color(&self, point: u8, red: u8, green: u8, blue: u8) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
if point >= self.kind.touchpoint_count() {
|
||||
return Err(StreamDeckError::InvalidTouchPointIndex);
|
||||
}
|
||||
@@ -761,61 +451,9 @@ impl StreamDeck {
|
||||
Ok(send_feature_report(&self.device, buf.as_slice())?)
|
||||
}
|
||||
|
||||
/// Sleeps the device
|
||||
pub fn sleep(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if !self.kind.is_mirabox() {
|
||||
return Err(StreamDeckError::UnsupportedOperation);
|
||||
}
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x48, 0x41, 0x4e];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Make periodic events to the device, to keep it alive
|
||||
pub fn keep_alive(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if !self.kind.is_mirabox() {
|
||||
return Err(StreamDeckError::UnsupportedOperation);
|
||||
}
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shutdown the device
|
||||
pub fn shutdown(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if !self.kind.is_mirabox() {
|
||||
return Err(StreamDeckError::UnsupportedOperation);
|
||||
}
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x43, 0x4c, 0x45, 0x00, 0x00, 0x44, 0x43];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x48, 0x41, 0x4E];
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Flushes the button's image to the device
|
||||
pub fn flush(&self) -> Result<(), StreamDeckError> {
|
||||
self.initialize()?;
|
||||
|
||||
if self.image_cache.write()?.is_empty() {
|
||||
if self.image_cache.read()?.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -823,14 +461,6 @@ impl StreamDeck {
|
||||
self.send_image(image.key, &image.image_data)?;
|
||||
}
|
||||
|
||||
if self.kind.is_mirabox() {
|
||||
let mut buf = vec![0x00, 0x43, 0x52, 0x54, 0x00, 0x00, 0x53, 0x54, 0x50];
|
||||
|
||||
mirabox_extend_packet(&self.kind, &mut buf);
|
||||
|
||||
write_data(&self.device, buf.as_slice())?;
|
||||
}
|
||||
|
||||
self.image_cache.write()?.clear();
|
||||
|
||||
Ok(())
|
||||
@@ -890,14 +520,11 @@ impl WriteImageParameters {
|
||||
pub fn for_key(kind: Kind, image_data_len: usize) -> Self {
|
||||
let image_report_length = match kind {
|
||||
Kind::Original => 8191,
|
||||
kind if kind.is_mirabox_v1() => 513,
|
||||
kind if kind.is_mirabox_v2() => 1025,
|
||||
_ => 1024,
|
||||
};
|
||||
|
||||
let image_report_header_length = match kind {
|
||||
Kind::Original | Kind::Mini | Kind::MiniMk2 => 16,
|
||||
kind if kind.is_mirabox() => 1,
|
||||
_ => 8,
|
||||
};
|
||||
|
||||
@@ -1049,12 +676,7 @@ impl DeviceStateReader {
|
||||
match input {
|
||||
StreamDeckInput::ButtonStateChange(buttons) => {
|
||||
for (index, (their, mine)) in zip(buttons.iter(), my_states.buttons.iter()).enumerate() {
|
||||
if self.device.kind.is_mirabox() && self.device.kind != Kind::MiraBoxN3EN {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::ButtonDown(index as u8));
|
||||
updates.push(DeviceStateUpdate::ButtonUp(index as u8));
|
||||
}
|
||||
} else if their != mine {
|
||||
if their != mine {
|
||||
let key_count = self.device.kind.key_count();
|
||||
if index < key_count as usize {
|
||||
if *their {
|
||||
@@ -1075,12 +697,7 @@ impl DeviceStateReader {
|
||||
|
||||
StreamDeckInput::EncoderStateChange(encoders) => {
|
||||
for (index, (their, mine)) in zip(encoders.iter(), my_states.encoders.iter()).enumerate() {
|
||||
if self.device.kind.is_mirabox() && self.device.kind != Kind::MiraBoxN3EN {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
|
||||
updates.push(DeviceStateUpdate::EncoderUp(index as u8));
|
||||
}
|
||||
} else if *their != *mine {
|
||||
if *their != *mine {
|
||||
if *their {
|
||||
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
|
||||
} else {
|
||||
|
||||
-145
@@ -45,80 +45,12 @@ pub fn extract_str(bytes: &[u8]) -> Result<String, Utf8Error> {
|
||||
Ok(from_utf8(bytes)?.replace('\0', "").to_string())
|
||||
}
|
||||
|
||||
/*
|
||||
Elgato's key index
|
||||
-----------------------------
|
||||
| 01 | 02 | 03 | 04 | 05 | 06 |
|
||||
|----|----|----|----|----|----|
|
||||
| 07 | 08 | 09 | 10 | 11 | 12 |
|
||||
|----|----|----|----|----|----|
|
||||
| 13 | 14 | 15 | 16 | 17 | 18 |
|
||||
-----------------------------
|
||||
|
||||
Ajazz AKP153x's key index
|
||||
-----------------------------
|
||||
| 0d | 0a | 07 | 04 | 01 | 10 |
|
||||
|----|----|----|----|----|----|
|
||||
| 0e | 0b | 08 | 05 | 02 | 11 |
|
||||
|----|----|----|----|----|----|
|
||||
| 0f | 0c | 09 | 06 | 03 | 12 |
|
||||
-----------------------------
|
||||
|
||||
Ajazz AKP815's key index
|
||||
--------------
|
||||
| 0f | 0e | 0d |
|
||||
|----|----|----|
|
||||
| 0c | 0b | 0a |
|
||||
|----|----|----|
|
||||
| 09 | 08 | 07 |
|
||||
|----|----|----|
|
||||
| 06 | 05 | 04 |
|
||||
|----|----|----|
|
||||
| 03 | 02 | 01 |
|
||||
--------------
|
||||
|
||||
*/
|
||||
|
||||
/// Converts Elgato key index to Ajazz key index
|
||||
pub fn elgato_to_ajazz153(kind: &Kind, key: u8) -> u8 {
|
||||
if key < kind.key_count() {
|
||||
[12, 9, 6, 3, 0, 15, 13, 10, 7, 4, 1, 16, 14, 11, 8, 5, 2, 17][key as usize]
|
||||
} else {
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts Ajazz key index to Elgato key index
|
||||
pub fn ajazz153_to_elgato_input(kind: &Kind, key: u8) -> u8 {
|
||||
if key < kind.key_count() {
|
||||
[4, 10, 16, 3, 9, 15, 2, 8, 14, 1, 7, 13, 0, 6, 12, 5, 11, 17][key as usize]
|
||||
} else {
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
/// Make last key index first, and first key index last
|
||||
pub fn inverse_key_index(kind: &Kind, key: u8) -> u8 {
|
||||
if key < kind.key_count() {
|
||||
kind.key_count() - 1 - key
|
||||
} else {
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
/// Flips key index horizontally, for use with Original v1 Stream Deck
|
||||
pub fn flip_key_index(kind: &Kind, key: u8) -> u8 {
|
||||
let col = key % kind.column_count();
|
||||
(key - col) + ((kind.column_count() - 1) - col)
|
||||
}
|
||||
|
||||
/// Extends buffer up to required packet length
|
||||
pub fn mirabox_extend_packet(kind: &Kind, buf: &mut Vec<u8>) {
|
||||
let length = if kind.is_mirabox_v2() { 1025 } else { 513 };
|
||||
|
||||
buf.extend(vec![0u8; length - buf.len()]);
|
||||
}
|
||||
|
||||
/// Reads button states, empty vector if no data
|
||||
pub fn read_button_states(kind: &Kind, states: &[u8]) -> Vec<bool> {
|
||||
if states[0] == 0 {
|
||||
@@ -126,16 +58,6 @@ pub fn read_button_states(kind: &Kind, states: &[u8]) -> Vec<bool> {
|
||||
}
|
||||
|
||||
match kind {
|
||||
kind if kind.is_mirabox() => {
|
||||
let mut bools = vec![];
|
||||
|
||||
for i in 0..kind.key_count() {
|
||||
bools.push(states[(i + 1) as usize] != 0);
|
||||
}
|
||||
|
||||
bools
|
||||
}
|
||||
|
||||
Kind::Original => {
|
||||
let mut bools = vec![];
|
||||
|
||||
@@ -186,70 +108,3 @@ pub fn read_encoder_input(kind: &Kind, data: &[u8]) -> Result<StreamDeckInput, S
|
||||
_ => Err(StreamDeckError::BadData),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read inputs from Ajazz AKP03x and MiraBox N3 devices
|
||||
pub fn ajazz03_read_input(kind: &Kind, input: u8, state: u8) -> Result<StreamDeckInput, StreamDeckError> {
|
||||
match input {
|
||||
(0..=6) | 0x25 | 0x30 | 0x31 => ajazz03_read_button_press(kind, input, state),
|
||||
0x90 | 0x91 | 0x50 | 0x51 | 0x60 | 0x61 => ajazz03_read_encoder_value(kind, input),
|
||||
0x33..=0x35 => ajazz03_read_encoder_press(kind, input, state),
|
||||
_ => Err(StreamDeckError::BadData),
|
||||
}
|
||||
}
|
||||
|
||||
fn ajazz03_read_button_press(kind: &Kind, input: u8, state: u8) -> Result<StreamDeckInput, StreamDeckError> {
|
||||
let mut button_states = vec![0x01];
|
||||
button_states.extend(vec![0u8; (kind.key_count() + 1) as usize]);
|
||||
|
||||
if input == 0 {
|
||||
return Ok(StreamDeckInput::ButtonStateChange(read_button_states(kind, &button_states)));
|
||||
}
|
||||
|
||||
let pressed_index: usize = match input {
|
||||
// Six buttons with displays
|
||||
(1..=6) => input as usize,
|
||||
// Three buttons without displays
|
||||
0x25 => 7,
|
||||
0x30 => 8,
|
||||
0x31 => 9,
|
||||
_ => return Err(StreamDeckError::BadData),
|
||||
};
|
||||
|
||||
button_states[pressed_index] = state;
|
||||
|
||||
Ok(StreamDeckInput::ButtonStateChange(read_button_states(kind, &button_states)))
|
||||
}
|
||||
|
||||
fn ajazz03_read_encoder_value(kind: &Kind, input: u8) -> Result<StreamDeckInput, StreamDeckError> {
|
||||
let mut encoder_values = vec![0i8; kind.encoder_count() as usize];
|
||||
|
||||
let (encoder, value): (usize, i8) = match input {
|
||||
// Left encoder
|
||||
0x90 => (0, -1),
|
||||
0x91 => (0, 1),
|
||||
// Middle (top) encoder
|
||||
0x50 => (1, -1),
|
||||
0x51 => (1, 1),
|
||||
// Right encoder
|
||||
0x60 => (2, -1),
|
||||
0x61 => (2, 1),
|
||||
_ => return Err(StreamDeckError::BadData),
|
||||
};
|
||||
|
||||
encoder_values[encoder] = value;
|
||||
Ok(StreamDeckInput::EncoderTwist(encoder_values))
|
||||
}
|
||||
|
||||
fn ajazz03_read_encoder_press(kind: &Kind, input: u8, state: u8) -> Result<StreamDeckInput, StreamDeckError> {
|
||||
let mut encoder_states = vec![false; kind.encoder_count() as usize];
|
||||
|
||||
let encoder: usize = match input {
|
||||
0x33 => 0, // Left encoder
|
||||
0x35 => 1, // Middle (top) encoder
|
||||
0x34 => 2, // Right encoder
|
||||
_ => return Err(StreamDeckError::BadData),
|
||||
};
|
||||
|
||||
encoder_states[encoder] = state != 0;
|
||||
Ok(StreamDeckInput::EncoderStateChange(encoder_states))
|
||||
}
|
||||
Reference in new issue
Block a user