Lua Scripting (lua.mo)

Started by dmilligan, March 29, 2015, 04:44:07 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

dmilligan

Lua Scripting Module



Run lua scripts in your camera!



Source: https://bitbucket.org/hudson/magic-lantern/branch/lua
Documentation: http://davidmilligan.github.io/ml-lua/
Current State: Merged!

Download:
Lua is now part of nightly builds!

Looking for an IDE? http://code.visualstudio.com/ + Lua extensions

NOTE: ML uses Lua version 5.3 (which is rather new and not widely adopted yet). It is very similar to 5.2 (the currently widely adopted version), the key difference has to do with integer division support. Older versions of Lua always use floating point division and always promote integers to floating point when doing division, 5.3 allows keeping integers as integers and doing integer division. I decided to go with 5.3 because of this fact. For our resource constrained devices, the ability to use integer division is very helpful (floating point division is much slower). Use a double slash (e.g. "2//3") to indicate integer division.

Can I help?
Perhaps you've been wanting to help with ML development, but writing low-level C code or digging through all the ML code to figure out how to do stuff is a little over your head? Well, I could use some help writing unit test scripts to test the scripting engine and API, and this should be a very easy task (just need basic knowledge of lua, a simple high-level scripting language). You don't even need to compile this branch, just write your test script and post it in this thread and I'll run it (though if you want to run yourself, feel free, request a build here, or compile in the cloud, just be aware things are very unstable at this point). I usually just barely have enough spare time here and there to simply implement a few API functions, and not really enough time to actually test that they work, so you may find that portions of API not working, this is why I really need your help. Thanks!

What to test and how?
I would prefer automated scripts that are like unit tests that I can just run and they spit out errors if something is not working as expected (hint: use the assert() function). For example to test file IO, try to write some data to a file, then read it back, if it's not the same data, throw an error.  Though, this is not always possible, so a script that simply exercises some particular API function is also still helpful. Things that need testing: any API function, menu stuff (make sure all the fields work as expected, see menu example), events stuff, file IO (use the builtin lua io library for this, note that stdin/out/err do not work, I know this), make sure all the constants are correctly defined, performance and resource utilization, etc.



Original Message:

Well I just managed to get lua running as module. Right now it's just "hello world", but I thought I'd share my progress.

https://bitbucket.org/dmilligan/magic-lantern/branch/lua

I'm quite familiar with lua as I implemented it inside a project at work, even wrote a fancy IDE/debugger. So now that I have the library compiled and running, creating an API should be fairly easy and straight forward.

DeafEyeJedi

Amazing work, David!

Looking forward to its progress...

[emoji106]
5D3.113 | 5D3.123 | EOSM.203 | 7D.203 | 70D.112 | 100D.101 | EOSM2.* | 50D.109

ItsMeLenny

Oh as a module! Took a few seconds for me to get it. lol.
Very good job! Now all I gotta learn is lua :P (unless you're doing a python one next)

a1ex

Great stuff!

Btw, @dmilligan, you have commit access on branches on the main repo, so you can just push things there.

You can reuse script.mo as a front-end GUI.

Here's my very old attempt at Lua scripting (it even has the API documented as PDF):
http://magiclantern.wikia.com/wiki/MagicLUA

PDF here.


jpaana

Don't know if it's feasible as it's probably a bit more work to integrate, but LuaJIT 2 is quite a bit faster even with JIT off than the standard Lua interpreter so it might also be a good alternative for these fairly performance constrained devices :) Also it has integrated FFI interface (http://luajit.org/ext_ffi.html), which makes working with C even easier.

surami

Is that correct, that this will be the replacement of the old script.mo?
550D + nightly ML

wolf

@ dmilligan
Thanks for bringing back a script module.

I compiled it with your "Compiling Magic Lantern in the Cloud" tutorial. Works great btw.
How do I start a script or is it too soon to test? (550D)


My test script:
print("hello, world");

dmilligan

It's working, but I have not documented the API yet, so it's not clear how a script should be setup. I plan on doing this, once more stuff is implemented. I can give you a quick example:

menu.new
{
    name = "Run my script!",
    help = "Press SET to run the script",
    select = function()
        console.show()
        print("Hello World!")
    end
}


here's a more advanced example:

mymenu = menu.new
{
    parent = "LUA",
    name = "Run Test Script",
    help = "Run the test script.",
    submenu =
    {
        {
            name = "Run",
            help = "Run this script.",
            icon_type = 5,
            update = "",
        },
        {
            name = "param1",
            help = "help for param1",
            min = 0,
            max = 100,
            warning = function() return "this param doesn't work right :P" end,
        },
        {
            name = "param2",
            help = "help for param2",
            min = 0,
            max = 10,
            value = 5,
            info = function() return "click it baby!" end,
        },
        {
            name = "dec test",
            min = 0,
            max = 10000,
            unit = 7,
        },
        {
            name = "choices test",
            choices = { "choice1", "choice2", "choice3" },
        }
    },
    update = function() return mymenu.submenu["choices test"].value end,
}

mymenu.submenu["Run"].select = function()
    console.show()
    print("param1= "..mymenu.submenu["param1"].value)
    print("param2= "..mymenu.submenu["param2"].value)
    print("dec test= "..mymenu.submenu["dec test"].value)
    print("choices test= "..mymenu.submenu["choices test"].value)
    print("script run finished!")
end

dmilligan

Got a few APIs implemented and documented. I'm open to comments /suggestions for the API, and what else should be added?

wolf

Cool.
I remember the PicoC API which was perfect for me.

http://www.magiclantern.fm/forum/index.php?topic=4362.0

I think power saving options i.e. display off/on are very useful.
Also key events, key press emulation and a text output like
"void bmp_printf(int fnt, int x, int y, char* fmt, ...); "    



g3gg0

hooray! nice to see progress there.
good work, dmilligan!

can modules register some functions, variables and constants to your lua module?
i am sure people would like to see some functions to call from lua. e.g. setting MLV options,
setting FRSP parameters or dual iso settings.

in this case i would prefer to not "directly" call lua module register function, but having a generic structure
that explains which functions, constants and variables my module has and call a "generic" script_register() function
to make those descriptor known.
in case there will be another scripting module, or some revival of the old ones, all of them can make use of that.

e.g.:
struct script_interface_descriptor mlv_desc =
{
    .funcs = { { .name = "mlv_start_rec", .func = &mlv_start }, { .... }},
    .vars = { { .name = "mlv_take_number", .type = VAR_TYPE_UINT32, .var = &mlv_.... }},
    .callouts = { { .name = "mlv_recording_started" }, { .name = "mlv_new_chunk" }}
}

this could be used by any script - or even PTP functions.
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

Walter Schulz

Will it be even remotely possible to access/manipulate ML options remote via USB connection? Sorry for the lame pun ...
EDIT: Just seen g3gg0's remark about PTP ...

Already answered. Damn, not to be a programmer sucks at times.

surami

I would like to run a script, which would be enabled when the picture is taken with the intervalometer and the AutoETTR module (+advanced intervalometer module) are also in use. The idea is to force a delay (4 seconds) between the shots independently from interval time.

I'm not familiar with LUA scripting and compiling the LUA module, but as I read on the API page, I should use the event "intervalometer" and the global function "msleep". The modules wouldn't do any confusion? I would like to learn and understand, that how I could do this.
550D + nightly ML

dmilligan

something like this should work:

force_delay_menu = menu.new
{
parent = "Intervalometer",
name = "Force Delay",
help = "Add an extra delay to each interval",
min = 0,
max = 300,
unit = UNIT.TIME,
}

events =
{
intervalometer = function() msleep(force_delay_menu.value * 1000) return true end
}

themichael

Would it be possible to play back a short audio file? 

Something useless like -

script_name = "Shutter Tones";
script_help = "Avoid talking to models";
events =
{
post_shoot = function() play("shutrton.wav") return true end
}


Or to say a wake up message, show a screen looking for a certain keypress sequence before playing "help help I am being camera napped!"

Of course it could play more useful stuff like focus distance (if reported) when focused or exposure settings, counting down long exposures, or the "number of number" when using auto bracketing.
7D, AE-1P, 4x5 and GAS

dmilligan

Pretty much anything is possible to do in a script that is possible from ML. The question is, is it worth while doing all the work to add whatever particular thing to the scripting API. Audio stuff is sort of a low priority, since there's a new audio backend in development, that is not finished (would be best to wait for it to be finished).



magic_button = KEY.SET

events =
{
    shoot_task = function()
        display.clear()
        display.rect(0,0,720,480,COLOR.BLACK,COLOR.BLACK)
        display.print("Please press the magic button...",20,80,FONT.LARGE)
        return true
    end
    keypress = function(key)
        if(key == magic_button) then
            events.shoot_task = nil
            events.keypress = nil
            display.clear()
        else
            beep(100)
        end
        return false
    end
}

surami

Thanks for the example David. Could you please send me a LUA.mo download link in private for testing purpose or should I wait for a more stable version?
550D + nightly ML

dmilligan

Just updated the OP, for builds you need a full build, not just the lua.mo: request a build here, or compile in the cloud.

If someone will provide the full builds, I will keep the lua.mo up to date in the OP.

See the OP for info about how and what to test.

surami

Thanks for the links. I could compile a build + LUA scripting module for my camera with Codio. It was my first try to compile something and it took some hours to figure everything out, but it seems so, that the "Force Delay" script works perfectly. I hadn't tested yet in the field outside with AutoETTR always ON or with Advanced Intervalometer module, but as I have more time I will make it and report back again.

OFF topic: Now I'm waiting for this Flash Hot Shoe Sync Adapter, I would like to use this as triggering the MX2 controller by DP. If it works, we can make nice day -> night/night -> day timelapses with some motion. (The Pixel TF-321 hot shoe sync adapter didn't worked for me, don't know what was the problem.) In theory there will be enough time (independently from interval time) during the shooting between the exposures for calculating the right ETTR picture and trigger the MX2 to move the cart on the slider and move the Merlin head.

Update: I got my simple hot shoe PC sync adapter and it works perfectly, solved.
550D + nightly ML

themichael

I went to try out my cloud compiled version and I don't have a Lua tab like Wolf does (post #6 above).

screen by memoirs-in-digital, on Flickr
7D, AE-1P, 4x5 and GAS

wolf

@themichael
you need to fetch the lua-repository.

Delete your ML folder on codio.com.
cd to workspace.
hg clone -r lua https://bitbucket.org/hudson/magic-lantern

dmilligan

You won't necessarily have a LUA tab. Scripts can specify what menu they appear under "LUA" is simply the default if a script doesn't specify this. If you don't have any scripts, or if all your scripts put themselves in other menus, then you won't have a LUA tab.

themichael

I still cannot find any Lua scripts.

Removed all the *.lua scripts in the directory.
Used the menu script in LuaAPI.rst saved as menu.lua
Cannot see it under any menu (no lua tab either) but can see it with file manager.

Compiled 15 hours ago, last change on bitbucket was 23 hours ago.
7D, AE-1P, 4x5 and GAS

dmilligan

I made some changes to the menu API and revamped the documentation. Please refer to the new documentation location linked to in the OP.

themichael

Now the test script is there and works. Trying my own.

Two questions -
A. (off topic) Can I save the scripts over USB so I don't risk damaging the CF pins on the camera?

2. Something is wrong with this script below, it doesn't show up. Is the mistake is in the menu.new part? Or am I completely off the rails?
mykeys = menu.new
{
    parent = "LUA",
    name = "Key Test Script",
    help = "Key code script.",
    submenu =
    {
            name = "Test",
            help = "Run my script.",
            icon_type = 5,
            update = "",
    },
    update = "key?",
}

mykeys.submenu["Test"].select = function()
    console.show()
    print("Waiting 10 sec for key")
    key.wait(,10000)
    if (key.last <> 0) then print("key "..key.last) else print("no key")
    print("donesies!!")
end
7D, AE-1P, 4x5 and GAS