Improve slowjog.

pull/5/head
Alexandre Bourget 2017-07-14 23:42:56 -04:00
rodzic 29ec7d3fd7
commit cb792838ef
4 zmienionych plików z 83 dodań i 42 usunięć

Wyświetl plik

@ -1,17 +1,25 @@
Linux driver for Contour Design Shuttle Pro V2
==============================================
My goal is to set it up for the Lightworks Non-Linear Editor.
The goal of this project is to use the Shuttle Pro V2 with the
Lightworks Non-Linear Video Editor. I'm using v14.
This program supports having modifiers for your Shuttle Pro V2
buttons. Avoid Lightworks key bindings with modifiers however. Capital
This program supports having **modifiers** for your Shuttle Pro V2
buttons. So you can multiple the functionality of your buttons. For
example, you can have different bindings for
<kbd>B1</kbd>+<kbd>F1</kbd> and <kbd>F1</kbd>.
Avoid Lightworks key bindings with modifiers however. Capital
letters are great as they cannot be combined, and are more direct and
they are less likely to conflict with your other bindings and
Lightworks recognizes them. All key names used here will work:
http://www.tcl.tk/man/tcl8.4/TkCmd/keysyms.htm
Lightworks recognizes them.
Right now, you need to install `xdotool` from your package
repositories. Eventually, we'll get rid of this dependency.
The key names to use in the X11 bindings are found here:
https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h or you can view them
locally in `/usr/include/X11/keysymdef.h` (stripped of the `XK_`
prefix).
You need to install the `xdotool` package before using this program.
Buttons layout on the Contour Design Shuttle Pro v2:
@ -31,7 +39,18 @@ Buttons layout on the Contour Design Shuttle Pro v2:
B2 B3
B1 B4
You can also use `SlowJogL` and `SlowJogR`, to use Frame nudge for example.
## Slow Jog
In addition to `JogL` and `JogR`, you can define bindings for
`SlowJogL` and `SlowJogR`. For example, you can use a slow jog use to
nudge by one frame at a time.
If you wish to not use slow jog, set the `slow_jog` key to `0` in the
configuration for this app. Otherwise, `slow_jog` represents the
minimum number of milliseconds between two events to be considered
slow. It defaults to 200 ms.
## Disable the native mouse pointer
@ -67,3 +86,5 @@ TODO
* Check udev, DISPLAY=:0.0 to start ?
* Retry ? Check the error message going out.
* Have a default SlowJog configuration.

Wyświetl plik

@ -18,7 +18,7 @@ type Config struct {
type AppConfig struct {
Name string `json:"name"`
MatchWindowTitles []string `json:"match_window_titles"`
SlowJog int `json:"slow_jog"` // Time in millisecond to use slow jog
SlowJog *int `json:"slow_jog"` // Time in millisecond to use slow jog
windowTitleRegexps []*regexp.Regexp
Bindings map[string]string `json:"bindings"`
bindings []*deviceBinding

Wyświetl plik

@ -118,7 +118,12 @@ func slowJogTiming() time.Duration {
if conf == nil {
return 200 * time.Millisecond
}
return time.Duration(conf.SlowJog) * time.Millisecond
slowJog := 200
if conf.SlowJog != nil {
slowJog = *conf.SlowJog
}
return time.Duration(slowJog) * time.Millisecond
}
func (m *Mapper) EmitOther(key string) error {
@ -158,54 +163,61 @@ func (m *Mapper) EmitKeys(modifiers map[int]bool, keyDown int) error {
}
func (m *Mapper) executeBinding(binding *deviceBinding) error {
holdButtons := binding.holdButtons
pressButton := binding.pressButton
time.Sleep(100 * time.Millisecond)
//xtest.FakeInputChecked(m.watcher.conn, m.watcher.rootWin)
// cookie := xtest.FakeInputChecked(m.watcher.conn, 2, 0x7b00, 0, m.watcher.lastWindowID, 0, 0, 0x00)
// if err := cookie.Check(); err != nil {
// return nil
// }
// cookie = xtest.FakeInputChecked(m.watcher.conn, 3, 0x7b00, 0, m.watcher.lastWindowID, 0, 0, 0x00)
// return cookie.Check()
fmt.Println("xdotool key --clearmodifiers", binding.original)
return exec.Command("xdotool", "key", "--clearmodifiers", binding.original).Run()
fmt.Println("Executing bindings:", holdButtons, pressButton)
// holdButtons := binding.holdButtons
// pressButton := binding.pressButton
time.Sleep(10 * time.Millisecond)
// fmt.Println("Executing bindings:", holdButtons, pressButton)
for _, button := range holdButtons {
fmt.Println("Key down", button)
time.Sleep(10 * time.Millisecond)
// time.Sleep(10 * time.Millisecond)
if err := m.virtualKeyboard.KeyDown(keyboardKeysUpper[button]); err != nil {
return err
}
}
// for _, button := range holdButtons {
// fmt.Println("Key down", button)
// time.Sleep(10 * time.Millisecond)
time.Sleep(10 * time.Millisecond)
// if err := m.virtualKeyboard.KeyDown(keyboardKeysUpper[button]); err != nil {
// return err
// }
// }
fmt.Println("Key press", pressButton)
if err := m.virtualKeyboard.KeyDown(keyboardKeysUpper[pressButton]); err != nil {
return err
}
// time.Sleep(10 * time.Millisecond)
time.Sleep(10 * time.Millisecond)
// fmt.Println("Key press", pressButton)
// if err := m.virtualKeyboard.KeyDown(keyboardKeysUpper[pressButton]); err != nil {
// return err
// }
if err := m.virtualKeyboard.KeyUp(keyboardKeysUpper[pressButton]); err != nil {
return err
}
// time.Sleep(10 * time.Millisecond)
time.Sleep(10 * time.Millisecond)
// if err := m.virtualKeyboard.KeyUp(keyboardKeysUpper[pressButton]); err != nil {
// return err
// }
for _, button := range holdButtons {
fmt.Println("Key up", button)
time.Sleep(10 * time.Millisecond)
if err := m.virtualKeyboard.KeyUp(keyboardKeysUpper[button]); err != nil {
return err
}
}
// time.Sleep(10 * time.Millisecond)
time.Sleep(50 * time.Millisecond)
// for _, button := range holdButtons {
// fmt.Println("Key up", button)
// time.Sleep(10 * time.Millisecond)
// if err := m.virtualKeyboard.KeyUp(keyboardKeysUpper[button]); err != nil {
// return err
// }
// }
return nil
// time.Sleep(50 * time.Millisecond)
// return nil
}
func jogVal(evs []evdev.InputEvent) int {

Wyświetl plik

@ -7,6 +7,7 @@ import (
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
"github.com/BurntSushi/xgb/xtest"
)
type watcher struct {
@ -14,6 +15,7 @@ type watcher struct {
root xproto.Window
activeAtom, nameAtom xproto.Atom
prevWindowName string
lastWindowID xproto.Window
}
func NewWindowWatcher() *watcher {
@ -29,6 +31,10 @@ func (w *watcher) Setup() error {
// Get the window id of the root window.
setup := xproto.Setup(X)
if err := xtest.Init(X); err != nil {
return err
}
w.conn = X
w.root = setup.DefaultScreen(X).Root
@ -76,6 +82,8 @@ func (w *watcher) watch() {
log.Fatal(err)
}
w.lastWindowID = windowID
windowName := string(reply.Value)
if w.prevWindowName != windowName {
w.prevWindowName = windowName