[bugfix] lua ipod mini gen 2 can't quit scripts while under load

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]> Sun, 5 Jul 2026 22:19:15 -0400
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 40b9d09022bed4573dc8914d332578e8ac9f6079
Author: William Wilgus <[email protected]>
Date:   Sun Jul 5 14:32:30 2026 -0400

    [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

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(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(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_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
+
+        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
     end
 
-    action = rb.get_plugin_action(rb.HZ/2, 1)
-    if action == actions.CANCEL or action == actions.EXIT then
-        break
+    function action_set_quit(bQuit)
+        quit = bQuit
     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;
-        redraw = true
-    elseif count > 5 then
-        count = 0;
-        rot = rot + 1
-        redraw = true
-    else
-        count = count + 1
+    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
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs