feat: add support for the Stream Deck + XL (#351)

Co-authored-by: nekename <63245705+nekename@users.noreply.github.com>
This commit is contained in:
nschurmannandnekename authored and GitHub committed 2026-07-29 11:53:07 +01:00
1 parent 5317ca2783
commit e9cfbbd781
5 files changed
+14 -11

No files matched your search

+2 -2
View File
@@ -1377,9 +1377,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "elgato-streamdeck"
version = "0.12.1"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e86db7c0f5bbffc406f4226ea5bf900bfd818bd8e4f93482bdc1ceeb17824ac"
checksum = "313b59c90e347b5cff677a52bbe8bdac9ae2f158df4ee1f7fdaa35295bdc4ccb"
dependencies = [
"hidapi",
"image",
+1 -1
View File
@@ -20,7 +20,7 @@ serde_json = "1.0"
tokio = { version = "1.48", features = ["full"] }
tokio-tungstenite = "0.28"
tiny_http = "0.12"
elgato-streamdeck = { version = "0.12", default-features = false, features = ["async"] }
elgato-streamdeck = { version = "0.13", default-features = false, features = ["async"] }
hidapi = "2.6"
image = { version = "0.25", default-features = false, features = ["bmp", "jpeg"] }
streamdeck-strip-render = { git = "https://github.com/FrostyCoolSlug/streamdeck-strip-render", rev = "23fa1399" }
+2
View File
@@ -13,6 +13,7 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00a5", MODE="0660"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00b8", MODE="0660", TAG+="uaccess"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00b9", MODE="0660", TAG+="uaccess"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00ba", MODE="0660", TAG+="uaccess"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00c6", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE="0660", TAG+="uaccess"
@@ -29,3 +30,4 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00b8", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00b9", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00ba", MODE="0660", TAG+="uaccess"
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="00c6", MODE="0660", TAG+="uaccess"
+6 -6
View File
@@ -84,13 +84,12 @@ async fn clear_all_touchpoints(device: &AsyncStreamDeck) {
pub async fn clear_screen(id: &str) -> Result<(), anyhow::Error> {
if let Some(device) = ELGATO_DEVICES.read().await.get(id) {
device.clear_all_button_images().await?;
if device.kind() == Kind::Plus {
if let Some(lcd_format) = device.kind().lcd_image_format() {
device
.write_lcd_fill(&convert_image_with_format_async(device.kind().lcd_image_format().unwrap(), image::DynamicImage::new_rgb8(800, 100))?)
.await?;
} else if device.kind() == Kind::Neo {
device
.write_lcd_fill(&convert_image_with_format_async(device.kind().lcd_image_format().unwrap(), image::DynamicImage::new_rgb8(248, 58))?)
.write_lcd_fill(&convert_image_with_format_async(
lcd_format,
image::DynamicImage::new_rgb8(lcd_format.size.0 as u32, lcd_format.size.1 as u32),
)?)
.await?;
}
clear_all_touchpoints(device).await;
@@ -127,6 +126,7 @@ async fn init(device: AsyncStreamDeck, device_id: String) {
Kind::Pedal => 5,
Kind::Plus => 7,
Kind::Neo => 9,
Kind::PlusXl => 13,
};
let _ = device.clear_all_button_images().await;
clear_all_touchpoints(&device).await;
+3 -2
View File
@@ -89,6 +89,7 @@
];
$: encoderRowIndex = device.rows;
$: touchpointRowIndex = device.rows + (device.encoders > 0 ? 1 : 0);
$: keypadRowWidth = device.columns * 132;
function flatIndexFromRowCol(row: number, col: number): number {
let index = 0;
@@ -162,7 +163,7 @@
<span id="grid-description" class="sr-only">{$t("device_view.grid_description")}</span>
<div
class="flex flex-col justify-center grow px-16 py-6 overflow-auto"
class:items-center={device.columns <= 8}
class:items-center={device.columns <= 9}
class:hidden={$inspectedParentAction || selectedDevice != device.id}
class:device-fade-x={overflowsX && !overflowsY}
class:device-fade-y={overflowsY && !overflowsX}
@@ -196,7 +197,7 @@
{/each}
</div>
<div class="flex flex-row" role="row">
<div class="flex flex-row justify-between" role="row" style={`width: ${keypadRowWidth}px;`}>
{#each { length: device.encoders } as _, i}
<Key
context={{ device: device.id, profile: profile.id, controller: "Encoder", position: i }}