This script should disable all keys, and log if there was a single or double keypress within 3 seconds.
When you run this script, I'd expect you'd be unable to navigate out of the menu.
Single presses are ignored.
But when you double press, it responds as a single press...
How's that possible with return false on all key events?
-- Double Press
-- Not working
key_counter = 0
function check_double_press()
sleep(3)
if(key_counter == 2) then
-- Double press
display.notify_box(tostring(key_counter))
elseif(key_counter == 1) then
-- Single press
display.notify_box(tostring(key_counter))
end
key_counter = 0
return false
end
event.keypress = function(k)
key_counter = key_counter + 1
if(key_counter == 1) then
task.create(function()
check_double_press()
end)
end
-- Don't respond to any keys
return false
end
Do you have other scripts running?
Multitasking limitations, see https://builds.magiclantern.fm/lua_api/modules/task.html and https://www.magiclantern.fm/forum/index.php?topic=14828.msg179227#msg179227 .
No easy fix for this one :(
Quote from: garry23 on July 11, 2019, 06:18:41 PM
Do you have other scripts running?
Good question! Just tried on a fresh install of the newest build from Danne. Only Lua module loaded and this test script. But the issue remains.
Quote from: a1ex on July 11, 2019, 08:55:20 PM
Multitasking limitations, see https://builds.magiclantern.fm/lua_api/modules/task.html and https://www.magiclantern.fm/forum/index.php?topic=14828.msg179227#msg179227 .
No easy fix for this one :(
That's a bummer :(
Will need to use creative workarounds then.
As a side-note, how can I set priority when calling task.create()? I thought it would just be an integer but I can't seem to get the syntax right.
Quote from: Jip-Hop on July 11, 2019, 09:35:38 PM
Good question! Just tried on a fresh install of the newest build from Danne. Only Lua module loaded and this test script. But the issue remains.
I could merge fixes here but that's blind merging on my part. Interested what a1ex has to say about the issue and the fix first.
What I understand is that there's no easy fix for the Lua multitasking limitations.
But the config.lua issue I ran into (https://www.magiclantern.fm/forum/index.php?topic=21220.msg218505#msg218505) is a separate matter and there's already a fix and pull request for those.
Yep. Those pull requests. Maybe a reason why they are not merged...
Ah yes good question.
I think I now have a working example, which uses event.shoot_task instead of task.create().
Honestly I don't know what event.shoot_task actually is, how often it refreshes etc.
And I'm still curious about the priority syntax for task.create().
This test blocks all keys, and no keys slip through.
Seems to reliably detect single and double press, which is what I wanted.
Doesn't this run into the multitasking limitations because it's all in one task?
-- Double Press
-- Working
first_press_time = nil
second_press_time = nil
event.shoot_task = function()
if(first_press_time == nil) then
return true
end
-- If after 500ms no second key is pressed
-- Don't wait and handle first key press
if(dryos.ms_clock - first_press_time) > 500 then
display.notify_box("Single")
first_press_time = nil
return true
end
if(second_press_time ~= nil) then
-- This is a double press
first_press_time = nil
second_press_time = nil
display.notify_box("Double")
end
return true
end
event.keypress = function(k)
if(first_press_time == nil) then
first_press_time = dryos.ms_clock
else
second_press_time = dryos.ms_clock
end
-- Don't respond to any keys
return false
end
@Jip-Hop
I think I hinted in a previous post that you need to exploit the two event handlers, ie key and shoot.
From my experience shoot handler is cycled fast enough.
Thanks garry23, that was great advice :)
Though also this technique I'm not quite out of the woods yet.
With below example I get funky results when I keep basing the PLAY for a while.
E.g. if I press it quickly, maybe 40 times, the camera locks up for some time.
When it responds again it often shows me, in the playback mode, a photo I've taken.
Clearly the intention of the script is to not allow default action of the keys.
Yet still a key event slipped through.
While this may be extreme usage it shows it's not robust.
With my more complex script the issues and lockups are worse, also with less key pressing.
-- Double Press
-- Working kind of
first_press_time = nil
second_press_time = nil
event.shoot_task = function()
if(first_press_time == nil) then
return true
end
-- If after 500ms no second key is pressed
-- Don't wait and handle first key press
if(dryos.ms_clock - first_press_time) > 500 then
display.notify_box("Single")
first_press_time = nil
return true
end
if(second_press_time ~= nil) then
-- This is a double press
first_press_time = nil
second_press_time = nil
display.notify_box("Double")
lv.pause()
lv.start()
end
return true
end
event.keypress = function(k)
if(first_press_time == nil) then
first_press_time = dryos.ms_clock
else
second_press_time = dryos.ms_clock
end
-- Don't respond to any keys
return false
end
I've now tried the approach from the calc.lua example.
Now I only have one event handler for the key presses and another infinite loop with task.yield(100).
Seems to work a lot better already, especially for opening the ML menu.
I've added a cooldown period too, but I can still get the camera to lock up by pressing keys quickly.
The camera no longer responds to any buttons on the back, the screen is either black or a frozen still.
But it still responds to switching to photo mode with the mode dial and back to video mode.
Then it works as normal again.
Also I can shutdown the camera with ON/OFF button still.
-- Double Press
-- Double Press works fine, but combined with the rest it may still cause issues
-- Simple test, doesn't lock up camera
first_press_time = nil
second_press_time = nil
cooldown_start_time = nil
event.keypress = function(k)
-- Temporarily ignore PLAY keys during cooldown period
if cooldown_start_time ~= nil and (dryos.ms_clock - cooldown_start_time) < 1000 then
return false
end
if(first_press_time == nil) then
first_press_time = dryos.ms_clock
else
second_press_time = dryos.ms_clock
end
-- Don't respond to any keys
return false
end
function main_loop()
while true do
if lv.paused == true then
lv.start()
end
if(first_press_time ~= nil) then
-- If after 500ms no second key is pressed
-- Don't wait and handle first key press
if(dryos.ms_clock - first_press_time) > 500 then
display.notify_box("Single")
cooldown_start_time = dryos.ms_clock
first_press_time = nil
if menu.visible == false then
menu.open()
end
elseif (second_press_time ~= nil) then
-- This is a double press
cooldown_start_time = dryos.ms_clock
first_press_time = nil
second_press_time = nil
display.notify_box("Double")
lv.pause()
-- lv.start()
end
end
task.yield(100)
end
end
console.hide()
main_loop()
@Jip-Hop
Only time for a quick look.
Your keypress event function only returns false ;)
You need to handle all keys, ie only your hyjacked key gets the special treatment, all other key presses need to return true.
Try using the keypress event to set flags for the shoot event to handle.
Hi garry23,
I'm using flags already and I'm aware I shouldn't return false always, but for this simple example I return false for all keys just to be clear that no keys should be handled as normal (they should all be blocked). Makes it all the more obvious when a key slips through.
From Lua api docs: "Event handlers will not run if there's already a script or another event handler actively executing at the same time."
This is a big problem for what I'm trying to do. If I double press the play key, I call a function to switch raw video preset and refresh live view. This apparently keeps the camera busy (it's actively executing a script). Therefore the key press event handler won't run the third time I press play, and the default action isn't prevented. Now the camera tries to go into play mode while still switching raw video presets and refreshing live view. This causes conflicts and partially locks up the camera.
So with a double press and a few seconds of patience it works fine, but if I accidentally triple press I lock up the camera and need to reboot or switch modes.
Conclusion: Until there's a reliable way to prevent the default action of a key I can't make this work.
Still curious if using task.create with a high priority would make a difference. But I still haven't figured out how to specify the priority...
@Jip-Hop
One thought I had, that I have tried before and that worked, is to have one script that handles all key events and maintains info in that scripts menus.
Thus other scripts, that do stuff, can read the key handler menu info.
This way you can also try and deconflict between the scripts.
Just a thought.