2026-02-11 22:16:20 -08:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"image"
|
|
|
|
|
"image/color"
|
|
|
|
|
"image/draw"
|
|
|
|
|
"os"
|
|
|
|
|
"os/signal"
|
|
|
|
|
"syscall"
|
|
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
"golang.org/x/image/font"
|
2026-02-11 22:16:20 -08:00
|
|
|
"qrun/lib/streamdeck"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func clamp(v int) int {
|
|
|
|
|
if v < 0 {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
if v > 255 {
|
|
|
|
|
return 255
|
|
|
|
|
}
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
dev, err := streamdeck.OpenModel(&streamdeck.ModelPlus)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
defer dev.Close()
|
|
|
|
|
|
|
|
|
|
dev.SetBrightness(80)
|
|
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
stripFont := streamdeck.LoadFace("fonts/AtkinsonHyperlegibleMono-Bold.ttf", 28)
|
|
|
|
|
|
2026-02-11 22:16:20 -08:00
|
|
|
rgb := [3]int{0, 0, 0}
|
2026-02-11 22:29:43 -08:00
|
|
|
hiNibble := [3]bool{false, false, false}
|
|
|
|
|
names := [3]string{"Red", "Green", "Blue"}
|
|
|
|
|
chanColors := [3]color.RGBA{
|
|
|
|
|
{255, 80, 80, 255},
|
|
|
|
|
{80, 255, 80, 255},
|
|
|
|
|
{80, 160, 255, 255},
|
2026-02-11 22:16:20 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
m := dev.Model()
|
|
|
|
|
segW := m.LCDWidth / 4
|
|
|
|
|
half := m.LCDHeight / 2
|
|
|
|
|
|
2026-02-11 22:16:20 -08:00
|
|
|
updateLCD := func() {
|
2026-02-11 22:29:43 -08:00
|
|
|
bg := color.RGBA{uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), 255}
|
|
|
|
|
img := image.NewRGBA(image.Rect(0, 0, m.LCDWidth, m.LCDHeight))
|
|
|
|
|
draw.Draw(img, img.Bounds(), &image.Uniform{bg}, image.Point{}, draw.Src)
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
x0 := i * segW
|
|
|
|
|
x1 := (i + 1) * segW
|
|
|
|
|
cc := chanColors[i]
|
2026-02-11 22:16:20 -08:00
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
top := img.SubImage(image.Rect(x0, 0, x1, half)).(*image.RGBA)
|
|
|
|
|
streamdeck.DrawOutlinedText(top, stripFont, cc, color.Black, 2, names[i])
|
2026-02-11 22:16:20 -08:00
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
valStr := fmt.Sprintf("%03d %02x", rgb[i], rgb[i])
|
|
|
|
|
bot := img.SubImage(image.Rect(x0, half, x1, m.LCDHeight)).(*image.RGBA)
|
|
|
|
|
streamdeck.DrawOutlinedText(bot, stripFont, cc, color.Black, 2, valStr)
|
|
|
|
|
|
|
|
|
|
charW := font.MeasureString(stripFont, "0").Ceil()
|
|
|
|
|
fullW := font.MeasureString(stripFont, valStr).Ceil()
|
|
|
|
|
metrics := stripFont.Metrics()
|
|
|
|
|
lineH := metrics.Height.Ceil()
|
|
|
|
|
botH := m.LCDHeight - half
|
|
|
|
|
textX := x0 + (segW-fullW)/2
|
|
|
|
|
baseY := half + (botH-lineH)/2 + metrics.Ascent.Ceil() + 2
|
|
|
|
|
|
|
|
|
|
nibbleIdx := 5
|
|
|
|
|
if hiNibble[i] {
|
|
|
|
|
nibbleIdx = 4
|
|
|
|
|
}
|
|
|
|
|
ux := textX + nibbleIdx*charW
|
|
|
|
|
for x := ux; x < ux+charW; x++ {
|
|
|
|
|
img.Set(x, baseY, cc)
|
|
|
|
|
}
|
2026-02-11 22:16:20 -08:00
|
|
|
}
|
2026-02-11 22:29:43 -08:00
|
|
|
dev.SetLCDImage(0, 0, m.LCDWidth, m.LCDHeight, img)
|
2026-02-11 22:16:20 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateLCD()
|
|
|
|
|
|
2026-02-11 22:29:43 -08:00
|
|
|
for i := 0; i < m.Keys; i++ {
|
2026-02-11 22:16:20 -08:00
|
|
|
dev.ClearKey(i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input := make(chan streamdeck.InputEvent, 64)
|
|
|
|
|
go func() {
|
|
|
|
|
if err := dev.ReadInput(input); err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "Read error: %v\n", err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
sig := make(chan os.Signal, 1)
|
|
|
|
|
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case ev := <-input:
|
|
|
|
|
if ev.Encoder != nil && ev.Encoder.Encoder < 3 {
|
|
|
|
|
i := ev.Encoder.Encoder
|
|
|
|
|
if ev.Encoder.Delta != 0 {
|
2026-02-11 22:29:43 -08:00
|
|
|
step := 1
|
|
|
|
|
if hiNibble[i] {
|
|
|
|
|
step = 16
|
2026-02-11 22:16:20 -08:00
|
|
|
}
|
2026-02-11 22:29:43 -08:00
|
|
|
rgb[i] = clamp(rgb[i] + ev.Encoder.Delta*step)
|
2026-02-11 22:16:20 -08:00
|
|
|
updateLCD()
|
|
|
|
|
fmt.Printf("R=%d G=%d B=%d\n", rgb[0], rgb[1], rgb[2])
|
|
|
|
|
} else if ev.Encoder.Pressed {
|
2026-02-11 22:29:43 -08:00
|
|
|
hiNibble[i] = !hiNibble[i]
|
|
|
|
|
updateLCD()
|
2026-02-11 22:16:20 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case <-sig:
|
|
|
|
|
fmt.Println()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|