From 40b9d09022bed4573dc8914d332578e8ac9f6079 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 5 Jul 2026 14:32:30 -0400 Subject: [PATCH] [bugfix] lua ipod mini gen 2 can't quit scripts while under load I rewrote some of the problematic scripts to use an event loop which fixed most of the issues but it turns out the underlying issue is that when the device is under load the timeout that detects a repeat press makes the key a repeat press and we miss the initial press completely due to being under load and under the gun Adds entries for PLA_EXIT and PLA_CANCEL with a Repeat press Change-Id: I8247b0ebd37fc58608f6be126c49e56f8375e9cf --- apps/plugins/lib/pluginlib_actions.c | 2 + apps/plugins/lua_scripts/memchk.lua | 62 ++++++++--- apps/plugins/lua_scripts/rb_poly.lua | 156 +++++++++++++++------------ apps/plugins/lua_scripts/rlimg.lua | 41 +++++-- 4 files changed, 172 insertions(+), 89 deletions(-) diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c index 593b2f43d2..5d2c0e323a 100644 --- a/apps/plugins/lib/pluginlib_actions.c +++ b/apps/plugins/lib/pluginlib_actions.c @@ -323,7 +323,9 @@ const struct button_mapping pla_main_ctx[] = || (CONFIG_KEYPAD == IPOD_3G_PAD) \ || (CONFIG_KEYPAD == IPOD_4G_PAD) {PLA_CANCEL, BUTTON_MENU|BUTTON_SELECT, BUTTON_NONE }, + {PLA_CANCEL, BUTTON_MENU|BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE }, {PLA_EXIT, BUTTON_PLAY|BUTTON_SELECT, BUTTON_NONE }, + {PLA_EXIT, BUTTON_PLAY|BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE }, {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE }, {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE }, diff --git a/apps/plugins/lua_scripts/memchk.lua b/apps/plugins/lua_scripts/memchk.lua index 6d9b623f31..48d8df2858 100644 --- a/apps/plugins/lua_scripts/memchk.lua +++ b/apps/plugins/lua_scripts/memchk.lua @@ -16,28 +16,58 @@ ]]-- local a = {} +local b = {} loops = 1 --global +local last_btn = 1 + +local ret = "" +local status = true +local depth = rb.LCD_DEPTH +if depth < 8 then depth = 8 end +local used, allocd, free = rb.mem_stats() +local alloc_sz = (free / (depth / 8)) / 1024 + local function alloc_tables(loops) - for i=1,loops do a[i] = {{}}; local b = {} end - return true + for i=1,loops do a[i] = {{tostring(loops * i) .. " mem test"}}; b[i] = {} end + b[1] = rb.new_image(loops, alloc_sz); +end + + +local function alloc_tables_sm(loops) + for i=1,loops do b[i] = {{}}; end + local btn = rb.button_get(false) + if (btn ~= 0) then + if last_btn ~= btn then + last_btn = btn + return false; + end + while rb.button_get(false) ~= 0 + do + + end + ret = "User Abort" + status = false + return true + end + return false end -local ret -local status = true rb.lcd_putsxy(0, 0, "memchk loops : ") while (status and loops < 1000) do rb.lcd_putsxy(0, 20, loops) rb.lcd_update() - alloc_tables(loops) + + if alloc_tables_sm(loops) then break end -- do call protected to catch OOM condition status, ret = pcall(alloc_tables, loops * 1000) loops = loops + 1 _G.loops = loops + rb.yield() end -local used, allocd, free = rb.mem_stats() +used, allocd, free = rb.mem_stats() local lu = collectgarbage("count") local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end @@ -47,10 +77,18 @@ s_t[1] = "rockbox:\n" s_t[2] = "Loops : " s_t[3] = loops - 1 s_t[4] = "\n" -s_t[5] = fmt("Used ", used) -s_t[6] = fmt("Allocd ", allocd) -s_t[7] = fmt("Free ", free) -s_t[8] = "\nlua:\n" -s_t[9] = fmt("Used", lu * 1024) -s_t[10] = "\n\nNote that the rockbox used count is a high watermark\n" +if not status == true then + s_t[5] = ret + +else + s_t[4] = "" + s_t[5] = "" +end +s_t[6] = "\n" +s_t[7] = fmt("Used ", used) +s_t[8] = fmt("Allocd ", allocd) +s_t[9] = fmt("Free ", free) +s_t[10] = "\nlua:\n" +s_t[11] = fmt("Used", lu * 1024) +s_t[12] = "\n\nNote that the rockbox used count is a high watermark\n" rb.splash_scroller(10 * rb.HZ, table.concat(s_t)) diff --git a/apps/plugins/lua_scripts/rb_poly.lua b/apps/plugins/lua_scripts/rb_poly.lua index 953e30fb6e..e02b2cc09e 100644 --- a/apps/plugins/lua_scripts/rb_poly.lua +++ b/apps/plugins/lua_scripts/rb_poly.lua @@ -273,7 +273,7 @@ local function Rot(t_pts, rot) local nw = max_x local nh = max_y - rot = rot % 7 + --rot = rot % 7 if rot == 0 then return t_pts end @@ -326,96 +326,118 @@ local function Rot(t_pts, rot) return rot_memoized[rot][pts] end -local count = -1 local function rb_logo_rot(x, y, sx, sy, rot) - local polygon - - if count >= 0 then - polygon = _poly.polygon - _lcd:clear(BLACK) - _poly.polyline(_LCD, x, y, Rot(cross_left_pts, rot), WHITE, false, true, sx, sy) - _poly.polyline(_LCD, x, y, Rot(R_shadow_pts, rot), WHITE, false, true, sx, sy) - else - polygon = function() end - end + local rot_m = rot % 7 + local rot_next = rot + 1 + local polygon = _poly.polygon + _lcd:clear(BLACK) + _poly.polyline(_LCD, x, y, Rot(cross_left_pts, rot_m), WHITE, false, true, sx, sy) + _poly.polyline(_LCD, x, y, Rot(R_shadow_pts, rot_m), WHITE, false, true, sx, sy) repeat - polygon(_LCD, x, y, Rot(R_outline_pts, rot), BLACK, YELLOW, true, sx, sy) - polygon(_LCD, x, y, Rot(R_center_pts, rot), BLACK, BLACK, true, sx, sy) - polygon(_LCD, x, y, Rot(b_outline_pts, rot), BLACK, GREY, true, sx, sy) - polygon(_LCD, x, y, Rot(b_center_pts, rot), BLACK, BLACK, true, sx, sy) + polygon(_LCD, x, y, Rot(R_outline_pts, rot_m), BLACK, YELLOW, true, sx, sy) + polygon(_LCD, x, y, Rot(R_center_pts, rot_m), BLACK, BLACK, true, sx, sy) + polygon(_LCD, x, y, Rot(b_outline_pts, rot_m), BLACK, GREY, true, sx, sy) + polygon(_LCD, x, y, Rot(b_center_pts, rot_m), BLACK, BLACK, true, sx, sy) - polygon(_LCD, x, y, Rot(clef_pts, rot), WHITE, WHITE, true, sx, sy) - polygon(_LCD, x, y, Rot(clef_void_1_pts, rot), WHITE, BLACK, true, sx, sy) - polygon(_LCD, x, y, Rot(clef_void_2_pts, rot), WHITE, YELLOW, true, sx, sy) - polygon(_LCD, x, y, Rot(clef_void_3_pts, rot), WHITE, YELLOW, true, sx, sy) + polygon(_LCD, x, y, Rot(clef_pts, rot_m), WHITE, WHITE, true, sx, sy) + polygon(_LCD, x, y, Rot(clef_void_1_pts, rot_m), WHITE, BLACK, true, sx, sy) + polygon(_LCD, x, y, Rot(clef_void_2_pts, rot_m), WHITE, YELLOW, true, sx, sy) + polygon(_LCD, x, y, Rot(clef_void_3_pts, rot_m), WHITE, YELLOW, true, sx, sy) + polygon = function() end -- don't draw but memoize the next point rot = rot + 1 - until count >= 0 or rot >= 6; + rot_m = rot % 7 + until rot > rot_next; end +-- we want the size of everything @ 1:1 scale so we can use that to flip/rotate the figure +rb_logo_sz(0, 0) + local action local redraw = true; local rot = 0 local sx = -2 local sy = -2 +local max_sx = (rb.LCD_WIDTH / max_x) * 3 +local max_sy = (rb.LCD_HEIGHT / max_y) * 3 --- we want the size of everything @ 1:1 scale so we can use that to flip/rotate the figure -rb_logo_sz(0, 0) -while true do +do + local act = rb.actions + local quit = false - if redraw then - rb_logo_rot(0,0, sx, sy, rot) - _lcd:update() - if count > 0 then - redraw = false + function action_event(action) + local event + + if action == actions.CANCEL or action == actions.EXIT then + quit = true + end + + if action == 0 then --timer timeout + rot = rot + 1 + redraw = true local prot = (rot) % 7 - if prot > 0 then + if prot > 0 then -- erase the previous rot prot = prot - 1 if prot == 0 then prot = 6 end rot_memoized[tostring(prot)] = nil end end - end - action = rb.get_plugin_action(rb.HZ/2, 1) - if action == actions.CANCEL or action == actions.EXIT then - break - end - - redraw = redraw or (action ~= actions.NONE) - - if action == actions.LEFT then - sx = sx - 1 - elseif action == actions.LEFTR then - sx = sx - 1 - sy = sy - 1 - elseif action == actions.RIGHT then - sx = sx + 1 - elseif action == actions.RIGHTR then - sx = sx + 1 - sy = sy + 1 - elseif action == actions.UP then - sy = sy - 1 - elseif action == actions.UPR then - sy = sy - 1 - sx = sy - elseif action == actions.DOWN then - sy = sy + 1 - elseif action == actions.DOWNR then - sy = sy + 1 - sx = sy - elseif action == actions.SELR then - rot = rot + 1 - count = 0; + if redraw then + --do nothing till redrawn + elseif action == actions.LEFT then + sx = sx - 1 + elseif action == actions.LEFTR then + sx = sx - 1 + sy = sy - 1 + elseif action == actions.RIGHT then + sx = sx + 1 + elseif action == actions.RIGHTR then + sx = sx + 1 + sy = sy + 1 + elseif action == actions.UP then + sy = sy - 1 + elseif action == actions.UPR then + sy = sy - 1 + sx = sy + elseif action == actions.DOWN then + sy = sy + 1 + elseif action == actions.DOWNR then + sy = sy + 1 + sx = sy + elseif action == actions.SELR then + rot = rot + 1 + count = 0; + redraw = true + else + return + end + if sx > max_sx then sx = max_sx end + if sy > max_sy then sy = max_sy end redraw = true - elseif count > 5 then - count = 0; - rot = rot + 1 - redraw = true - else - count = count + 1 end + + function action_set_quit(bQuit) + quit = bQuit + end + + function action_quit() + return quit + end +end + +local eva = rockev.register("action", action_event) +local evt = rockev.register("timer", action_event, rb.HZ * 5) + +--[[ Main loop ]] +while not action_quit() do + if redraw then + rb_logo_rot(0,0, sx, sy, rot) + _lcd:update() + redraw = false + end + rb.yield() end --wend local used, allocd, free = rb.mem_stats() diff --git a/apps/plugins/lua_scripts/rlimg.lua b/apps/plugins/lua_scripts/rlimg.lua index f9eadf2f54..3068b2d7e4 100755 --- a/apps/plugins/lua_scripts/rlimg.lua +++ b/apps/plugins/lua_scripts/rlimg.lua @@ -75,6 +75,7 @@ local BLUE = _clr.set(WHITE, 0, 0, 255) ------------------------------------------- local clrs local CANCEL_BUTTON = rb.actions.PLA_CANCEL +local EXIT_BUTTON = rb.actions.PLA_EXIT local LCD_DEPTH = rb.LCD_DEPTH -- EXAMPLES ---------------------------------------------------------------------- EXAMPLES--------------------------------------------------------------------- function my_blit(dst_val, dx, dy, src_val, sx, sy) @@ -235,8 +236,9 @@ function bounce_image(img) _img.resize(img_sqy, img) _img.resize(img_sqx, img) - -- moves definition of CANCEL_BUTTON from global to local + -- moves definition of CANCEL_BUTTON / EXIT_BUTTON from global to local local CANCEL_BUTTON = CANCEL_BUTTON + local EXIT_BUTTON = EXIT_BUTTON -------------------------------------------------------- local imgn = img local hold = 0 @@ -347,7 +349,8 @@ function bounce_image(img) end -- 0 = timeout immediately -- ( -1 would be never timeout, and >0 is amount of 'ticks' before timeout) - if rb.get_plugin_action(wait) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(wait) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break; end end @@ -444,6 +447,10 @@ function twist(img) -- calculated position of each point in the sine wave(s) local xs, xe + -- moves definition of CANCEL_BUTTON / EXIT_BUTTON from global to local + local CANCEL_BUTTON = CANCEL_BUTTON + local EXIT_BUTTON = EXIT_BUTTON + --[[--Profiling code local timer = _timer.start()]] @@ -527,8 +534,8 @@ function twist(img) _lcd:update() z = z + zi - - if rb.get_plugin_action(0) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(0) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break end collectgarbage("step") @@ -556,7 +563,8 @@ function draw_target(img) end _lcd:update() - if rb.get_plugin_action( 20) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(rb.HZ / 5) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then z = 16; break; end @@ -596,7 +604,8 @@ function draw_sweep(img, cx, cy, radius, color) elseif wait < 50 then wait = 50 - wait end - if rb.get_plugin_action( wait) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(wait) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break end end @@ -622,6 +631,10 @@ function rotate_image(img) screen_img :copy(_LCD, 1, 1, xr, yr, w, h) --_print.f("CW") + -- moves definition of CANCEL_BUTTON / EXIT_BUTTON from global to local + local CANCEL_BUTTON = CANCEL_BUTTON + local EXIT_BUTTON = EXIT_BUTTON + --[[--Profiling code local timer = _timer.start()]] @@ -660,7 +673,8 @@ function rotate_image(img) end d = d + i - if rb.get_plugin_action(0) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(0) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break; end end @@ -686,6 +700,10 @@ function flip_image(img) screen_img =_img.new(w, h) screen_img :copy(_LCD, 1, 1, x, y, w, h) + -- moves definition of CANCEL_BUTTON / EXIT_BUTTON from global to local + local CANCEL_BUTTON = CANCEL_BUTTON + local EXIT_BUTTON = EXIT_BUTTON + --[[--Profiling code local timer = _timer.start()]] @@ -707,7 +725,8 @@ function flip_image(img) d = d + i - if rb.get_plugin_action(rb.HZ) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(rb.HZ) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break; end end @@ -733,7 +752,8 @@ function blit_mask(dst) dst:copy(bmask, 1, 1, 1, 1, nil, nil, false, _blit.BSAND, color) _lcd:update() - if rb.get_plugin_action(0) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(0) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break end end @@ -823,7 +843,8 @@ function long_text() _lcd:copy(img, 1, _lcd.H - h, w - p, 1) _lcd:update() if p == 0 or w - p == 1 then wait = 100; rb.sleep(50) end - if rb.get_plugin_action(wait) == CANCEL_BUTTON then + local btn = rb.get_plugin_action(wait) + if btn == CANCEL_BUTTON or btn == EXIT_BUTTON then break end end