Vaguely works.
This commit is contained in:
parent
e77c04f6b1
commit
9c8f1ebee7
2
.gitignore
vendored
2
.gitignore
vendored
@ -24,7 +24,7 @@
|
|||||||
/Godeps/
|
/Godeps/
|
||||||
|
|
||||||
### VisualStudioCode ###
|
### VisualStudioCode ###
|
||||||
.vscode/*
|
.vscode/
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
|
10
Makefile
10
Makefile
@ -1,6 +1,7 @@
|
|||||||
GO = go
|
GO = go
|
||||||
GOFLAGS =
|
GOFLAGS =
|
||||||
INSTALLDIR = "$(APPDATA)\Elgato\StreamDeck\Plugins\dev.samwho.streamdeck.livesplit.sdPlugin"
|
INSTALLDIR = "$(APPDATA)\Elgato\StreamDeck\Plugins\dev.samwho.streamdeck.livesplit.sdPlugin"
|
||||||
|
LOGDIR = "$(APPDATA)\Elgato\StreamDeck\logs"
|
||||||
|
|
||||||
.PHONY: test install build
|
.PHONY: test install build
|
||||||
|
|
||||||
@ -8,9 +9,14 @@ build:
|
|||||||
$(GO) build $(GOFLAGS)
|
$(GO) build $(GOFLAGS)
|
||||||
|
|
||||||
test:
|
test:
|
||||||
$(GO) run $(GOFLAGS) main.go -- -port 12345 -pluginUUID 213 -registerEvent test -info "{\"application\":{\"language\":\"en\",\"platform\":\"mac\",\"version\":\"4.1.0\"},\"plugin\":{\"version\":\"1.1\"},\"devicePixelRatio\":2,\"devices\":[{\"id\":\"55F16B35884A859CCE4FFA1FC8D3DE5B\",\"name\":\"Device Name\",\"size\":{\"columns\":5,\"rows\":3},\"type\":0},{\"id\":\"B8F04425B95855CF417199BCB97CD2BB\",\"name\":\"Another Device\",\"size\":{\"columns\":3,\"rows\":2},\"type\":1}]}"
|
$(GO) run $(GOFLAGS) main.go -port 12345 -pluginUUID 213 -registerEvent test -info "{\"application\":{\"language\":\"en\",\"platform\":\"mac\",\"version\":\"4.1.0\"},\"plugin\":{\"version\":\"1.1\"},\"devicePixelRatio\":2,\"devices\":[{\"id\":\"55F16B35884A859CCE4FFA1FC8D3DE5B\",\"name\":\"Device Name\",\"size\":{\"columns\":5,\"rows\":3},\"type\":0},{\"id\":\"B8F04425B95855CF417199BCB97CD2BB\",\"name\":\"Another Device\",\"size\":{\"columns\":3,\"rows\":2},\"type\":1}]}"
|
||||||
|
|
||||||
install: build
|
install: build
|
||||||
|
rm -rf $(INSTALLDIR)
|
||||||
|
mkdir $(INSTALLDIR)
|
||||||
cp *.png $(INSTALLDIR)
|
cp *.png $(INSTALLDIR)
|
||||||
cp *.json $(INSTALLDIR)
|
cp *.json $(INSTALLDIR)
|
||||||
cp *.exe $(INSTALLDIR)
|
cp *.exe $(INSTALLDIR)
|
||||||
|
|
||||||
|
logs:
|
||||||
|
tail -f $(LOGDIR)/streamdeck-livesplit.log
|
58
main.go
58
main.go
@ -1,19 +1,61 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/samwho/streamdeck-livesplit/streamdeck"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
logFile = "C:\\Users\\samwh\\AppData\\Roaming\\Elgato\\StreamDeck\\logs\\streamdeck-livesplit.log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
port = flag.Int("port", -1, "")
|
||||||
|
pluginUUID = flag.String("pluginUUID", "", "")
|
||||||
|
registerEvent = flag.String("registerEvent", "", "")
|
||||||
|
info = flag.String("info", "", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var port int
|
f, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
var pluginUUID string
|
if err != nil {
|
||||||
var registerEvent string
|
log.Fatalf("error opening file: %v", err)
|
||||||
var info string
|
}
|
||||||
|
defer f.Close()
|
||||||
|
log.SetOutput(f)
|
||||||
|
|
||||||
flag.IntVar(&port, "name", -1, "")
|
|
||||||
flag.StringVar(&pluginUUID, "pluginUUID", "", "")
|
|
||||||
flag.StringVar(®isterEvent, "registerEvent", "", "")
|
|
||||||
flag.StringVar(&info, "info", "", "")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
params := streamdeck.RegistrationParams{
|
||||||
|
Port: *port,
|
||||||
|
PluginUUID: *pluginUUID,
|
||||||
|
RegisterEvent: *registerEvent,
|
||||||
|
Info: *info,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("registration params: %v\n", params)
|
||||||
|
ctx := context.Background()
|
||||||
|
if err := run(ctx, params); err != nil {
|
||||||
|
log.Fatalf("%v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context, params streamdeck.RegistrationParams) error {
|
||||||
|
client, err := streamdeck.NewClient(ctx, params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client.RegisterHandler(streamdeck.KeyDown, func(ctx context.Context, client *streamdeck.Client, event streamdeck.Event) {
|
||||||
|
return client.Log("key down!")
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Println("waiting for connection to close...")
|
||||||
|
client.Join()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
114
streamdeck/client.go
Normal file
114
streamdeck/client.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package streamdeck
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventHandler func(ctx context.Context, client *Client, event EventReceived) error
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
c *websocket.Conn
|
||||||
|
handlers map[string][]EventHandler
|
||||||
|
done chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(ctx context.Context, params RegistrationParams) (*Client, error) {
|
||||||
|
interrupt := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(interrupt, os.Interrupt)
|
||||||
|
|
||||||
|
u := url.URL{Scheme: "ws", Host: fmt.Sprintf("127.0.0.1:%d", params.Port)}
|
||||||
|
log.Printf("connecting to StreamDeck at %v\n", u)
|
||||||
|
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Printf("connected to StreamDeck\n")
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
c: c,
|
||||||
|
handlers: make(map[string][]EventHandler),
|
||||||
|
done: done,
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
log.Println("starting read loop")
|
||||||
|
for {
|
||||||
|
_, message, err := client.c.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("read: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event := EventReceived{}
|
||||||
|
if err := json.Unmarshal(message, &event); err != nil {
|
||||||
|
log.Printf("failed to unmarshal received event: %s\n", string(message))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := setContext(ctx, event.Context)
|
||||||
|
for _, f := range client.handlers[event.Event] {
|
||||||
|
f(ctx, client, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("recv: ", string(message))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := client.register(params); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) register(params RegistrationParams) error {
|
||||||
|
log.Println("sending register event...")
|
||||||
|
if err := client.c.WriteJSON(NewRegisterEvent(params)); err != nil {
|
||||||
|
client.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) SetSettings(ctx context.Context, settings interface{}) error {
|
||||||
|
return client.c.WriteJSON(NewEvent(ctx, SetSettings, settings))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) GetSettings(ctx context.Context) error {
|
||||||
|
return client.c.WriteJSON(NewEvent(ctx, GetSettings, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) Log(message string) error {
|
||||||
|
return client.c.WriteJSON(NewLogMessage(message))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) RegisterHandler(eventName string, handler EventHandler) {
|
||||||
|
client.handlers[eventName] = append(client.handlers[eventName], handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) Close() error {
|
||||||
|
err := client.c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-client.done:
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
}
|
||||||
|
return client.c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) Join() {
|
||||||
|
<-client.done
|
||||||
|
}
|
53
streamdeck/constants.go
Normal file
53
streamdeck/constants.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package streamdeck
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
const (
|
||||||
|
DidReceiveSettings = "didReceiveSettings"
|
||||||
|
DidReceiveGlobalSettings = "didReceiveGlobalSettings"
|
||||||
|
KeyDown = "keyDown"
|
||||||
|
KeyUp = "keyUp"
|
||||||
|
WillAppear = "willAppear"
|
||||||
|
WillDisappear = "willDisappear"
|
||||||
|
TitleParametersDidChange = "titleParametersDidChange"
|
||||||
|
DeviceDidConnect = "deviceDidConnect"
|
||||||
|
DeviceDidDisconnect = "deviceDidDisconnect"
|
||||||
|
ApplicationDidLaunch = "applicationDidLaunch"
|
||||||
|
ApplicationDidTerminate = "applicationDidTerminate"
|
||||||
|
SystemDidWakeUp = "systemDidWakeUp"
|
||||||
|
PropertyInspectorDidAppear = "propertyInspectorDidAppear"
|
||||||
|
PropertyInspectorDidDisappear = "propertyInspectorDidDisappear"
|
||||||
|
SendToPlugin = "sendToPlugin"
|
||||||
|
SendToPropertyInspector = "sendToPropertyInspector"
|
||||||
|
|
||||||
|
SetSettings = "setSettings"
|
||||||
|
GetSettings = "getSettings"
|
||||||
|
SetGlobalSettings = "setGlobalSettings"
|
||||||
|
GetGlobalSettings = "getGlobalSettings"
|
||||||
|
OpenURL = "openUrl"
|
||||||
|
LogMessage = "logMessage"
|
||||||
|
SetTitle = "setTitle"
|
||||||
|
SetImage = "setImage"
|
||||||
|
ShowAlert = "showAlert"
|
||||||
|
ShowOk = "showOk"
|
||||||
|
SetState = "setState"
|
||||||
|
SwitchToProfile = "switchToProfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contextKeyType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
contextKey contextKeyType = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
func getContext(ctx context.Context) string {
|
||||||
|
if ctx == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Value(contextKey).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setContext(ctx context.Context, streamdeckContext string) context.Context {
|
||||||
|
return context.WithValue(ctx, contextKey, streamdeckContext)
|
||||||
|
}
|
47
streamdeck/messages.go
Normal file
47
streamdeck/messages.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package streamdeck
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LogMessagePayload struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogMessage(message string) Event {
|
||||||
|
return NewEvent(nil, LogMessage, LogMessagePayload{Message: message})
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterEvent struct {
|
||||||
|
Event string `json:"event"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRegisterEvent(params RegistrationParams) RegisterEvent {
|
||||||
|
return RegisterEvent{
|
||||||
|
Event: params.RegisterEvent,
|
||||||
|
UUID: params.PluginUUID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
Action string `json:"action,omitempty"`
|
||||||
|
Event string `json:"event,omitempty"`
|
||||||
|
Context string `json:"context,omitempty"`
|
||||||
|
Device string `json:"device,omitempty"`
|
||||||
|
Payload string `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEvent(ctx context.Context, name string, payload interface{}) Event {
|
||||||
|
payloadStr, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Event{
|
||||||
|
Event: name,
|
||||||
|
Context: getContext(ctx),
|
||||||
|
Payload: string(payloadStr),
|
||||||
|
}
|
||||||
|
}
|
8
streamdeck/registration.go
Normal file
8
streamdeck/registration.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package streamdeck
|
||||||
|
|
||||||
|
type RegistrationParams struct {
|
||||||
|
Port int
|
||||||
|
PluginUUID string
|
||||||
|
RegisterEvent string
|
||||||
|
Info string
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user