[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
This commit is contained in:
William Wilgus 2026-07-05 14:32:30 -04:00
parent ebf42dae68
commit 40b9d09022
4 changed files with 172 additions and 89 deletions

View file

@ -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 },

View file

@ -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))

View file

@ -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,66 +326,67 @@ 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
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), 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
_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
if redraw then
--do nothing till redrawn
elseif action == actions.LEFT then
sx = sx - 1
elseif action == actions.LEFTR then
sx = sx - 1
@ -409,13 +410,34 @@ while true do
rot = rot + 1
count = 0;
redraw = true
elseif count > 5 then
count = 0;
rot = rot + 1
redraw = true
else
count = count + 1
return
end
if sx > max_sx then sx = max_sx end
if sy > max_sy then sy = max_sy end
redraw = true
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()

View file

@ -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