Vaguely works.
This commit is contained in:
parent
e77c04f6b1
commit
9c8f1ebee7
2
.gitignore
vendored
2
.gitignore
vendored
@ -24,7 +24,7 @@
|
||||
/Godeps/
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
.vscode/
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
|
8
Makefile
8
Makefile
@ -1,6 +1,7 @@
|
||||
GO = go
|
||||
GOFLAGS =
|
||||
INSTALLDIR = "$(APPDATA)\Elgato\StreamDeck\Plugins\dev.samwho.streamdeck.livesplit.sdPlugin"
|
||||
LOGDIR = "$(APPDATA)\Elgato\StreamDeck\logs"
|
||||
|
||||
.PHONY: test install build
|
||||
|
||||
@ -8,9 +9,14 @@ build:
|
||||
$(GO) build $(GOFLAGS)
|
||||
|
||||
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
|
||||
rm -rf $(INSTALLDIR)
|
||||
mkdir $(INSTALLDIR)
|
||||
cp *.png $(INSTALLDIR)
|
||||
cp *.json $(INSTALLDIR)
|
||||
cp *.exe $(INSTALLDIR)
|
||||
|
||||
logs:
|
||||
tail -f $(LOGDIR)/streamdeck-livesplit.log
|
58
main.go
58
main.go
@ -1,19 +1,61 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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() {
|
||||
var port int
|
||||
var pluginUUID string
|
||||
var registerEvent string
|
||||
var info string
|
||||
f, err := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
log.Fatalf("error opening file: %v", err)
|
||||
}
|
||||
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()
|
||||
|
||||
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