-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
streamdeck.go
136 lines (104 loc) · 3.57 KB
/
streamdeck.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package streamdeck
import (
"image"
"image/color"
"github.com/pkg/errors"
hid "github.com/sstallion/go-hid"
)
const VendorElgato = 0x0fd9
const (
// Streamdeck Original V2 (0fd9:006d) 15 keys
StreamDeckOriginalV2 uint16 = 0x006d
// Stremdeck XL (0fd9:006c) 32 keys
StreamDeckXL uint16 = 0x006c
// StreamDeck Mini (0fd9:0063) 6 keys
StreamDeckMini uint16 = 0x0063
// StreamDeck Mini V2 (0fd9:0090) 6 keys
StreamDeckMiniV2 uint16 = 0x0090
)
var DeckToName = map[uint16]string{
StreamDeckOriginalV2: "StreamDeck Original V2",
StreamDeckXL: "StreamDeck XL",
StreamDeckMini: "StreamDeck Mini",
StreamDeckMiniV2: "StreamDeck Mini V2",
}
// EventType represents the state of a button (Up / Down)
type EventType uint8
const (
EventTypeUp EventType = iota
EventTypeDown
)
// Event represents a state change on a button
type Event struct {
Key int
Type EventType
}
// Client manages the connection to the StreamDeck
type Client struct {
cfg deckConfig
dev *hid.Device
devType uint16
keyStates []EventType
evts chan Event
}
// New creates a new Client for the given device (see constants for supported types)
func New(devicePID uint16) (*Client, error) {
dev, err := hid.OpenFirst(VendorElgato, devicePID)
if err != nil {
return nil, errors.Wrap(err, "Unable to open device")
}
cfg := decks[devicePID]
cfg.SetDevice(dev)
client := &Client{
cfg: cfg,
dev: dev,
devType: devicePID,
keyStates: make([]EventType, cfg.NumKeys()),
evts: make(chan Event, 100),
}
go client.read()
return client, nil
}
// Close closes the underlying HID connection
func (c Client) Close() error { return c.dev.Close() }
// Serial returns the device serial
func (c Client) Serial() (string, error) { return c.dev.GetSerialNbr() }
// FillColor fills a key with a solid color
func (c Client) FillColor(keyIdx int, col color.RGBA) error { return c.cfg.FillColor(keyIdx, col) }
// FillImage fills a key with an image
func (c Client) FillImage(keyIdx int, img image.Image) error { return c.cfg.FillImage(keyIdx, img) }
// FillPanel slices a big image and fills the keys with the parts
func (c Client) FillPanel(img image.RGBA) error { return c.cfg.FillPanel(img) }
// ClearKey fills a key with solid black
func (c Client) ClearKey(keyIdx int) error { return c.cfg.ClearKey(keyIdx) }
// ClearAllKeys fills all keys with solid black
func (c Client) ClearAllKeys() error { return c.cfg.ClearAllKeys() }
// IconSize returns the required icon size for the StreamDeck
func (c Client) IconSize() int { return c.cfg.IconSize() }
// NumKeys returns the number of keys available on the StreamDeck
func (c Client) NumKeys() int { return c.cfg.NumKeys() }
// SetBrightness sets the brightness of the keys (0-100)
func (c Client) SetBrightness(pct int) error { return c.cfg.SetBrightness(pct) }
// ResetToLogo restores the original Elgato StreamDeck logo
func (c Client) ResetToLogo() error { return c.cfg.ResetToLogo() }
// GetFimwareVersion retrieves the firmware version
func (c Client) GetFimwareVersion() (string, error) { return c.cfg.GetFimwareVersion() }
// Subscribe returns a channel to listen for incoming events
func (c Client) Subscribe() <-chan Event { return c.evts }
func (c Client) emit(key int, t EventType) { c.evts <- Event{Key: key, Type: t} }
func (c *Client) read() {
for {
buf := make([]byte, 1024)
_, err := c.dev.Read(buf)
if err != nil {
continue
}
for k := 0; k < c.cfg.NumKeys(); k++ {
newState := EventType(buf[k+c.cfg.KeyDataOffset()])
if c.keyStates[k] != newState {
c.emit(k, newState)
c.keyStates[k] = newState
}
}
}
}