Script state at camera switch off

Started by garry23, December 07, 2017, 07:53:10 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

garry23

Although I have picked up a bit of scripting knowledge, thanks to the help I've received on the ML Forum, the one area I'm weak in is io.

For example, what is the easiest/simplest way to have my script's 'state', ie as set in the script's menus, recorded like the menu states in the ML core, ie at camera switch off. So my script starts in the same configuration as I left it at camera switch off, rather than a hard coded state.

I would welcome some hints or pointers.

Cheers

Garry

a1ex

https://bitbucket.org/hudson/magic-lantern/src/lua_fix/scripts/copy2m.lua (config.create_from_menu - if I understand it well, it should "just work" for complex scripts with simple menus)
https://bitbucket.org/hudson/magic-lantern/commits/2c8a5d0 (sokoban - example for simple scripts)
https://bitbucket.org/hudson/magic-lantern/src/manual_lens_info/scripts/lens.lua (example for menu with custom state)

BTW, event.config_save should be called whenever ML saves its own settings (that is, after closing ML menu - if you have clicked something - or at shutdown).

Would be nice to have arbitrary variables tagged as persistent somehow, so they will save their state at shutdown and auto-restore at startup. In modules and ML core, we declare them as CONFIG_INT and the backend does the rest.

garry23

@a1ex

Thanks, I'll read those links.

BTW I did try and look at the Lua Config module but it was not easy for me to see how to use it in my script.

If I can see how someone else has used config, then I can adapt for my use.

Cheers

Garry

garry23

@a1ex

Sorry to bother you, but I hope you can help; as I feel I'm so close, after reading the links you set me.

I have used config to save my menu set up and proved the savings work.

I then read one setting back in OK, ie at camera restart.

I'm stumbling on how to access a menu item that is more than one whole word.

Here is a snippet of my code.

Focus_Bar_Menu = menu.new
{
    parent = "Focus",
    name = "Focus Bar",
    help = "Shows depth of field info",
    depends_on = DEPENDS_ON.LIVEVIEW,
    submenu =
    {
        {
            name = "Display",
            help = "Switches the focus bar display on & off",
            choices = {CON,COFF},
            value = CON
        },
        {
            name = "Show Info",
            help = "Full shows additional near DoF info",
            choices = options2,
            value = "Simple" -- start up default
        },
        {
            name = "Unity Blur Multiplier",
            help = "Used for focus bar display, ie the red zone",
            min = 1,
            max = 10,
            value = 5 -- start up default
        },
        {
            name = "Diffraction",
            help = "Switches the diffraction on & off in the focus bar",
            help2 = "Focus Bar total blur is dynamically linked to ML total blur (CoC) setting",
            choices = {CON,COFF},
        },
        {
            name = "Focus Bar Multiplier",
            help = "Zoom out the focus bar by the specified amount",
            help2 = "1 means no zoom. 0 = place FP at focus bar max. -1 = DoF mode",
            min = -1,
            max = 9,
            value = -1 -- start up default
        },
        {
            name = "Near DoF Criterion",
            help = "Provides near DoF based on different infinity blurs",
            help2 = "Based on the logic that near blur can be larger than the infinity blur",
            choices = options,
            value = "Defocus" -- start up default
        },
        {
            name = "Focus Stacking",
            help = "Only works in DoF mode",
            help2 = "Magenta bar shows the amount of overlap re the last image",
            choices = {CON,COFF},
            value = COFF -- start up default
        }
    }
}
config.create_from_menu(Focus_Bar_Menu)

if cfg.data ~= nil then
    cfg = config:load()
    menu.set("Focus Bar","Display",cfg.data.Display)
    menu.set("Focus Bar","Focus Stacking",cfg.data."Focus Stacking")
end


Can you put me out of my misery, ie how to handle menus with a space in their title, ie the Focus Stacking menu item: which is obviously wrong.

Cheers

Garry

dmilligan

Doing this is completely unnecessary:

if cfg.data ~= nil then
    cfg = config:load()
    menu.set("Focus Bar","Display",cfg.data.Display)
    menu.set("Focus Bar","Focus Stacking",cfg.data."Focus Stacking")
end


config.create_from_menu does everything (setting up the save, initializing, and reloading menu values on startup). You simply pass your menu to that function and everything just works.

but to answer you question, since it's a general Lua syntax question:

menu.set("Focus Bar", "Focus Stacking", cfg.data["Focus Stacking"])

garry23

@dmilligan

Many thanks.

As you can see, I'm still very much in learning mode, and really appreciate your help.

Cheers

Garry

garry23

@dmilligan

David just a repeat thanks, as I've just proved the use of 'only' require("config") and config.create_from_menu(Focus_Bar_Menu) handles everything seamlessly in my focus bar script.

If only I had realised this before.

I have looked at the config module many times, but couldn't work out how to use it.

Once again, many thanks to you and @a1ex for finding the time to support/mentor the likes of myself.

Cheers

Garry

a1ex

Well, that's a sign the documentation needs some improvement in this area.

garry23

@a1ex @dmilligan

I have found Lua API documentation mostly helpful, but some entries are rather minimal.

I've considered suggesting changes, but feel my knowledge not up to it.

If those with the knowledge can find effort, I think it has two parts.

First ensure all the API entries are complete, for example, the current config menu entry is this:

Quoteconfig:create_from_menu(m)
    Create a new config instance from a menu structure, filename will be determined automagically
    Parameters:

        m the menu to create a config for


When I read this, after being pointed to it, I thought OK it creates the config, but I need to load it back to use it. Until David educated me that create_from_menu does it all.

Second, some of the API entries would benefit from a demo code snippet, to help scripters see/understand how to use the API call or function.

Bottom line: I am happy to support, ie I share my humble scripting attempts to help others, but I truly believe the Lua API documentation needs someone with 'insider knowledge' to add (more) value. That is 'right first time'.

Cheers

Garry


Jip-Hop

config.create_from_menu works great for me.
But how can I get and set values in the config without using a menu?
My autorun script needs to store state between reboots, and using a hidden menu (in addition to actual menu items) just to store state is not great  :P

I tried it like this, for example:

config.create_from_menu(preset_menu_ratio);

if cfg.data ~= nil then
    cfg = config:load()
    for key,value in ipairs(cfg) do
        display.notify_box(tostring(key) .. " " .. tostring(value));
        sleep(1);
    end
end


But cfg is not defined.
I tried using "config" instead, but no dice.

aprofiti

Quote from: Jip-Hop on July 10, 2019, 10:15:44 PM
config.create_from_menu works great for me.
But how can I get and set values in the config without using a menu?
My autorun script needs to store state between reboots, and using a hidden menu (in addition to actual menu items) just to store state is not great
Thats basically because you are not using the "pointer" returned by "config.create()" or "config.create_from_menu()".
Quote from: Jip-Hop on July 10, 2019, 10:15:44 PM
I tried using "config" instead, but no dice.
Only use public methods/returned values and don't access/modify global variables or private functions from config.lua (ex. "config" table or config.serialize() ), because if the current implementation will change in the future, your script will not works or will not behave as you may expecting.

After loading the config from a file, the library initialize and load all values inside his internal data structure.
This is a simplified overview on how it's memorized in memory:

config = {} -> a table, basically the script it's memorizing here what it needs during his usage
|- ...
|- configs -> in this table there is one entry for each script
|- ...

Each script's entry is following this structure:
|- filename
|- default -> a table or simple entry, initial value for each entry of data
|- data    -> this is a table containing the actual values
   Example for one menu:
   |- "MenuName" -> key for the corresponding menu table
      |- ... -> one <key,value> pairs for each menu entry (value is a table if it's a submenu)
   Example of a table:
   |- {"key" = value}


An example of usage with a configuration saved as a table:

require("config")

configuration = {["Apples"] = 1,["Eggs"] = 2}
my_config = config.create(configuration);

print(my_config.data["Apples"])

If during the script you change values in my_config somehow, they should get saved to file and loaded at the next run.




Very Important: There is a bug in the current implementation of Config's Lib (lua_fix and derived) when calling more than one config.create() in the same script.

Take a look at this example (it's untested, it's from what I remember):

FirstTable = {1,2,3, name = "alex"}
SecondTable = {"a","b", text = "Hello World!"}

config.create(FirstTable);
config.create(SecondTable);


This is a representation of what is memorized:

{
  [1] = "a",
  [2] = "b",
  [3] = 3,
  ["name"] = "alex",
  ["text"] = "Hello World!"
}

Basically the second config is overwriting the first two entries because they doesn't have a specified key so they are mapped to integers.




Quote from: garry23 on December 08, 2017, 03:42:49 PM
I have found Lua API documentation mostly helpful, but some entries are rather minimal.
Yes, it needs some improvements :)

Quote from: a1ex on December 07, 2017, 08:12:23 PM
https://bitbucket.org/hudson/magic-lantern/src/manual_lens_info/scripts/lens.lua (example for menu with custom state)
This script is using a modified version of the library, so keep it as reference if you need a complex usage but don't forget to use correct config.lua from manual_lens_info otherwise will not works with multiple menu's config in the same script as in lens.lua.

Quote from: garry23 on December 08, 2017, 03:42:49 PM
Bottom line: I am happy to support, ie I share my humble scripting attempts to help others, but I truly believe the Lua API documentation needs someone with 'insider knowledge' to add (more) value. That is 'right first time'.
@garry23 I added support for nested submenus and allowed to have separate menu entries (to avoid packing all into a single big chunk and have separate menus organized by functionality); Let me know if there is something wrong in the case you or someone else test it.

Jip-Hop

Thanks aprofiti!!

I need to take another look tomorrow, but a quick test with the config.lua from manual_lens_info you linked to solved another issue I was having.
In this script (proof of concept) I was calling config.create_from_menu multiple times.
config.create_from_menu(preset_menu_ratio)
config.create_from_menu(preset_menu_fps)
config.create_from_menu(preset_menu_a)
config.create_from_menu(preset_menu_b)
config.create_from_menu(preset_menu_c)
config.create_from_menu(preset_menu_d)

And I couldn't figure out why everything was falling apart...

With the new config.lua at least this seems to be working :D