Skip to content

Commit d7d755a

Browse files
authored
Merge pull request #5 from unix-streamdeck/feat/hotplug
Feat/hotplug
2 parents 75706a2 + fe9ee0b commit d7d755a

File tree

3 files changed

+104
-53
lines changed

3 files changed

+104
-53
lines changed

dbus.go

+12-16
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ import (
77
"log"
88
)
99

10-
1110
var conn *dbus.Conn
1211

13-
var s *StreamDeckDBus
12+
var sDbus *StreamDeckDBus
1413

1514
type StreamDeckDBus struct {
16-
Cols int `json:"cols,omitempty"`
17-
Rows int `json:"rows,omitempty"`
15+
Cols int `json:"cols,omitempty"`
16+
Rows int `json:"rows,omitempty"`
1817
IconSize int `json:"icon_size,omitempty"`
19-
Page int `json:"page"`
18+
Page int `json:"page"`
2019
}
2120

2221
func (s StreamDeckDBus) GetDeckInfo() (string, *dbus.Error) {
@@ -43,8 +42,8 @@ func (StreamDeckDBus) ReloadConfig() *dbus.Error {
4342
return nil
4443
}
4544

46-
func (StreamDeckDBus) SetPage(page int) *dbus.Error {
47-
SetPage(config, page, dev)
45+
func (StreamDeckDBus) SetPage(page int) *dbus.Error {
46+
SetPage(config, page)
4847
return nil
4948
}
5049

@@ -73,13 +72,10 @@ func InitDBUS() error {
7372
}
7473
defer conn.Close()
7574

76-
s = &StreamDeckDBus{
77-
Cols: int(dev.Columns),
78-
Rows: int(dev.Rows),
79-
IconSize: int(dev.Pixels),
75+
sDbus = &StreamDeckDBus{
8076
Page: p,
8177
}
82-
conn.ExportAll(s, "/com/unixstreamdeck/streamdeckd", "com.unixstreamdeck.streamdeckd")
78+
conn.ExportAll(sDbus, "/com/unixstreamdeck/streamdeckd", "com.unixstreamdeck.streamdeckd")
8379
reply, err := conn.RequestName("com.unixstreamdeck.streamdeckd",
8480
dbus.NameFlagDoNotQueue)
8581
if err != nil {
@@ -89,14 +85,14 @@ func InitDBUS() error {
8985
if reply != dbus.RequestNameReplyPrimaryOwner {
9086
return errors.New("DBus: Name already taken")
9187
}
92-
select {}
88+
select {}
9389
}
9490

9591
func EmitPage(page int) {
9692
if conn != nil {
9793
conn.Emit("/com/unixstreamdeck/streamdeckd", "com.unixstreamdeck.streamdeckd.Page", page)
9894
}
99-
if s != nil {
100-
s.Page = page
95+
if sDbus != nil {
96+
sDbus.Page = page
10197
}
102-
}
98+
}

interface.go

+19-14
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"image/draw"
1515
"log"
1616
"os"
17+
"strings"
1718
)
1819

1920
var p int
@@ -38,16 +39,23 @@ func ResizeImage(img image.Image) image.Image {
3839
return resize.Resize(dev.Pixels, dev.Pixels, img, resize.Lanczos3)
3940
}
4041

41-
func SetImage(img image.Image, i int, page int, dev streamdeck.Device) {
42+
func SetImage(img image.Image, i int, page int, _ streamdeck.Device) {
4243
ctx := context.Background()
4344
err := sem.Acquire(ctx, 1)
4445
if err != nil {
4546
log.Println(err)
4647
return
4748
}
4849
defer sem.Release(1)
49-
if p == page {
50-
dev.SetImage(uint8(i), img)
50+
if p == page && isOpen {
51+
err := dev.SetImage(uint8(i), img)
52+
if err != nil {
53+
if strings.Contains(err.Error(), "hidapi") {
54+
disconnect()
55+
} else {
56+
log.Println(err)
57+
}
58+
}
5159
}
5260
}
5361

@@ -79,7 +87,7 @@ func SetKeyImage(currentKey *api.Key, i int) {
7987
}
8088
}
8189

82-
func SetPage(config *api.Config, page int, dev streamdeck.Device) {
90+
func SetPage(config *api.Config, page int) {
8391
p = page
8492
currentPage := config.Pages[page]
8593
for i := 0; i < len(currentPage); i++ {
@@ -114,7 +122,7 @@ func SetKey(currentKey *api.Key, i int, page int, dev streamdeck.Device) {
114122
}
115123
}
116124

117-
func HandleInput(key *api.Key, page int, index int, dev streamdeck.Device) {
125+
func HandleInput(key *api.Key, page int, index int) {
118126
if key.Command != "" {
119127
runCommand(key.Command)
120128
}
@@ -123,7 +131,7 @@ func HandleInput(key *api.Key, page int, index int, dev streamdeck.Device) {
123131
}
124132
if key.SwitchPage != 0 {
125133
page = key.SwitchPage - 1
126-
SetPage(config, page, dev)
134+
SetPage(config, page)
127135
}
128136
if key.Brightness != 0 {
129137
err := dev.SetBrightness(uint8(key.Brightness))
@@ -145,7 +153,7 @@ func HandleInput(key *api.Key, page int, index int, dev streamdeck.Device) {
145153
}
146154
key.KeyHandlerStruct = handler
147155
}
148-
key.KeyHandlerStruct.Key(page, index, key, dev)
156+
key.KeyHandlerStruct.Key(page, index, key, streamdeck.Device{})
149157
}
150158
}
151159

@@ -154,19 +162,16 @@ func Listen() {
154162
if err != nil {
155163
log.Println(err)
156164
}
157-
for {
165+
for isOpen {
158166
select {
159167
case k, ok := <-kch:
160168
if !ok {
161-
err = dev.Open()
162-
if err != nil {
163-
log.Println(err)
164-
}
165-
continue
169+
disconnect()
170+
return
166171
}
167172
if k.Pressed == true {
168173
if len(config.Pages)-1 >= p && len(config.Pages[p])-1 >= int(k.Index) {
169-
HandleInput(&config.Pages[p][k.Index], p, int(k.Index), dev)
174+
HandleInput(&config.Pages[p][k.Index], p, int(k.Index))
170175
}
171176
}
172177
}

main.go

+73-23
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package main
22

33
import (
4+
"context"
45
"encoding/json"
6+
"errors"
7+
"fmt"
58
"github.com/unix-streamdeck/api"
69
"github.com/unix-streamdeck/driver"
10+
"golang.org/x/sync/semaphore"
711
_ "image/gif"
812
_ "image/jpeg"
913
_ "image/png"
@@ -17,30 +21,21 @@ import (
1721

1822
var dev streamdeck.Device
1923
var config *api.Config
20-
var configPath = os.Getenv("HOME") + "/.streamdeck-config.json"
24+
var configPath = os.Getenv("HOME") + string(os.PathSeparator) + ".streamdeck-config.json"
25+
var isOpen = false
26+
var disconnectSem = semaphore.NewWeighted(1)
27+
var connectSem = semaphore.NewWeighted(1)
2128

2229
var basicConfig = api.Config{
2330
Pages: []api.Page{
2431
{
25-
api.Key{
26-
},
32+
api.Key{},
2733
},
2834
},
2935
}
3036

3137
func main() {
32-
d, err := streamdeck.Devices()
33-
if err != nil {
34-
log.Println(err)
35-
}
36-
if len(d) == 0 {
37-
log.Println("No Stream Deck devices found.")
38-
}
39-
dev = d[0]
40-
err = dev.Open()
41-
if err != nil {
42-
log.Println(err)
43-
}
38+
var err error
4439
config, err = readConfig()
4540
if err != nil && !os.IsNotExist(err) {
4641
log.Println(err)
@@ -63,9 +58,63 @@ func main() {
6358
config.Pages = append(config.Pages, api.Page{})
6459
}
6560
cleanupHook()
66-
SetPage(config, 0, dev)
6761
go InitDBUS()
68-
Listen()
62+
attemptConnection()
63+
}
64+
65+
func attemptConnection() {
66+
for !isOpen {
67+
_ = openDevice()
68+
if isOpen {
69+
SetPage(config, p)
70+
if sDbus != nil {
71+
sDbus.IconSize = int(dev.Pixels)
72+
sDbus.Rows = int(dev.Rows)
73+
sDbus.Cols = int(dev.Columns)
74+
}
75+
Listen()
76+
}
77+
}
78+
}
79+
80+
func disconnect() {
81+
ctx := context.Background()
82+
err := disconnectSem.Acquire(ctx, 1)
83+
if err != nil {
84+
return
85+
}
86+
defer disconnectSem.Release(1)
87+
if !isOpen {
88+
return
89+
}
90+
log.Println("Device disconnected")
91+
_ = dev.Close()
92+
isOpen = false
93+
unmountHandlers()
94+
}
95+
96+
func openDevice() error {
97+
ctx := context.Background()
98+
err := connectSem.Acquire(ctx, 1)
99+
if err != nil {
100+
return err
101+
}
102+
defer connectSem.Release(1)
103+
d, err := streamdeck.Devices()
104+
if err != nil {
105+
return err
106+
}
107+
if len(d) == 0 {
108+
return errors.New("No streamdeck devices found")
109+
}
110+
err = d[0].Open()
111+
if err != nil {
112+
return err
113+
}
114+
dev = d[0]
115+
isOpen = true
116+
fmt.Println("Device (" + dev.Serial + ") connected")
117+
return nil
69118
}
70119

71120
func readConfig() (*api.Config, error) {
@@ -81,7 +130,6 @@ func readConfig() (*api.Config, error) {
81130
return &config, nil
82131
}
83132

84-
85133
func runCommand(command string) {
86134
//args := strings.Split(command, " ")
87135
c := exec.Command("/bin/sh", "-c", command)
@@ -115,7 +163,7 @@ func SetConfig(configString string) error {
115163
if len(config.Pages) == 0 {
116164
config.Pages = append(config.Pages, api.Page{})
117165
}
118-
SetPage(config, p, dev)
166+
SetPage(config, p)
119167
return nil
120168
}
121169

@@ -129,7 +177,7 @@ func ReloadConfig() error {
129177
if len(config.Pages) == 0 {
130178
config.Pages = append(config.Pages, api.Page{})
131179
}
132-
SetPage(config, p, dev)
180+
SetPage(config, p)
133181
return nil
134182
}
135183

@@ -158,11 +206,13 @@ func SaveConfig() error {
158206
func unmountHandlers() {
159207
for i := range config.Pages {
160208
page := config.Pages[i]
161-
for i2 := range page {
162-
key := page[i2]
209+
for i2 := 0; i2 < len(page); i2++ {
210+
key := &page[i2]
163211
if key.IconHandlerStruct != nil {
164212
key.IconHandlerStruct.Stop()
213+
key.IconHandlerStruct = nil
214+
key.Buff = nil
165215
}
166216
}
167217
}
168-
}
218+
}

0 commit comments

Comments
 (0)