mirror of https://github.com/koreader/koreader
AutoFrontlight plugin (#2941)
* Add AutoFrontlight plugin * Add configuration to control autofrontlight featurepull/2962/head
parent
ed0ba6737e
commit
53eb4dee50
@ -0,0 +1,64 @@
|
|||||||
|
local Device = require("device")
|
||||||
|
|
||||||
|
if not Device:isKindle() or
|
||||||
|
(Device.model ~= "KindleVoyage" and Device.model ~= "KindleOasis") then
|
||||||
|
return { disabled = true, }
|
||||||
|
end
|
||||||
|
|
||||||
|
local DataStorage = require("datastorage")
|
||||||
|
local LuaSettings = require("luasettings")
|
||||||
|
local UIManager = require("ui/uimanager")
|
||||||
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||||
|
local logger = require("logger")
|
||||||
|
|
||||||
|
local AutoFrontlight = {
|
||||||
|
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/autofrontlight.lua"),
|
||||||
|
settings_id = 0,
|
||||||
|
enabled = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
function AutoFrontlight:_schedule()
|
||||||
|
if not self.enabled then
|
||||||
|
logger.dbg("AutoFrontlight:_schedule() is disabled")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local settings_id = self.settings_id
|
||||||
|
logger.dbg("AutoFrontlight:_schedule() @ ", os.time(), ", it should be executed at ", os.time() + 1)
|
||||||
|
UIManager:scheduleIn(1, function()
|
||||||
|
self:_action(settings_id)
|
||||||
|
self:_schedule(self.settings_id)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function AutoFrontlight:_action(settings_id)
|
||||||
|
if settings_id ~= self.settings_id then
|
||||||
|
logger.dbg("AutoFrontlight:_action(): registered settings_id ",
|
||||||
|
settings_id,
|
||||||
|
" does not equal to current one ",
|
||||||
|
self.settings_id)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
logger.dbg("AutoFrontlight:_action() @ ", os.time())
|
||||||
|
if Device:ambientBrightnessLevel() <= 1 then
|
||||||
|
logger.dbg("AutoFrontlight: going to turn on frontlight")
|
||||||
|
Device:getPowerDevice():turnOnFrontlight()
|
||||||
|
else
|
||||||
|
logger.dbg("AutoFrontlight: going to turn off frontlight")
|
||||||
|
Device:getPowerDevice():turnOffFrontlight()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AutoFrontlight:init()
|
||||||
|
self.enabled = not self.settings:nilOrFalse("enable")
|
||||||
|
logger.dbg("AutoFrontlight:init() self.enabled: ", self.enabled)
|
||||||
|
self:_schedule()
|
||||||
|
end
|
||||||
|
|
||||||
|
AutoFrontlight:init()
|
||||||
|
|
||||||
|
local AutoFrontlightWidget = WidgetContainer:new{
|
||||||
|
name = "AutoFrontlight",
|
||||||
|
}
|
||||||
|
|
||||||
|
return AutoFrontlightWidget
|
@ -0,0 +1,48 @@
|
|||||||
|
describe("AutoFrontlight widget tests", function()
|
||||||
|
local Device, MockTime
|
||||||
|
|
||||||
|
setup(function()
|
||||||
|
require("commonrequire")
|
||||||
|
package.unloadAll()
|
||||||
|
|
||||||
|
Device = require("device/generic/device"):new()
|
||||||
|
Device.brightness = 0
|
||||||
|
Device.hasFrontlight = function() return true end
|
||||||
|
Device.powerd = require("device/generic/powerd"):new{
|
||||||
|
frontlight = 0,
|
||||||
|
}
|
||||||
|
Device.powerd.frontlightIntensityHW = function()
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
Device.powerd.setIntensityHW = function(self, intensity)
|
||||||
|
self.frontlight = intensity
|
||||||
|
end
|
||||||
|
Device.ambientBrightnessLevel = function(self)
|
||||||
|
return self.brightness
|
||||||
|
end
|
||||||
|
|
||||||
|
MockTime = require("mock_time")
|
||||||
|
MockTime:install()
|
||||||
|
end)
|
||||||
|
|
||||||
|
teardown(function()
|
||||||
|
MockTime:uninstall()
|
||||||
|
package.unloadAll()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should automatically turn on or off frontlight", function()
|
||||||
|
local UIManager = require("ui/uimanager")
|
||||||
|
Device.brightness = 0
|
||||||
|
MockTime:increase(2)
|
||||||
|
assert.are.equal(Device:getPowerDevice().frontlight, 2)
|
||||||
|
Device.brightness = 1
|
||||||
|
MockTime:increase(2)
|
||||||
|
assert.are.equal(Device:getPowerDevice().frontlight, 2)
|
||||||
|
Device.brightness = 2
|
||||||
|
MockTime:increase(2)
|
||||||
|
assert.are.equal(Device:getPowerDevice().frontlight, 0)
|
||||||
|
Device.brightness = 3
|
||||||
|
MockTime:increase(2)
|
||||||
|
assert.are.equal(Device:getPowerDevice().frontlight, 0)
|
||||||
|
end)
|
||||||
|
end)
|
@ -0,0 +1,73 @@
|
|||||||
|
describe("AutoFrontlight widget tests", function()
|
||||||
|
local Device, PowerD, MockTime
|
||||||
|
|
||||||
|
setup(function()
|
||||||
|
require("commonrequire")
|
||||||
|
package.unloadAll()
|
||||||
|
|
||||||
|
MockTime = require("mock_time")
|
||||||
|
MockTime:install()
|
||||||
|
|
||||||
|
PowerD = require("device/generic/powerd"):new{
|
||||||
|
frontlight = 0,
|
||||||
|
}
|
||||||
|
PowerD.frontlightIntensityHW = function()
|
||||||
|
return 2
|
||||||
|
end
|
||||||
|
PowerD.setIntensityHW = function(self, intensity)
|
||||||
|
self.frontlight = intensity
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
teardown(function()
|
||||||
|
MockTime:uninstall()
|
||||||
|
package.unloadAll()
|
||||||
|
end)
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
Device = require("device")
|
||||||
|
Device.isKindle = function() return true end
|
||||||
|
Device.model = "KindleVoyage"
|
||||||
|
Device.brightness = 0
|
||||||
|
Device.hasFrontlight = function() return true end
|
||||||
|
Device.powerd = PowerD:new{
|
||||||
|
device = Device,
|
||||||
|
}
|
||||||
|
Device.ambientBrightnessLevel = function(self)
|
||||||
|
return self.brightness
|
||||||
|
end
|
||||||
|
Device.input.waitEvent = function() end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should automatically turn on or off frontlight", function()
|
||||||
|
local UIManager = require("ui/uimanager")
|
||||||
|
UIManager._run_forever = true
|
||||||
|
require("luasettings"):
|
||||||
|
open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"):
|
||||||
|
saveSetting("enable", "true"):
|
||||||
|
close()
|
||||||
|
local class = dofile("plugins/autofrontlight.koplugin/main.lua")
|
||||||
|
local AutoFrontlight = class:new()
|
||||||
|
AutoFrontlight:init()
|
||||||
|
Device.brightness = 3
|
||||||
|
MockTime:increase(1)
|
||||||
|
UIManager:handleInput()
|
||||||
|
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
||||||
|
Device.brightness = 0
|
||||||
|
MockTime:increase(1)
|
||||||
|
UIManager:handleInput()
|
||||||
|
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
||||||
|
Device.brightness = 1
|
||||||
|
MockTime:increase(1)
|
||||||
|
UIManager:handleInput()
|
||||||
|
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
||||||
|
Device.brightness = 2
|
||||||
|
MockTime:increase(1)
|
||||||
|
UIManager:handleInput()
|
||||||
|
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
||||||
|
Device.brightness = 3
|
||||||
|
MockTime:increase(1)
|
||||||
|
UIManager:handleInput()
|
||||||
|
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
||||||
|
end)
|
||||||
|
end)
|
@ -0,0 +1,185 @@
|
|||||||
|
describe("Frontlight function in PowerD", function()
|
||||||
|
local PowerD, device
|
||||||
|
setup(function()
|
||||||
|
require("commonrequire")
|
||||||
|
|
||||||
|
PowerD = require("device/generic/powerd"):new{
|
||||||
|
frontlight = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
param = {
|
||||||
|
fl_min = 1,
|
||||||
|
fl_max = 5,
|
||||||
|
device = {
|
||||||
|
hasFrontlight = function() return true end
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
frontlight = param.fl_min
|
||||||
|
stub(PowerD, "init")
|
||||||
|
stub(PowerD, "frontlightIntensityHW")
|
||||||
|
stub(PowerD, "setIntensityHW")
|
||||||
|
PowerD.setIntensityHW = function(self, intensity)
|
||||||
|
self.frontlight = intensity
|
||||||
|
end
|
||||||
|
spy.on(PowerD, "setIntensityHW")
|
||||||
|
spy.on(PowerD, "turnOnFrontlightHW")
|
||||||
|
spy.on(PowerD, "turnOffFrontlightHW")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should read frontlight intensity during initialization", function()
|
||||||
|
PowerD.frontlightIntensityHW.returns(2)
|
||||||
|
local p = PowerD:new(param)
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.init).is_called(1)
|
||||||
|
assert.stub(p.frontlightIntensityHW).is_called(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
test_when_off = function(fl_min)
|
||||||
|
param.fl_min = fl_min
|
||||||
|
PowerD.frontlightIntensityHW.returns(fl_min)
|
||||||
|
local p = PowerD:new(param)
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.init).is_called(1)
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.are.equal(param.fl_min, p.frontlight)
|
||||||
|
assert.stub(p.frontlightIntensityHW).is_called(1)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
-- The intensity is param.fl_min, turnOnFrontlight() should take no effect.
|
||||||
|
assert.is.falsy(p:turnOnFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
-- Same as the above one, toggleFrontlight() should also take no effect.
|
||||||
|
assert.is.falsy(p:toggleFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
assert.is.truthy(p:setIntensity(2))
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(2)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
assert.is.falsy(p:turnOnFrontlight())
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(2)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
assert.is.truthy(p:turnOffFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(3)
|
||||||
|
assert.are.equal(param.fl_min, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(0)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(2)
|
||||||
|
|
||||||
|
assert.is.truthy(p:turnOnFrontlight())
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(4)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(2)
|
||||||
|
|
||||||
|
assert.is.truthy(p:toggleFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(5)
|
||||||
|
assert.are.equal(param.fl_min, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(3)
|
||||||
|
|
||||||
|
assert.is.truthy(p:toggleFrontlight())
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(6)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(2)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
test_when_on = function(fl_min)
|
||||||
|
assert(fl_min < 2)
|
||||||
|
param.fl_min = fl_min
|
||||||
|
PowerD.frontlightIntensityHW.returns(2)
|
||||||
|
local p = PowerD:new(param)
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.init).is_called(1)
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(0)
|
||||||
|
|
||||||
|
assert.is.falsy(p:setIntensity(2))
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(0)
|
||||||
|
|
||||||
|
assert.is.falsy(p:turnOnFrontlight())
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(1)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(0)
|
||||||
|
|
||||||
|
assert.is.truthy(p:turnOffFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(2)
|
||||||
|
assert.are.equal(param.fl_min, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(1)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
assert.is.truthy(p:toggleFrontlight())
|
||||||
|
assert.are.equal(2, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOn())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(3)
|
||||||
|
assert.are.equal(2, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(2)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(1)
|
||||||
|
|
||||||
|
assert.is.truthy(p:toggleFrontlight())
|
||||||
|
assert.are.equal(0, p:frontlightIntensity())
|
||||||
|
assert.is.truthy(p:isFrontlightOff())
|
||||||
|
assert.stub(p.setIntensityHW).is_called(4)
|
||||||
|
assert.are.equal(param.fl_min, p.frontlight)
|
||||||
|
assert.spy(p.turnOnFrontlightHW).is_called(2)
|
||||||
|
assert.spy(p.turnOffFrontlightHW).is_called(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it("should turn on and off frontlight when the frontlight was off", function()
|
||||||
|
test_when_off(0)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should turn on and off frontlight when the minimum level is 1 and frontlight was off",
|
||||||
|
function() test_when_off(1) end)
|
||||||
|
|
||||||
|
it("should turn on and off frontlight when the frontlight was on", function()
|
||||||
|
test_when_on(0)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("should turn on and off frontlight when the minimum level is 1 and frontlight was on",
|
||||||
|
function() test_when_on(1) end)
|
||||||
|
end)
|
@ -0,0 +1,45 @@
|
|||||||
|
local MockTime = {
|
||||||
|
original_os_time = os.time,
|
||||||
|
original_util_time = nil,
|
||||||
|
value = os.time(),
|
||||||
|
}
|
||||||
|
|
||||||
|
function MockTime:install()
|
||||||
|
assert(self ~= nil)
|
||||||
|
local util = require("ffi/util")
|
||||||
|
if self.original_util_time == nil then
|
||||||
|
self.original_util_time = util.gettime
|
||||||
|
assert(self.original_util_time ~= nil)
|
||||||
|
end
|
||||||
|
os.time = function() return self.value end
|
||||||
|
util.gettime = function() return self.value, 0 end
|
||||||
|
end
|
||||||
|
|
||||||
|
function MockTime:uninstall()
|
||||||
|
assert(self ~= nil)
|
||||||
|
local util = require("ffi/util")
|
||||||
|
os.time = self.original_os_time
|
||||||
|
if self.original_util_time ~= nil then
|
||||||
|
util.gettime = self.original_util_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function MockTime:set(value)
|
||||||
|
assert(self ~= nil)
|
||||||
|
if type(value) ~= "number" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
self.value = math.floor(value)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function MockTime:increase(value)
|
||||||
|
assert(self ~= nil)
|
||||||
|
if type(value) ~= "number" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
self.value = math.floor(self.value + value)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return MockTime
|
Loading…
Reference in New Issue