Add Stream Deck+ support with encoders, touch strip, and LCD output

This commit is contained in:
Ian Gulliver
2026-02-11 22:07:17 -08:00
parent 366f1714a0
commit 12e02e680d
3 changed files with 319 additions and 94 deletions

View File

@@ -10,13 +10,6 @@ import (
"qrun/lib/streamdeck"
)
var keyLabels = []string{
"1", "2", "3", "4", "5", "6", "7", "8",
"A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "W", "X",
}
var palette = []color.RGBA{
{220, 50, 50, 255},
{50, 180, 50, 255},
@@ -28,15 +21,6 @@ var palette = []color.RGBA{
{100, 100, 200, 255},
}
func drawKey(dev *streamdeck.Device, key int, active bool) {
col := key % streamdeck.KeyCols()
bg := palette[col]
if !active {
bg = color.RGBA{bg.R / 3, bg.G / 3, bg.B / 3, 255}
}
dev.SetKeyText(key, bg, color.White, keyLabels[key])
}
func main() {
dev, err := streamdeck.Open()
if err != nil {
@@ -45,19 +29,43 @@ func main() {
}
defer dev.Close()
fmt.Printf("Connected to: %s (serial: %s)\n", dev.Product(), dev.SerialNumber())
model := dev.Model()
fmt.Printf("Connected to: %s (%s, serial: %s)\n", dev.Product(), model.Name, dev.SerialNumber())
fmt.Printf("Keys: %d (%dx%d), Encoders: %d\n", model.Keys, model.KeyCols, model.KeyRows, model.Encoders)
dev.SetBrightness(80)
for i := 0; i < streamdeck.KeyCount(); i++ {
drawKey(dev, i, false)
keyLabels := make([]string, model.Keys)
for i := range keyLabels {
if i < 8 {
keyLabels[i] = string(rune('1' + i))
} else {
keyLabels[i] = string(rune('A' + i - 8))
}
}
active := make([]bool, streamdeck.KeyCount())
drawKey := func(key int, active bool) {
col := key % model.KeyCols
bg := palette[col%len(palette)]
if !active {
bg = color.RGBA{bg.R / 3, bg.G / 3, bg.B / 3, 255}
}
dev.SetKeyText(key, bg, color.White, keyLabels[key])
}
keys := make(chan streamdeck.KeyEvent, 64)
for i := 0; i < model.Keys; i++ {
drawKey(i, false)
}
if model.LCDWidth > 0 {
dev.SetLCDColor(0, 0, model.LCDWidth, model.LCDHeight, color.RGBA{30, 30, 30, 255})
}
active := make([]bool, model.Keys)
input := make(chan streamdeck.InputEvent, 64)
go func() {
if err := dev.ReadKeys(keys); err != nil {
if err := dev.ReadInput(input); err != nil {
fmt.Fprintf(os.Stderr, "Read error: %v\n", err)
}
}()
@@ -67,13 +75,29 @@ func main() {
for {
select {
case ev := <-keys:
if !ev.Pressed {
continue
case ev := <-input:
if ev.Key != nil && ev.Key.Pressed {
k := ev.Key.Key
active[k] = !active[k]
drawKey(k, active[k])
fmt.Printf("Key %s toggled %v\n", keyLabels[k], active[k])
}
if ev.Encoder != nil {
e := ev.Encoder
if e.Delta != 0 {
fmt.Printf("Encoder %d rotated %+d\n", e.Encoder, e.Delta)
} else {
fmt.Printf("Encoder %d pressed=%v\n", e.Encoder, e.Pressed)
}
}
if ev.Touch != nil {
t := ev.Touch
if t.Type == streamdeck.TouchSwipe {
fmt.Printf("Touch swipe (%d,%d) -> (%d,%d)\n", t.X, t.Y, t.X2, t.Y2)
} else {
fmt.Printf("Touch %v at (%d,%d)\n", t.Type, t.X, t.Y)
}
}
active[ev.Key] = !active[ev.Key]
drawKey(dev, ev.Key, active[ev.Key])
fmt.Printf("Key %s toggled %v\n", keyLabels[ev.Key], active[ev.Key])
case <-sig:
fmt.Println()
return