From 36e36e116c009c5bdc810f97b538cf9f17df481e Mon Sep 17 00:00:00 2001 From: Harald Albrecht Date: Sat, 5 Jan 2019 22:56:48 +0100 Subject: [PATCH] wip lonely shift, tests, kdenlive skeleton --- sdcard/keys.lua | 1 + sdcard/layouts/kdenlive.lua | 53 +++++++++++++ sdcard/layouts/shift.lua | 85 +++++++++++++++++---- sdcard/snippets/multibow.lua | 6 +- spec/kdenlive_spec.lua | 35 +++++++++ spec/shift_spec.lua | 141 +++++++++++++++++++++++++---------- 6 files changed, 266 insertions(+), 55 deletions(-) create mode 100644 sdcard/layouts/kdenlive.lua create mode 100644 spec/kdenlive_spec.lua diff --git a/sdcard/keys.lua b/sdcard/keys.lua index c719f77..bc9dc98 100644 --- a/sdcard/keys.lua +++ b/sdcard/keys.lua @@ -1,4 +1,5 @@ require "keybow" require "layouts/shift" require "layouts/vsc-golang" +require "layouts/kdenlive" require "layouts/empty" diff --git a/sdcard/layouts/kdenlive.lua b/sdcard/layouts/kdenlive.lua new file mode 100644 index 0000000..b91c3ce --- /dev/null +++ b/sdcard/layouts/kdenlive.lua @@ -0,0 +1,53 @@ +--[[ +Copyright 2019 Harald Albrecht + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]]-- + +-- allow users to set their own configuration before req'ing this +-- module, in order to control the key layout. For defaults, please see +-- below. +local k = _G.kdenlive or {} -- module + +local mb = require "snippets/multibow" + + + +k = {} -- module + +-- Key colors for unshifted and shifted keys; keep them rather muted in order +-- to not distract your video editing work. +k.UNSHIFTED_COLOR = {r=0, g=50, b=0} +k.SHIFTED_COLOR = {r=50, g=0, b=0} +k.keymap = { + name="kdenlive", + [9] = {c={0,1,0}} +} +k.keymap_shifted = { + name="kdenlive-shifted", + secondary=true, + [9] = {c={1,0,0}} +} +k.keymap.shift_to = k.keymap_shifted +k.keymap_shifted.shift_to = k.keymap +mb.register_keymap(k.keymap) +mb.register_keymap(k.keymap_shifted) + + +return k -- module \ No newline at end of file diff --git a/sdcard/layouts/shift.lua b/sdcard/layouts/shift.lua index 241e4b0..7f05f00 100644 --- a/sdcard/layouts/shift.lua +++ b/sdcard/layouts/shift.lua @@ -22,7 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]]-- -local shift = {} -- module +-- allow users to set their own configuration before req'ing this +-- module, in order to control the key layout. For defaults, please see +-- below. +local shift = _G.shift or {} -- module local mb = require "snippets/multibow" @@ -46,31 +49,83 @@ SHIFT →LAYOUT 🔆BRIGHT ]]-- -shift.KEY_SHIFT = 11 -shift.KEY_LAYOUT = 8 -shift.KEY_BRIGHTNESS = 5 +-- Default hardware key to function assignments, can be overriden by users +shift.KEY_SHIFT = shift.KEY_SHIFT or 11 +shift.KEY_LAYOUT = shift.KEY_LAYOUT or 8 +shift.KEY_BRIGHTNESS = shift.KEY_BRIGHTNESS or 5 + + +-- Internal flag for detecting SHIFT press-release sequences without any SHIFTed +-- function. +local shift_only = false +local in_shift = false +local other_key = false + + +-- Switch to the next SHIFT layer within the currently active keyboard layout. +-- SHIFT layer(s) are wired up as a circular list of keymaps, linked using their +-- "shift_to" elements. +function shift.shift_secondary_keymap() + local keymap = mb.current_keymap + if keymap and keymap.shift_to then + mb.activate_keymap(keymap.shift_to.name) + end +end + + +function shift.release_other() + other_key = false + if not in_shift then + mb.ungrab() + end +end + + +-- SHIFT press: switches into grabbed SHIFT mode, activating brightness change, +-- keymap cycling, et cetera. function shift.grab(key) - mb.grab("shift-shifted") + mb.grab("shift-shifted") + in_shift = true + other_key = false -- play safe. + shift_only = true end + +-- SHIFT release: leaves (grabbed) SHIFT mode, but only if there is no other +-- (bound) key currently being held. function shift.release(key) - mb.ungrab() + in_shift = false + if not other_key then + mb.ungrab() + end + if shift_only then + shift.shift_secondary_keymap() + end end + +-- Cycles to the next primary keyboard layout (keymap) function shift.cycle(key) - mb.cycle_primary_keymaps() + other_key = true + shift_only = false + mb.cycle_primary_keymaps() end + +-- Changes the Keybow LED brightness, by cycling through different brightness +-- levels function shift.brightness(key) - local b = mb.brightness + 0.3 - if b > 1 then; b = 0.4; end - mb.set_brightness(b) + other_key = true + shift_only = false + local b = mb.brightness + 0.3 + if b > 1 then; b = 0.4; end + mb.set_brightness(b) end --- define and register keymaps - +-- define and register our keymaps: the permanent SHIFT key-only keymap, as well +-- as a temporary grabbing keymap while the SHIFT key is being pressed and held. shift.keymap = { name="shift", permanent=true, @@ -81,11 +136,11 @@ shift.keymap_shifted = { secondary=true, [shift.KEY_SHIFT] = {c={r=1, g=1, b=1}, press=shift.grab, release=shift.release}, - [shift.KEY_LAYOUT] = {c={r=0, g=1, b=1}, press=shift.cycle}, - [shift.KEY_BRIGHTNESS] = {c={r=0.5, g=0.5, b=0.5}, press=shift.brightness} + [shift.KEY_LAYOUT] = {c={r=0, g=1, b=1}, press=shift.cycle, release=shift.release_other}, + [shift.KEY_BRIGHTNESS] = {c={r=0.5, g=0.5, b=0.5}, press=shift.brightness, release=shift.release_other} } - mb.register_keymap(shift.keymap) mb.register_keymap(shift.keymap_shifted) + return shift -- module diff --git a/sdcard/snippets/multibow.lua b/sdcard/snippets/multibow.lua index fcfdf37..e95ae63 100644 --- a/sdcard/snippets/multibow.lua +++ b/sdcard/snippets/multibow.lua @@ -113,7 +113,9 @@ function mb.cycle_primary_keymaps() end end next_name = next_name or first_name - mb.activate_keymap(next_name) + if first_name then + mb.activate_keymap(next_name) + end end @@ -121,7 +123,7 @@ end -- to "activate" permanent keymaps at all (and thus this deed cannot be done). function mb.activate_keymap(name) local keymap = mb.keymaps[name] - if not keymap.permanent then + if keymap and not keymap.permanent then mb.current_keymap = keymap mb.activate_leds() end diff --git a/spec/kdenlive_spec.lua b/spec/kdenlive_spec.lua new file mode 100644 index 0000000..41d0b28 --- /dev/null +++ b/spec/kdenlive_spec.lua @@ -0,0 +1,35 @@ +--[[ +Copyright 2019 Harald Albrecht + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]]-- + +local kbh = require("spec/keybowhandler") +local mb = require("snippets/multibow") +local k = require("layouts/kdenlive") + + +describe("Kdenlive keymap", function() + + it("...", function() + local kms = mb.registered_keymaps() + assert.is.equal(#kms, 2) + end) + +end) diff --git a/spec/shift_spec.lua b/spec/shift_spec.lua index 32e9791..66acc52 100644 --- a/spec/shift_spec.lua +++ b/spec/shift_spec.lua @@ -23,11 +23,10 @@ SOFTWARE. require "mocked-keybow" require "snippets/multibow" local kbh = require("spec/keybowhandler") +local mb = require("snippets/multibow") describe("SHIFT multibow keymap", function() - local mb = require("snippets/multibow") - insl(function() it("installs the SHIFT keymap", function() @@ -50,12 +49,26 @@ describe("SHIFT multibow keymap", function() assert.is_true(keymap.secondary) end end + + default_key_shift = shift.KEY_SHIFT end) end) insl(function() + it("accepts changes form default", function() + local override = 42 + + _G.shift = { KEY_SHIFT=override } + local shift = require("layouts/shift") + assert.is.equal(shift.KEY_SHIFT, override) + end) + + end) + + describe("SHIFTY", function() + -- ensure to get a fresh SHIFT layout instance each time we run -- an isolated, erm, insulated test. local shift @@ -64,55 +77,107 @@ describe("SHIFT multibow keymap", function() shift = require("layouts/shift") end) - it("SHIFT grabs", function() - spy.on(mb, "grab") - spy.on(mb, "ungrab") + insl(function() + it("SHIFT grabs", function() + spy.on(mb, "grab") + spy.on(mb, "ungrab") - -- route in the SHIFT permanent keymap - kbh.handle_key(shift.KEY_SHIFT, true) - assert.spy(mb.grab).was.called(1) - assert.spy(mb.grab).was.called_with(shift.keymap_shifted.name) + -- route in the SHIFT permanent keymap + kbh.handle_key(shift.KEY_SHIFT, true) + assert.spy(mb.grab).was.called(1) + assert.spy(mb.grab).was.called_with(shift.keymap_shifted.name) - -- route in the shifted(!) SHIFT keymap, so this checks - -- that we ungrab correctly - mb.grab:clear() - kbh.handle_key(shift.KEY_SHIFT, false) - assert.spy(mb.grab).was_not.called() - assert.spy(mb.ungrab).was.called(1) + -- route in the shifted(!) SHIFT keymap, so this checks + -- that we ungrab correctly + mb.grab:clear() + kbh.handle_key(shift.KEY_SHIFT, false) + assert.spy(mb.grab).was_not.called() + assert.spy(mb.ungrab).was.called(1) - mb.grab:revert() - mb.ungrab:revert() + mb.grab:revert() + mb.ungrab:revert() + end) end) - describe("while SHIFTed", function() + insl(function() + it("only lonely SHIFT triggers shift", function() + stub(shift, "shift_secondary_keymap") - before_each(function() - kbh.handle_key(shift.KEY_SHIFT, true) + -- test that lonely SHIFT triggers... + kbh.tap(shift.KEY_SHIFT) + assert.stub(shift.shift_secondary_keymap).was.called(1) + + -- but that SHIFT followed by another function doesn't shift. + shift.shift_secondary_keymap:clear() + for idx, key in ipairs({ + shift.KEY_LAYOUT, + shift.KEY_BRIGHTNESS + }) do + kbh.handle_key(shift.KEY_SHIFT, true) + kbh.tap(key) + kbh.handle_key(shift.KEY_SHIFT, false) + assert.stub(shift.shift_secondary_keymap).was_not.called() + end end) + end) - after_each(function() - kbh.handle_key(shift.KEY_SHIFT, false) + insl(function() + it("lonly SHIFTs shift around", function() + local keymap = { + name="test" + } + local keymap_shifted = { + name="test-shifted" + } + keymap.shift_to = keymap_shifted + keymap_shifted.shift_to = keymap + mb.register_keymap(keymap) + mb.register_keymap(keymap_shifted) + assert.is.equal(mb.current_keymap, keymap) + + spy.on(mb, "activate_keymap") + + kbh.tap(shift.KEY_SHIFT) + assert.spy(mb.activate_keymap).was.called_with(keymap_shifted.name) + assert.is.equal(mb.current_keymap, keymap_shifted) + kbh.tap(shift.KEY_SHIFT) + assert.is.equal(mb.current_keymap, keymap) + + mb.activate_keymap:revert() end) + end) - it("cycles primary keymaps", function() - stub(mb, "cycle_primary_keymaps") + insl(function() + describe("while SHIFTed", function() - kbh.tap(shift.KEY_LAYOUT) - assert.stub(mb.cycle_primary_keymaps).was.called(1) + before_each(function() + kbh.handle_key(shift.KEY_SHIFT, true) + end) + + after_each(function() + kbh.handle_key(shift.KEY_SHIFT, false) + end) + + it("cycles primary keymaps", function() + stub(mb, "cycle_primary_keymaps") + + kbh.tap(shift.KEY_LAYOUT) + assert.stub(mb.cycle_primary_keymaps).was.called(1) + + mb.cycle_primary_keymaps:revert() + end) + + it("changes brightness", function() + stub(mb, "set_brightness") + + kbh.tap(shift.KEY_BRIGHTNESS) + kbh.tap(shift.KEY_BRIGHTNESS) + assert.stub(mb.set_brightness).was.called(2) + + mb.set_brightness:revert() + end) - mb.cycle_primary_keymaps:revert() end) - - it("changes brightness", function() - stub(mb, "set_brightness") - - kbh.tap(shift.KEY_BRIGHTNESS) - kbh.tap(shift.KEY_BRIGHTNESS) - assert.stub(mb.set_brightness).was.called(2) - - mb.set_brightness:revert() - end) - end) end)