diff --git a/cmd/streamdeck/action_keyPress.go b/cmd/streamdeck/action_keyPress.go new file mode 100644 index 0000000..4ac1219 --- /dev/null +++ b/cmd/streamdeck/action_keyPress.go @@ -0,0 +1,81 @@ +package main + +import ( + "strconv" + "time" + + "github.com/pkg/errors" + "github.com/sashko/go-uinput" +) + +func init() { + registerAction("key_press", actionKeyPress{}) +} + +type actionKeyPress struct{} + +func (actionKeyPress) Execute(attributes map[string]interface{}) error { + keys, ok := attributes["keys"].([]interface{}) + if !ok { + return errors.New("No keys array present") + } + + var ( + delay time.Duration + keyCodes []uint16 + ) + + if v, ok := attributes["delay"].(string); ok { + if d, err := time.ParseDuration(v); err == nil { + delay = d + } + } + + for _, k := range keys { + // Convert misdetections into strings + switch k.(type) { + case int: + k = strconv.Itoa(k.(int)) + } + + if kv, ok := k.(string); ok { + if kc, ok := uinputKeyMapping[kv]; ok { + keyCodes = append(keyCodes, kc) + } else { + return errors.Errorf("Unknown key %q", kv) + } + } else { + return errors.New("Unknown key type detected") + } + } + + if v, ok := attributes["mod_shift"].(bool); ok && v { + if err := kbd.KeyDown(uinput.KeyLeftShift); err != nil { + return errors.Wrap(err, "Unable to set shift") + } + defer kbd.KeyUp(uinput.KeyLeftShift) + } + + if v, ok := attributes["mod_alt"].(bool); ok && v { + if err := kbd.KeyDown(uinput.KeyLeftAlt); err != nil { + return errors.Wrap(err, "Unable to set shift") + } + defer kbd.KeyUp(uinput.KeyLeftAlt) + } + + if v, ok := attributes["mod_ctrl"].(bool); ok && v { + if err := kbd.KeyDown(uinput.KeyLeftCtrl); err != nil { + return errors.Wrap(err, "Unable to set shift") + } + defer kbd.KeyUp(uinput.KeyLeftCtrl) + } + + for _, kc := range keyCodes { + if err := kbd.KeyPress(kc); err != nil { + return errors.Wrap(err, "Unable to press key") + } + time.Sleep(delay) + } + + return nil +} diff --git a/cmd/streamdeck/go.mod b/cmd/streamdeck/go.mod index 195ddee..eb0c806 100644 --- a/cmd/streamdeck/go.mod +++ b/cmd/streamdeck/go.mod @@ -9,6 +9,7 @@ require ( github.com/Luzifer/streamdeck v0.0.0-20191120013804-40fbd11001d0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/pkg/errors v0.8.1 + github.com/sashko/go-uinput v0.0.0-20180923134002-15fcac7aa54a github.com/sirupsen/logrus v1.4.2 github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e // indirect diff --git a/cmd/streamdeck/go.sum b/cmd/streamdeck/go.sum index 94db017..6cd9a88 100644 --- a/cmd/streamdeck/go.sum +++ b/cmd/streamdeck/go.sum @@ -13,6 +13,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sashko/go-uinput v0.0.0-20180923134002-15fcac7aa54a h1:AWRVuJ7oUaZdSQviWTIV14AuNzoNHrodAQjY5VTpSdk= +github.com/sashko/go-uinput v0.0.0-20180923134002-15fcac7aa54a/go.mod h1:5XNvpYRRmWADwhphlimZLWP70oEL1f54E4Guo20fvV4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= diff --git a/cmd/streamdeck/keymap.go b/cmd/streamdeck/keymap.go new file mode 100644 index 0000000..2c42bf0 --- /dev/null +++ b/cmd/streamdeck/keymap.go @@ -0,0 +1,89 @@ +package main + +import "github.com/sashko/go-uinput" + +var uinputKeyMapping = map[string]uint16{ + ``: uinput.KeyEsc, + `1`: uinput.Key1, + `2`: uinput.Key2, + `3`: uinput.Key3, + `4`: uinput.Key4, + `5`: uinput.Key5, + `6`: uinput.Key6, + `7`: uinput.Key7, + `8`: uinput.Key8, + `9`: uinput.Key9, + `0`: uinput.Key0, + `-`: uinput.KeyMinus, + `=`: uinput.KeyEqual, + ``: uinput.KeyBackspace, + ``: uinput.KeyTab, + `q`: uinput.KeyQ, + `w`: uinput.KeyW, + `e`: uinput.KeyE, + `r`: uinput.KeyR, + `t`: uinput.KeyT, + `y`: uinput.KeyY, + `u`: uinput.KeyU, + `i`: uinput.KeyI, + `o`: uinput.KeyO, + `p`: uinput.KeyP, + `[`: uinput.KeyLeftBrace, + `]`: uinput.KeyRightBrace, + ``: uinput.KeyEnter, + ``: uinput.KeyLeftCtrl, + `a`: uinput.KeyA, + `s`: uinput.KeyS, + `d`: uinput.KeyD, + `f`: uinput.KeyF, + `g`: uinput.KeyG, + `h`: uinput.KeyH, + `j`: uinput.KeyJ, + `k`: uinput.KeyK, + `l`: uinput.KeyL, + `;`: uinput.KeySemicolon, + `'`: uinput.KeyApostrophe, + ``: uinput.KeyGrave, + ``: uinput.KeyLeftShift, + `\`: uinput.KeyBackslash, + `z`: uinput.KeyZ, + `x`: uinput.KeyX, + `c`: uinput.KeyC, + `v`: uinput.KeyV, + `b`: uinput.KeyB, + `n`: uinput.KeyN, + `m`: uinput.KeyM, + `,`: uinput.KeyComma, + `.`: uinput.KeyDot, + `/`: uinput.KeySlash, + ``: uinput.KeyRightShift, + ``: uinput.KeyLeftAlt, + ``: uinput.KeySpace, + ``: uinput.KeyCapsLock, + `f1`: uinput.KeyF1, + `f2`: uinput.KeyF2, + `f3`: uinput.KeyF3, + `f4`: uinput.KeyF4, + `f5`: uinput.KeyF5, + `f6`: uinput.KeyF6, + `f7`: uinput.KeyF7, + `f8`: uinput.KeyF8, + `f9`: uinput.KeyF9, + `f10`: uinput.KeyF10, + ``: uinput.KeyNumLock, + ``: uinput.KeyScrollLock, + `f11`: uinput.KeyF11, + `f12`: uinput.KeyF12, + `f13`: uinput.KeyF13, + `f14`: uinput.KeyF14, + `f15`: uinput.KeyF15, + `f16`: uinput.KeyF16, + `f17`: uinput.KeyF17, + `f18`: uinput.KeyF18, + `f19`: uinput.KeyF19, + `f20`: uinput.KeyF20, + `f21`: uinput.KeyF21, + `f22`: uinput.KeyF22, + `f23`: uinput.KeyF23, + `f24`: uinput.KeyF24, +} diff --git a/cmd/streamdeck/main.go b/cmd/streamdeck/main.go index 3457a23..0ca457f 100644 --- a/cmd/streamdeck/main.go +++ b/cmd/streamdeck/main.go @@ -7,6 +7,7 @@ import ( "github.com/Luzifer/rconfig/v2" "github.com/Luzifer/streamdeck" "github.com/pkg/errors" + "github.com/sashko/go-uinput" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" ) @@ -25,6 +26,8 @@ var ( sd *streamdeck.Client + kbd uinput.Keyboard + version = "dev" ) @@ -58,6 +61,13 @@ func main() { userConfFile.Close() + // Initalize control devices + kbd, err = uinput.CreateKeyboard() + if err != nil { + log.WithError(err).Fatal("Unable to create uinput keyboard") + } + defer kbd.Close() + // Initialize device sd, err = streamdeck.New(streamdeck.StreamDeckOriginalV2) if err != nil {