Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions Module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,20 @@ package api
type Module struct {
Name string `json:"name,omitempty"`

NewIcon func() IconHandler `json:"-"`
NewKey func() KeyHandler `json:"-"`
NewLcd func() LcdHandler `json:"-"`
NewKnobOrTouch func() KnobOrTouchHandler `json:"-"`
NewKeyGridBackground func() KeyGridBackgroundHandler `json:"-"`
NewTouchPanelBackgroundHandler func() TouchPanelBackgroundHandler `json:"-"`
NewForeground func() ForegroundHandler `json:"-"`
NewInput func() InputHandler `json:"-"`
NewBackground func() BackgroundHandler `json:"-"`

IconFields []Field `json:"icon_fields,omitempty"`
KeyFields []Field `json:"key_fields,omitempty"`
LcdFields []Field `json:"lcd_fields,omitempty"`
KnobOrTouchFields []Field `json:"knob_or_touch_fields,omitempty"`
LinkedFields []Field `json:"linked_fields,omitempty"`
KeyGridBackgroundFields []Field `json:"key_grid_background_fields"`
TouchPanelBackgroundFields []Field `json:"touch_panel_background_fields"`
ForegroundFields []Field `json:"icon_fields,omitempty"`
InputFields []Field `json:"key_fields,omitempty"`
BackgroundFields []Field `json:"lcd_fields,omitempty"`
LinkedFields []Field `json:"linked_fields,omitempty"`

IsIcon bool `json:"is_icon,omitempty"`
IsKey bool `json:"is_key,omitempty"`
IsLcd bool `json:"is_lcd,omitempty"`
IsKnob bool `json:"is_knob,omitempty"`
IsLinkedHandlers bool `json:"is_linked_handlers,omitempty"`
IsKeyGridBackground bool `json:"is_key_grid_background"`
IsTouchPanelBackground bool `json:"is_touch_panel_background"`
Linked bool `json:"linked,omitempty"`
IsForeground bool `json:"is_foreground,omitempty"`
IsInput bool `json:"is_input,omitempty"`
IsBackground bool `json:"is_background,omitempty"`
IsLinkedHandlers bool `json:"is_linked_handlers,omitempty"`
Linked bool `json:"linked,omitempty"`
}

type FieldType string
Expand Down
78 changes: 23 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,83 +66,51 @@ imgWithText, _ := api.DrawText(resizedImg, "Hello", 0, "CENTER")
### Implementing handlers

```go
// Implement a key handler
type MyKeyHandler struct{}

func (h *MyKeyHandler) Key(key api.KeyConfigV3, info api.StreamDeckInfoV1) {
// Handle key press
// Implement a handler
type MyHandler struct{
running bool
}

// Implement an icon handler
type MyIconHandler struct {
running bool
func (h *MyHandler) Input(fields map[string]any, handlerType HandlerType, info StreamDeckInfoV1, event InputEvent) {
switch event.EventType {
case api.KNOB_CW:
// Handle clockwise rotation
case api.KNOB_CCW:
// Handle counter-clockwise rotation
case api.KNOB_PRESS:
// Handle knob press
case api.KEY_PRESS:
// Handle key press
}
}

func (h *MyIconHandler) Start(key api.KeyConfigV3, info api.StreamDeckInfoV1, callback func(image image.Image)) {
h.running = true
// Generate and update icon
// Call callback with new images when needed
func (h *MyHandler) Start(fields map[string]any, handlerType HandlerType, info StreamDeckInfoV1, callback func(image image.Image)) {
// Generate image and send it back via callback
}

func (h *MyIconHandler) IsRunning() bool {
func (h *MyHandler) IsRunning() bool {
return h.running
}

func (h *MyIconHandler) SetRunning(running bool) {
func (h *MyHandler) SetRunning(running bool) {
h.running = running
}

func (h *MyIconHandler) Stop() {
func (h *MyHandler) Stop() {
h.running = false
// Clean up resources and stop calling callback
}

// Implement an LCD handler (for Stream Deck Plus)
type MyLcdHandler struct {
running bool
}

func (h *MyLcdHandler) Start(knob api.KnobConfigV3, info api.StreamDeckInfoV1, callback func(image image.Image)) {
h.running = true
// Generate and update LCD image
}

func (h *MyLcdHandler) IsRunning() bool {
return h.running
}

func (h *MyLcdHandler) SetRunning(running bool) {
h.running = running
}

func (h *MyLcdHandler) Stop() {
h.running = false
}

// Implement a knob or touch handler (for Stream Deck Plus)
type MyKnobHandler struct{}

func (h *MyKnobHandler) Input(knob api.KnobConfigV3, info api.StreamDeckInfoV1, event api.InputEvent) {
switch event.EventType {
case api.KNOB_CW:
// Handle clockwise rotation
case api.KNOB_CCW:
// Handle counter-clockwise rotation
case api.KNOB_PRESS:
// Handle knob press
}
}
```

## API Documentation

The API provides several interfaces for handling Stream Deck interactions:

- `Handler`: Base interface for all handlers
- `IconHandler`: For handling dynamic icons/images
- `KeyHandler`: For handling key press events
- `LcdHandler`: For handling LCD displays (Stream Deck Plus)
- `KnobOrTouchHandler`: For handling knob rotations and touch events (Stream Deck Plus)
- `ForegroundHandler`: For handling dynamic icons/images
- `InputHandler`: For handling input events
- `BackgroundHandler`: For handling dynamic backgrounds for individual displays, or whole deck
- `CombinedHandler`: For handlers that can do foregrounds and handle input, if this handler is applied to the foreground and input of a specific key/lcd segment, the same instance of the struct will be used, so resources can be shared

Key components:

Expand Down
167 changes: 116 additions & 51 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,71 @@ package api

import (
"image"
"math"
"time"
)

type LcdBackgrounder interface {
GetTouchPanelBackground() string
GetTouchPanelBackgroundBuff() []image.Image
SetTouchPanelBackgroundBuff(img []image.Image)
GetTouchPanelBackgroundHandler() TouchPanelBackgroundHandler
SetTouchPanelBackgroundHandler(handler TouchPanelBackgroundHandler)
GetTouchPanelBackgroundHandler() BackgroundHandler
SetTouchPanelBackgroundHandler(handler BackgroundHandler)
GetTouchPanelBackgroundHandlerFields() map[string]any
}

type KeyGridBackgrounder interface {
GetKeyGridBackground() string
GetKeyGridBackgroundBuff() []image.Image
SetKeyGridBackgroundBuff(img []image.Image)
GetKeyGridBackgroundHandler() KeyGridBackgroundHandler
SetKeyGridBackgroundHandler(handler KeyGridBackgroundHandler)
GetKeyGridBackgroundHandler() BackgroundHandler
SetKeyGridBackgroundHandler(handler BackgroundHandler)
GetKeyGridBackgroundHandlerFields() map[string]any
}

type InputActions interface {
GetSwitchPage() int
GetKeyBind() string
GetCommand() string
GetBrightness() int
GetUrl() string
GetObsCommand() string
GetObsCommandParams() map[string]string
}

type ForegroundActions interface {
GetIcon() string
GetText() string
GetTextSize() int
GetTextAlignment() VerticalAlignment
GetFontFace() string
GetTextColour() string
}

type ConfigV3 struct {
Modules []string `json:"modules,omitempty"`
Decks []DeckV3 `json:"decks"`
ObsConnectionInfo ObsConnectionInfoV2 `json:"obs_connection_info,omitempty"`
}

type DeckV3 struct {
Serial string `json:"serial"`
Pages []PageV3 `json:"pages"`
TouchPanelBackground string `json:"touch_panel_background"`
TouchPanelBackgroundBuff []image.Image `json:"-"`
TouchPanelBackgroundHandler TouchPanelBackgroundHandler `json:"-"`
TouchPanelBackgroundHandlerFields map[string]any `json:"touch_panel_background_handler_fields"`
KeyGridBackground string `json:"key_grid_background"`
KeyGridBackgroundBuff []image.Image `json:"-"`
KeyGridBackgroundHandler KeyGridBackgroundHandler `json:"-"`
KeyGridBackgroundHandlerFields map[string]any `json:"key_grid_background_handler_fields"`
}

func (d *DeckV3) SetTouchPanelBackgroundHandler(handler TouchPanelBackgroundHandler) {
Serial string `json:"serial"`
Pages []PageV3 `json:"pages"`
TouchPanelBackground string `json:"touch_panel_background"`
TouchPanelBackgroundBuff []image.Image `json:"-"`
TouchPanelBackgroundHandler BackgroundHandler `json:"-"`
TouchPanelBackgroundHandlerFields map[string]any `json:"touch_panel_background_handler_fields"`
KeyGridBackground string `json:"key_grid_background"`
KeyGridBackgroundBuff []image.Image `json:"-"`
KeyGridBackgroundHandler BackgroundHandler `json:"-"`
KeyGridBackgroundHandlerFields map[string]any `json:"key_grid_background_handler_fields"`
}

func (d *DeckV3) SetTouchPanelBackgroundHandler(handler BackgroundHandler) {
d.TouchPanelBackgroundHandler = handler
}

func (d *DeckV3) GetTouchPanelBackgroundHandler() TouchPanelBackgroundHandler {
func (d *DeckV3) GetTouchPanelBackgroundHandler() BackgroundHandler {
return d.TouchPanelBackgroundHandler
}

Expand Down Expand Up @@ -78,11 +98,11 @@ func (d *DeckV3) SetKeyGridBackgroundBuff(img []image.Image) {
d.KeyGridBackgroundBuff = img
}

func (d *DeckV3) SetKeyGridBackgroundHandler(handler KeyGridBackgroundHandler) {
func (d *DeckV3) SetKeyGridBackgroundHandler(handler BackgroundHandler) {
d.KeyGridBackgroundHandler = handler
}

func (d *DeckV3) GetKeyGridBackgroundHandler() KeyGridBackgroundHandler {
func (d *DeckV3) GetKeyGridBackgroundHandler() BackgroundHandler {
return d.KeyGridBackgroundHandler
}

Expand All @@ -91,23 +111,23 @@ func (d *DeckV3) GetKeyGridBackgroundHandlerFields() map[string]any {
}

type PageV3 struct {
Keys []KeyV3 `json:"keys"`
Knobs []KnobV3 `json:"knobs"`
TouchPanelBackground string `json:"touch_panel_background"`
TouchPanelBackgroundBuff []image.Image `json:"-"`
TouchPanelBackgroundHandler TouchPanelBackgroundHandler `json:"-"`
TouchPanelBackgroundHandlerFields map[string]any `json:"touch_panel_background_handler_fields"`
KeyGridBackground string `json:"key_grid_background"`
KeyGridBackgroundBuff []image.Image `json:"-"`
KeyGridBackgroundHandler KeyGridBackgroundHandler `json:"-"`
KeyGridBackgroundHandlerFields map[string]any `json:"key_grid_background_handler_fields"`
}

func (p *PageV3) SetTouchPanelBackgroundHandler(handler TouchPanelBackgroundHandler) {
Keys []KeyV3 `json:"keys"`
Knobs []KnobV3 `json:"knobs"`
TouchPanelBackground string `json:"touch_panel_background"`
TouchPanelBackgroundBuff []image.Image `json:"-"`
TouchPanelBackgroundHandler BackgroundHandler `json:"-"`
TouchPanelBackgroundHandlerFields map[string]any `json:"touch_panel_background_handler_fields"`
KeyGridBackground string `json:"key_grid_background"`
KeyGridBackgroundBuff []image.Image `json:"-"`
KeyGridBackgroundHandler BackgroundHandler `json:"-"`
KeyGridBackgroundHandlerFields map[string]any `json:"key_grid_background_handler_fields"`
}

func (p *PageV3) SetTouchPanelBackgroundHandler(handler BackgroundHandler) {
p.TouchPanelBackgroundHandler = handler
}

func (p *PageV3) GetTouchPanelBackgroundHandler() TouchPanelBackgroundHandler {
func (p *PageV3) GetTouchPanelBackgroundHandler() BackgroundHandler {
return p.TouchPanelBackgroundHandler
}

Expand Down Expand Up @@ -139,11 +159,11 @@ func (p *PageV3) SetKeyGridBackgroundBuff(img []image.Image) {
p.KeyGridBackgroundBuff = img
}

func (p *PageV3) SetKeyGridBackgroundHandler(handler KeyGridBackgroundHandler) {
func (p *PageV3) SetKeyGridBackgroundHandler(handler BackgroundHandler) {
p.KeyGridBackgroundHandler = handler
}

func (p *PageV3) GetKeyGridBackgroundHandler() KeyGridBackgroundHandler {
func (p *PageV3) GetKeyGridBackgroundHandler() BackgroundHandler {
return p.KeyGridBackgroundHandler
}

Expand All @@ -152,21 +172,66 @@ func (p *PageV3) GetKeyGridBackgroundHandlerFields() map[string]any {
}

type StreamDeckInfoV1 struct {
Cols int `json:"cols,omitempty"`
Rows int `json:"rows,omitempty"`
IconSize int `json:"icon_size,omitempty"`
Page int `json:"page"`
Serial string `json:"serial,omitempty"`
Name string `json:"name,omitempty"`
Connected bool `json:"connected"`
LastConnected time.Time `json:"last_connected,omitempty"`
LastDisconnected time.Time `json:"last_disconnected,omitempty"`
LcdWidth int `json:"lcd_width,omitempty"`
LcdHeight int `json:"lcd_height,omitempty"`
LcdCols int `json:"lcd_cols,omitempty"`
KnobCols int `json:"knob_cols,omitempty"`
PaddingX int `json:"padding_x"`
PaddingY int `json:"padding_y"`
Cols int `json:"cols,omitempty"`
Rows int `json:"rows,omitempty"`
IconSize int `json:"icon_size,omitempty"`
Page int `json:"page"`
Serial string `json:"serial,omitempty"`
Name string `json:"name,omitempty"`
Connected bool `json:"connected"`
LastConnected time.Time `json:"last_connected,omitempty"`
LastDisconnected time.Time `json:"last_disconnected,omitempty"`
LcdWidth int `json:"lcd_width,omitempty"`
LcdHeight int `json:"lcd_height,omitempty"`
LcdCols int `json:"lcd_cols,omitempty"`
KnobCols int `json:"knob_cols,omitempty"`
PaddingX int `json:"padding_x"`
PaddingY int `json:"padding_y"`
KeyGridBackgroundWidth int `json:"key_grid_background_width"`
KeyGridBackgroundHeight int `json:"key_grid_background_height"`
LcdBackgroundWidth int `json:"lcd_background_width"`
LcdBackgroundHeight int `json:"lcd_background_height"`
}

func (info StreamDeckInfoV1) GetDimensions(handlerType HandlerType) (int, int) {
if handlerType == LCD {
return info.LcdWidth, info.LcdHeight
}
return info.IconSize, info.IconSize
}

func (info StreamDeckInfoV1) GetGridDimensions(handlerType HandlerType) (int, int) {
if handlerType == LCD {
return info.LcdBackgroundWidth, info.LcdBackgroundHeight
}
return info.KeyGridBackgroundWidth, info.KeyGridBackgroundHeight
}

func (info StreamDeckInfoV1) SplitBackgroundImage(background image.Image, handlerType HandlerType) []image.Image {
var frameArr []image.Image

if handlerType == KEY {
for keyIndex := range info.Cols * info.Rows {
keyX := keyIndex % info.Cols
keyY := int(math.Floor(float64(keyIndex) / float64(info.Cols)))

x0, y0 := keyX*(info.IconSize+info.PaddingX), keyY*(info.IconSize+info.PaddingY)
x1, y1 := keyX*(info.IconSize+info.PaddingX)+info.IconSize, keyY*(info.IconSize+info.PaddingY)+info.IconSize

frameArr = append(frameArr, SubImage(background, x0, y0, x1, y1))
}
} else {
for lcdIndex := range info.LcdCols {
x0, y0 := info.LcdWidth*lcdIndex, 0
x1, y1 := info.LcdWidth*(lcdIndex+1), info.LcdHeight

subImage := SubImage(background, x0, y0, x1, y1)

frameArr = append(frameArr, subImage)
}
}

return frameArr
}

type ObsConnectionInfoV2 struct {
Expand Down
Loading
Loading