-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
424 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
plugin | ||
simulator | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package Config | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/blackprism/goxlr-routing/GOXLR" | ||
"io/ioutil" | ||
) | ||
|
||
type Keybinding struct { | ||
Id int16 | ||
Name string | ||
Triggers []Trigger | ||
} | ||
|
||
type Trigger struct { | ||
Type string | ||
Actions []Action | ||
} | ||
|
||
type Action struct { | ||
Name GOXLR.ActionType | ||
Input GOXLR.Input | ||
Output GOXLR.Output | ||
} | ||
|
||
func Json(file string) []Keybinding { | ||
type Root []struct { | ||
Keybinding string `json:"keybinding"` | ||
Triggers []struct { | ||
Type string `json:"type"` | ||
Actions []struct { | ||
Name string `json:"name"` | ||
Targets []struct { | ||
Inputs []string `json:"inputs"` | ||
Outputs []string `json:"outputs"` | ||
} `json:"targets"` | ||
} `json:"actions,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
} `json:"triggers"` | ||
} | ||
|
||
jsonConfig, err := ioutil.ReadFile(file) | ||
|
||
if err != nil { | ||
panic(fmt.Sprintf("File %s can't be opened", file)) | ||
} | ||
|
||
var root Root | ||
json.Unmarshal(jsonConfig, &root) | ||
|
||
keybindings := []Keybinding{} | ||
|
||
for index, keybindingSetup := range root { | ||
var tmpTriggers []Trigger | ||
for _, trigger := range keybindingSetup.Triggers { | ||
if trigger.Type == "routing" { | ||
var tmpActions []Action | ||
for _, action := range trigger.Actions { | ||
for _, target := range action.Targets { | ||
for _, input := range target.Inputs { | ||
for _, output := range target.Outputs { | ||
tmpActions = append(tmpActions, Action{ | ||
actionToGoXLR(action.Name), | ||
inputToGoXLR(input), | ||
outputToGoXLR(output), | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
tmpTriggers = append(tmpTriggers, Trigger{ | ||
trigger.Type, | ||
tmpActions, | ||
}) | ||
} | ||
} | ||
keybindings = append(keybindings, Keybinding{ | ||
Id: int16(index) + 1, | ||
Name: keybindingSetup.Keybinding, | ||
Triggers: tmpTriggers, | ||
}) | ||
} | ||
|
||
return keybindings | ||
} | ||
|
||
func actionToGoXLR(action string) GOXLR.ActionType { | ||
switch action { | ||
case "toggle": | ||
return GOXLR.Toggle | ||
} | ||
|
||
panic(fmt.Sprintf("Action %s can't be converted to GOXLR format", action)) | ||
} | ||
|
||
func inputToGoXLR(input string) GOXLR.Input { | ||
switch input { | ||
case "Mic": | ||
return GOXLR.Mic | ||
case "Chat": | ||
return GOXLR.Chat | ||
case "Music": | ||
return GOXLR.Music | ||
case "Game": | ||
return GOXLR.Game | ||
case "Console": | ||
return GOXLR.Console | ||
case "Line In": | ||
return GOXLR.LineIn | ||
case "System": | ||
return GOXLR.System | ||
case "Samples": | ||
return GOXLR.Samples | ||
} | ||
|
||
panic(fmt.Sprintf("Input %s can't be converted to GOXLR format", input)) | ||
} | ||
|
||
func outputToGoXLR(output string) GOXLR.Output { | ||
switch output { | ||
case "Headphones": | ||
return GOXLR.Headphones | ||
case "Broadcast Stream Mix": | ||
return GOXLR.BroadcastMix | ||
case "Line Out": | ||
return GOXLR.LineOut | ||
case "Chat Mic": | ||
return GOXLR.ChatMic | ||
} | ||
|
||
panic(fmt.Sprintf("Output %s can't be converted to GOXLR format", output)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package GOXLR | ||
|
||
type ActionType string | ||
|
||
const ( | ||
Toggle ActionType = "Toggle" | ||
) | ||
const ( | ||
TurnOn ActionType = "Turn On" | ||
) | ||
const ( | ||
TurnOff ActionType = "Turn Off" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package GOXLR | ||
|
||
type Input string | ||
|
||
const ( | ||
Mic Input = "Mic" | ||
) | ||
const ( | ||
Chat Input = "Chat" | ||
) | ||
const ( | ||
Music Input = "Music" | ||
) | ||
const ( | ||
Game Input = "Game" | ||
) | ||
const ( | ||
Console Input = "Console" | ||
) | ||
const ( | ||
LineIn Input = "Line In" | ||
) | ||
const ( | ||
System Input = "System" | ||
) | ||
const ( | ||
Samples Input = "Samples" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package GOXLR | ||
|
||
type Output string | ||
|
||
const ( | ||
Headphones Output = "Headphones" | ||
) | ||
const ( | ||
BroadcastMix Output = "Broadcast Mix" | ||
) | ||
const ( | ||
LineOut Output = "Line Out" | ||
) | ||
const ( | ||
ChatMic Output = "Chat Mic" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package GOXLR | ||
|
||
type Payload struct { | ||
} | ||
|
||
func (p Payload) Routing(action ActionType, input Input, output Output) []byte { | ||
return []byte(`{ | ||
"action": "com.tchelicon.goxlr.routingtable", | ||
"event": "keyUp", | ||
"payload": { | ||
"settings":{ | ||
"RoutingAction": "` + string(action) + `", | ||
"RoutingInput": "` + string(input) + `", | ||
"RoutingOutput": "` + string(output) + `" | ||
} | ||
} | ||
}`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package Key | ||
|
||
import ( | ||
"fmt" | ||
"github.com/blackprism/goxlr-routing/Config" | ||
"github.com/blackprism/goxlr-routing/GOXLR" | ||
"github.com/gorilla/websocket" | ||
"log" | ||
"strings" | ||
"syscall" | ||
"time" | ||
"unsafe" | ||
) | ||
|
||
type MSG struct { | ||
HWND uintptr | ||
UINT uintptr | ||
WPARAM int16 | ||
LPARAM int64 | ||
DWORD int32 | ||
POINT struct{ X, Y int64 } | ||
} | ||
|
||
const ( | ||
ModAlt = 1 << iota | ||
ModCtrl | ||
ModShift | ||
) | ||
|
||
type Listener struct { | ||
user32 *syscall.DLL | ||
keybindings []Config.Keybinding | ||
payload GOXLR.Payload | ||
} | ||
|
||
func NewListener(actions []Config.Keybinding, payload GOXLR.Payload) Listener { | ||
return Listener{ | ||
user32: syscall.MustLoadDLL("user32"), | ||
keybindings: actions, | ||
payload: payload, | ||
} | ||
} | ||
|
||
func (l *Listener) Register() { | ||
l.user32 = syscall.MustLoadDLL("user32") | ||
|
||
reghotkey := l.user32.MustFindProc("RegisterHotKey") | ||
for _, keybinding := range l.keybindings { | ||
keys := strings.Split(keybinding.Name, "+") | ||
mods := keys[:len(keys)-1] | ||
key := keys[len(keys)-1] | ||
|
||
modSum := 0 | ||
for _, mod := range mods { | ||
switch mod { | ||
case "Ctrl": | ||
modSum += ModCtrl | ||
case "Alt": | ||
modSum += ModAlt | ||
case "Shift": | ||
modSum += ModShift | ||
} | ||
} | ||
|
||
// Register hotkeys: | ||
r1, _, err := reghotkey.Call(0, uintptr(keybinding.Id), uintptr(modSum), uintptr(key[0])) | ||
if r1 != 1 { | ||
fmt.Println("Failed to register", keybinding.Name, ", error:", err) | ||
} | ||
} | ||
} | ||
|
||
func (l Listener) Listen(c *websocket.Conn) { | ||
peekmsg := l.user32.MustFindProc("PeekMessageW") | ||
|
||
for { | ||
var msg = &MSG{} | ||
peekmsg.Call(uintptr(unsafe.Pointer(msg)), 0, 0, 0, 1) | ||
|
||
// Registered id is in the WPARAM field: | ||
if id := msg.WPARAM; id != 0 { | ||
for _, keybinding := range l.keybindings { | ||
if keybinding.Id != id { | ||
continue | ||
} | ||
|
||
log.Println("Hotkey pressed:", keybinding.Name) | ||
|
||
for _, trigger := range keybinding.Triggers { | ||
if trigger.Type == "routing" { | ||
for _, action := range trigger.Actions { | ||
w, _ := c.NextWriter(websocket.TextMessage) | ||
w.Write(l.payload.Routing(action.Name, action.Input, action.Output)) | ||
w.Close() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
time.Sleep(time.Millisecond * 5) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
BIN = goxlr-routing | ||
BUILDOS ?= windows | ||
BUILDARCH ?= 386 | ||
BUILDENVS ?= CGO_ENABLED=0 GOOS=$(BUILDOS) GOARCH=$(BUILDARCH) | ||
BUILDFLAGS ?= -a -installsuffix cgo --ldflags '-X main.Version=$(VERSION) -extldflags "-lm -lstdc++ -static"' | ||
|
||
build: | ||
@echo "==> Building binary ($(BUILDOS)/$(BUILDARCH)/$(BIN))" | ||
@$(BUILDENVS) go build -v $(BUILDFLAGS) -o bin/$(BIN).exe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
GO XLR Application to change routing via keybinding | ||
=================================================== | ||
|
||
This tiny application allows you to change the routing via keybinding | ||
You can look the file config.json to see how configure it. | ||
|
||
How to use | ||
---------- | ||
|
||
1. You need GO XLR StreamDeck plugin enabled. | ||
2. Configure config.json | ||
3. Launch goxlr-routing.exe | ||
4. Click on "Global Settings > Connect/Reconnect to Streamdeck App" | ||
5. Enjoy | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/blackprism/goxlr-routing/Key" | ||
gwebsocket "github.com/gorilla/websocket" | ||
"log" | ||
"net/http" | ||
) | ||
|
||
type Websocket struct { | ||
listener Key.Listener | ||
upgrader gwebsocket.Upgrader | ||
} | ||
|
||
func NewWebsocket(listener Key.Listener) Websocket { | ||
var upgrader = gwebsocket.Upgrader{} | ||
|
||
return Websocket{ | ||
listener, | ||
upgrader, | ||
} | ||
} | ||
|
||
func (w Websocket) Listen(addr string) { | ||
http.HandleFunc("/", w.handler) | ||
|
||
log.Println("Start websocket server") | ||
log.Fatal(http.ListenAndServe(addr, nil)) | ||
} | ||
|
||
func (w Websocket) handler(writer http.ResponseWriter, request *http.Request) { | ||
connection, err := w.upgrader.Upgrade(writer, request, nil) | ||
if err != nil { | ||
log.Print("Can't convert Http request to websocket:", err) | ||
return | ||
} | ||
defer connection.Close() | ||
|
||
log.Println("Connection from", connection.RemoteAddr()) | ||
|
||
w.listener.Listen(connection) | ||
} |
Oops, something went wrong.