Commit d0f9af08 authored by alex@thinkpad's avatar alex@thinkpad
Browse files

menu.set: reworked to fix issues with certain menus, e.g. FPS override

https://www.magiclantern.fm/forum/index.php?topic=14828.msg199771#msg199771

--HG--
branch : lua_fix
parent 64666b019e52
......@@ -306,6 +306,7 @@ function test_camera_gui()
end
lv.stop()
assert(not lv.enabled)
printf("Canon GUI tests completed.\n")
printf("\n")
......@@ -347,9 +348,43 @@ function test_menu()
sleep(1)
assert(menu.select("Overlay"))
assert(menu.select("Movie"))
assert(menu.select("Shoot"))
-- perform the next test in LiveView
menu.close()
lv.start()
assert(lv.enabled)
assert(lv.running)
menu.open()
assert(menu.select("Movie", "FPS override"))
assert(menu.set("Movie", "FPS override", "OFF")) -- "OFF" and "ON" are boolean matches for zero/nonzero internal state
assert(menu.get("Movie", "FPS override") == "OFF")
assert(menu.set("FPS override", "Desired FPS", "23.976")) -- this menu entry will print "23.976 (from 25)" or something like that
assert(menu.get("FPS override", "Desired FPS"):sub(1,13) == "23.976 (from ")
assert(menu.set("FPS override", "Desired FPS", "5")) -- this menu entry will print "5 (from 30)" or something like that
assert(menu.get("FPS override", "Desired FPS"):sub(1,8) == "5 (from ")
assert(menu.set("FPS override", "Desired FPS", "10")) -- this menu entry will print "10 (from 25)" or something like that
assert(menu.get("FPS override", "Desired FPS"):sub(1,9) == "10 (from ")
assert(menu.set("FPS override", "Optimize for", "Exact FPS")) -- nothing fancy here, just request exact frame rate
assert(menu.get("FPS override", "Optimize for") == "Exact FPS")
assert(menu.set("Movie", "FPS override", "ON")) -- enable FPS override
assert(menu.get("Movie", "FPS override") ~= "ON") -- the menu entry will print something else
sleep(2) -- switching the frame rate takes a while
assert(menu.get("Movie", "FPS override") == "10.000") -- it should eventually settle to our requested value
assert(menu.get("FPS override", "Actual FPS") == "10.000") -- current FPS value can be read from here
assert(menu.set("Movie", "FPS override", "OFF")) -- that was it
assert(menu.get("Movie", "FPS override") == "OFF") -- make sure it's turned off
-- LiveView test completed
menu.close()
lv.stop()
assert(not lv.running)
assert(not lv.enabled)
menu.open()
assert(menu.select("Shoot"))
assert(menu.select("Shoot", "Advanced Bracket"))
-- boolean items should be set-able as int (0 or 1)
......@@ -369,6 +404,14 @@ function test_menu()
assert(menu.get("Shoot", "Advanced Bracket") == "OFF")
sleep(1)
-- "ON" and "OFF" are interpreted as booleans,
-- even if the menu entry doesn't display exactly this string
assert(menu.set("Shoot", "Advanced Bracket", "ON"))
assert(menu.get("Shoot", "Advanced Bracket") ~= "ON")
assert(menu.get("Shoot", "Advanced Bracket") ~= "OFF")
assert(menu.set("Shoot", "Advanced Bracket", "OFF"))
assert(menu.get("Shoot", "Advanced Bracket") == "OFF")
assert(menu.set("Shoot", "Intervalometer", 0))
assert(menu.get("Shoot", "Intervalometer", 0) == 0)
assert(menu.get("Shoot", "Intervalometer") == "OFF")
......
......@@ -6536,14 +6536,21 @@ int menu_set_str_value_from_script(const char* name, const char* entry_name, cha
return INT_MIN;
}
/* if the menu item has multiple choices defined,
* or just a valid min/max range, it's easy */
if (IS_ML_PTR(entry->priv) && (entry->choices || (entry->max > entry->min)))
/* FIXME: trying to print INT_MIN crashes Canon's vsnprintf?! */
printf(
(value_int == INT_MIN) ? "menu.set('%s', '%s', '%s')\n"
: "menu.set('%s', '%s', '%s', %d)\n",
name, entry_name, value, value_int
);
/* if the menu item has multiple choices defined, it's easy */
if (IS_ML_PTR(entry->priv) && entry->choices)
{
for (int i = entry->min; i < entry->max; i++)
{
if (streq(value, pickbox_string(entry, i)))
{
printf("menu.set('%s', '%s'): pickbox entry #%d\n", entry_name, value, i);
*(int*)(entry->priv) = i;
return 1;
}
......@@ -6570,47 +6577,74 @@ int menu_set_str_value_from_script(const char* name, const char* entry_name, cha
* - timeout 2 seconds
*/
int wait_retries = 0;
int tstart = get_ms_clock();
for (int i = 0; get_ms_clock() - tstart < 2000; i++)
int wait_after_toggle = 0;
int start_time = get_ms_clock();
int elapsed_time = 0;
for (int i = 0; (elapsed_time = get_ms_clock() - start_time) < 2000; i++)
{
if (wait_after_toggle)
{
/* maybe we need to wait for other tasks? */
int delay = (elapsed_time < 500) ? 200 :
(elapsed_time < 1500) ? 50 : 10;
//~ printf("menu.set('%s', '%s'): wait for %d ms\n", entry_name, value, delay);
msleep(delay);
}
char* current = menu_get_str_value_from_script_do(name, entry_name, &info);
//~ printf("menu.set('%s', '%s'): current '%s'\n", entry_name, value, current);
if (streq(current, value))
{
//~ printf("menu_set('%s', '%s'): match str (%s)\n", entry_name, value, current);
printf("menu.set('%s', '%s'): matched string (%s)\n", entry_name, value, current);
goto ok; // success!!
}
/* optional argument to allow numeric match? */
if (value_int != INT_MIN && IS_ML_PTR(entry->priv) && CURRENT_VALUE == value_int)
{
//~ printf("menu_set('%s', '%s'): match int (%d, %s)\n", entry_name, value, value_int, current);
printf("menu.set('%s', '%s'): matched integer (%d, %s)\n", entry_name, value, value_int, current);
goto ok; // also success!
}
/* boolean match with "ON" ? */
if (streq(value, "ON") && IS_ML_PTR(entry->priv) && CURRENT_VALUE != 0)
{
printf("menu.set('%s', '%s'): matched boolean ('%s')\n", entry_name, value, current);
goto ok; // also success!
}
/* boolean match with "OFF" ? */
if (streq(value, "OFF") && IS_ML_PTR(entry->priv) && CURRENT_VALUE == 0)
{
printf("menu.set('%s', '%s'): matched boolean ('%s')\n", entry_name, value, current);
goto ok; // also success!
}
/* accept 3500 instead of 3500K, or ON instead of ON,blahblah
* but not 160 instead of 1600, or 1m instead of 1m10s */
int len_val = strlen(value);
int len_cur = strlen(current);
if (len_val < len_cur && startswith(current, value))
{
/* comma after the requested value? ok, assume separator */
if (current[len_val] == ',')
/* comma or space after the requested value? ok, assume separator */
if (current[len_val] == ',' || current[len_val] == ' ')
{
//~ printf("menu_set('%s', '%s'): match comma (%s)\n", entry_name, value, current);
printf("menu.set('%s', '%s'): matched separator (%s)\n", entry_name, value, current);
goto ok;
}
/* requested 10, got 10m? accept (but refuse 105) */
if (len_cur == len_val + 1 && !isdigit(current[len_val]))
{
//~ printf("menu_set('%s', '%s'): match 1-chr suffix (%s)\n", entry_name, value, current);
printf("menu.set('%s', '%s'): matched 1-char suffix (%s)\n", entry_name, value, current);
goto ok;
}
/* requested 10, got 10cm? accept (but refuse 10.5) */
if (len_cur == len_val + 2 && !isdigit(current[len_val]) && !isdigit(current[len_val+1]))
{
//~ printf("menu_set('%s', '%s'): match 2-chr suffix (%s)\n", entry_name, value, current);
printf("menu.set('%s', '%s'): matched 2-char suffix (%s)\n", entry_name, value, current);
goto ok;
}
}
......@@ -6620,28 +6654,31 @@ int menu_set_str_value_from_script(const char* name, const char* entry_name, cha
if (wait_retries < 5)
{
/* we may need to wait for other tasks */
//~ printf("menu_set('%s', '%s'): wait (%s, %d)\n", entry_name, value, current, retries);
//~ printf("menu.set('%s', '%s'): wait (%s, %d)\n", entry_name, value, current, wait_retries);
msleep(100);
wait_retries++;
/* check the current string again */
continue;
}
printf("menu_set('%s', '%s'): value not changing (%s)\n", entry_name, value, current);
printf("menu.set('%s', '%s'): value not changing (%s)\n", entry_name, value, current);
break;
}
if (i > 0 && streq(current, first)) // back to first value? stop here
{
printf("menu_set('%s', '%s'): back to first value (%s)\n", entry_name, value, current);
if (!wait_after_toggle)
{
/* we may need to wait for other tasks */
printf("menu.set('%s', '%s'): let's try once more\n", entry_name, value);
wait_after_toggle = 1;
i = -1;
continue;
}
printf("menu.set('%s', '%s'): back to first value (%s)\n", entry_name, value, current);
break;
}
// for debugging, print this always
if (i > 50 && i % 10 == 0) // it's getting fishy, maybe it's good to show some progress
{
printf("menu_set('%s', '%s') [%d]: trying %s (%d), was %s...\n", entry_name, value, i, current, CURRENT_VALUE, last);
}
snprintf(last, sizeof(last), "%s", current);
wait_retries = 0;
......@@ -6649,11 +6686,9 @@ int menu_set_str_value_from_script(const char* name, const char* entry_name, cha
if (entry->select)
{
/* custom menu selection logic */
//~ printf("menu.set('%s', '%s'): custom select\n", entry_name, value);
entry->select( entry->priv, 1);
/* fixme: will crash in file_man */
/* the custom logic might rely on other tasks to update */
msleep(50);
}
else if IS_ML_PTR(entry->priv)
{
......@@ -6675,15 +6710,19 @@ int menu_set_str_value_from_script(const char* name, const char* entry_name, cha
}
else
{
printf("menu_set('%s', '%s') don't know how to toggle\n", entry_name, value);
printf("menu.set('%s', '%s'): don't know how to toggle\n", entry_name, value);
break;
}
}
printf("Could not set value '%s' for menu %s -> %s\n", value, name, entry_name);
printf("menu.set('%s', '%s'): giving up after %d ms\n", entry_name, value, elapsed_time);
give_semaphore(menu_sem);
return 0; // boo :(
ok:
if (elapsed_time > 1000) {
printf("menu.set('%s', '%s'): took %d ms\n", entry_name, value, elapsed_time);
}
give_semaphore(menu_sem);
return 1; // :)
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment