mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Basically: * Use `extend` for class definitions * Use `new` for object instantiations That includes some minor code cleanups along the way: * Updated `Widget`'s docs to make the semantics clearer. * Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283) * Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass). * Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events. * Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier. * Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references. * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak). * Terminal: Make sure the shell is killed on plugin teardown. * InputText: Fix Home/End/Del physical keys to behave sensibly. * InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...). * OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of. * ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed! * Kobo: Minor code cleanups.
170 lines
6.7 KiB
Lua
170 lines
6.7 KiB
Lua
local Device = require("device")
|
|
|
|
if not Device:isPocketBook() --[[and not Device:isKobo()]] then
|
|
return { disabled = true }
|
|
end
|
|
|
|
local PowerD = Device:getPowerDevice()
|
|
local DataStorage = require("datastorage")
|
|
local LuaSettings = require("luasettings")
|
|
local UIManager = require("ui/uimanager")
|
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|
local SpinWidget = require("ui/widget/spinwidget")
|
|
local logger = require("logger")
|
|
local _ = require("gettext")
|
|
|
|
local AutoStandby = WidgetContainer:extend{
|
|
is_doc_only = false,
|
|
name = "autostandby",
|
|
|
|
-- static for all plugin instances
|
|
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/autostandby.lua"),
|
|
delay = 0,
|
|
lastInput = 0,
|
|
preventing = false,
|
|
}
|
|
|
|
function AutoStandby:init()
|
|
logger.dbg("AutoStandby:init() instance=", tostring(self))
|
|
if not self.settings:has("filter") then
|
|
logger.dbg("AutoStandby: No settings found, initializing defaults")
|
|
self.settings.data = {
|
|
forbidden = false, -- If forbidden, standby is never allowed to occur
|
|
filter = 1, -- Consider input only further than this many seconds apart
|
|
min = 1, -- Initial delay period during which we won't standby
|
|
mul = 1.5, -- Multiply the delay with each subsequent input that happens, scales up to max
|
|
max = 30, -- Input that happens further than 30 seconds since last input one reset delay back to 'min'
|
|
win = 5, -- Additional time window to consider input contributing to standby delay
|
|
bat = 60, -- If battery is below this percent, make auto-standby aggressive again (disables scaling by mul)
|
|
}
|
|
self.settings:flush()
|
|
end
|
|
|
|
UIManager.event_hook:registerWidget("InputEvent", self)
|
|
self.ui.menu:registerToMainMenu(self)
|
|
end
|
|
|
|
function AutoStandby:onCloseWidget()
|
|
logger.dbg("AutoStandby:onCloseWidget() instance=", tostring(self))
|
|
UIManager:unschedule(AutoStandby.allow)
|
|
end
|
|
|
|
function AutoStandby:addToMainMenu(menu_items)
|
|
menu_items.autostandby = {
|
|
sorting_hint = "device",
|
|
text = _("Auto-standby settings"),
|
|
sub_item_table = {
|
|
{
|
|
keep_menu_open = true,
|
|
text = _("Allow auto-standby"),
|
|
checked_func = function() return self:isAllowedByConfig() end,
|
|
callback = function() self.settings:saveSetting("forbidden", self:isAllowedByConfig()):flush() end,
|
|
},
|
|
self:genSpinMenuItem(_("Min input idle seconds"), "min", function() return 0 end, function() return self.settings:readSetting("max") end),
|
|
self:genSpinMenuItem(_("Max input idle seconds"), "max", function() return 0 end),
|
|
self:genSpinMenuItem(_("Input window seconds"), "win", function() return 0 end, function() return self.settings:readSetting("max") end),
|
|
self:genSpinMenuItem(_("Always standby if battery below"), "bat", function() return 0 end, function() return 100 end),
|
|
}
|
|
}
|
|
end
|
|
|
|
-- We've received touch/key event, so delay standby accordingly
|
|
function AutoStandby:onInputEvent()
|
|
logger.dbg("AutoStandby:onInputevent() instance=", tostring(self))
|
|
local config = self.settings.data
|
|
local t = os.time()
|
|
if t < AutoStandby.lastInput + config.filter then
|
|
-- packed too close together, ignore
|
|
logger.dbg("AutoStandby: input packed too close to previous one, ignoring")
|
|
return
|
|
end
|
|
|
|
-- Nuke past timer as we'll reschedule the allow (or not)
|
|
UIManager:unschedule(AutoStandby.allow)
|
|
|
|
if PowerD:getCapacityHW() <= config.bat then
|
|
-- battery is below threshold, so allow standby aggressively
|
|
logger.dbg("AutoStandby: battery below threshold, enabling aggressive standby")
|
|
self:allow()
|
|
return
|
|
elseif t > AutoStandby.lastInput + config.max then
|
|
-- too far apart, so reset delay
|
|
logger.dbg("AutoStandby: input too far in future, resetting adaptive standby delay from", AutoStandby.delay, "to", config.min)
|
|
AutoStandby.delay = config.min
|
|
elseif t < AutoStandby.lastInput + AutoStandby.delay + config.win then
|
|
-- otherwise widen the delay - "adaptive" - with frequent inputs, but don't grow beyonnd the max
|
|
AutoStandby.delay = math.min((AutoStandby.delay+1) * config.mul, config.max)
|
|
logger.dbg("AutoStandby: increasing standby delay to", AutoStandby.delay)
|
|
end -- equilibrium: when the event arrives beyond delay + win, but still below max, we keep the delay as-is
|
|
|
|
AutoStandby.lastInput = t
|
|
|
|
if not self:isAllowedByConfig() then
|
|
-- all standbys forbidden, always prevent
|
|
self:prevent()
|
|
return
|
|
elseif AutoStandby.delay == 0 then
|
|
-- If delay is 0 now, just allow straight
|
|
self:allow()
|
|
return
|
|
end
|
|
-- otherwise prevent for a while for duration of the delay
|
|
self:prevent()
|
|
-- and schedule standby re-enable once delay expires
|
|
UIManager:scheduleIn(AutoStandby.delay, AutoStandby.allow, AutoStandby)
|
|
end
|
|
|
|
-- Prevent standby (by timer)
|
|
function AutoStandby:prevent()
|
|
if not AutoStandby.preventing then
|
|
AutoStandby.preventing = true
|
|
UIManager:preventStandby()
|
|
end
|
|
end
|
|
|
|
-- Allow standby (by timer)
|
|
function AutoStandby:allow()
|
|
if AutoStandby.preventing then
|
|
AutoStandby.preventing = false
|
|
UIManager:allowStandby()
|
|
end
|
|
end
|
|
|
|
function AutoStandby:isAllowedByConfig()
|
|
return self.settings:isFalse("forbidden")
|
|
end
|
|
|
|
function AutoStandby:genSpinMenuItem(text, cfg, min, max)
|
|
return {
|
|
keep_menu_open = true,
|
|
text = text,
|
|
enabled_func = function() return self:isAllowedByConfig() end,
|
|
callback = function()
|
|
local spin = SpinWidget:new {
|
|
value = self.settings:readSetting(cfg),
|
|
value_min = min and min() or 0,
|
|
value_max = max and max() or 9999,
|
|
value_hold_step = 10,
|
|
ok_text = "Update",
|
|
title_text = text,
|
|
callback = function(spin) self.settings:saveSetting(cfg, spin.value):flush() end,
|
|
}
|
|
UIManager:show(spin)
|
|
end
|
|
}
|
|
end
|
|
|
|
-- koreader is merely waiting for user input right now.
|
|
-- UI signals us that standby is allowed at this very moment because nothing else goes on in the background.
|
|
function AutoStandby:onAllowStandby()
|
|
logger.dbg("AutoStandby: onAllowStandby()")
|
|
-- In case the OS frontend itself doesn't manage power state, we can do it on our own here.
|
|
-- One should also configure wake-up pins and perhaps wake alarm,
|
|
-- if we want to enter deeper sleep states later on from within standby.
|
|
|
|
--os.execute("echo mem > /sys/power/state")
|
|
end
|
|
|
|
return AutoStandby
|
|
|