2014-10-03 08:11:53 +00:00
#!./luajit
2016-12-29 08:10:38 +00:00
io.stdout : write ( [ [
2016-10-15 03:36:00 +00:00
---------------------------------------------
launching ...
_ _____ ____ _
| |/ / _ \ | _ \ ___ __ _ __ | | ___ _ __
| ' / | | | |_) / _ \ / _` |/ _` |/ _ \ ' __ |
| . \ | _ | | _ < __ / ( _ | | ( _ | | __ / |
| _ | \ _ \ ___ /| _ | \ _ \ ___ | \ __ , _ | \ __ , _ | \ ___ | _ |
2018-03-05 22:27:03 +00:00
It ' s a scroll... It ' s a codex ... It ' s KOReader!
[ * ] Current time : ] ] , os.date ( " %x-%X " ) , " \n " )
2016-10-22 07:53:02 +00:00
io.stdout : flush ( )
2016-10-15 03:36:00 +00:00
2019-12-06 21:55:30 +00:00
-- Load default settings
2016-11-13 07:44:06 +00:00
require ( " defaults " )
2015-06-15 08:46:43 +00:00
local DataStorage = require ( " datastorage " )
pcall ( dofile , DataStorage : getDataDir ( ) .. " /defaults.persistent.lua " )
2014-09-25 14:22:30 +00:00
2019-12-06 21:55:30 +00:00
-- Set up Lua and ffi search paths
2016-11-13 07:44:06 +00:00
require ( " setupkoenv " )
2015-02-18 17:37:36 +00:00
2018-03-05 22:27:03 +00:00
io.stdout : write ( " [*] Version: " , require ( " version " ) : getCurrentRevision ( ) , " \n \n " )
io.stdout : flush ( )
2019-12-06 21:55:30 +00:00
-- Read settings and check for language override
-- Has to be done before requiring other files because
2014-01-18 22:04:14 +00:00
-- they might call gettext on load
2016-06-12 18:28:44 +00:00
G_reader_settings = require ( " luasettings " ) : open (
DataStorage : getDataDir ( ) .. " /settings.reader.lua " )
2014-01-19 17:59:27 +00:00
local lang_locale = G_reader_settings : readSetting ( " language " )
2019-12-06 21:55:33 +00:00
-- Allow quick switching to Arabic for testing RTL/UI mirroring
if os.getenv ( " KO_RTL " ) then lang_locale = " ar_AA " end
2016-11-13 07:44:06 +00:00
local _ = require ( " gettext " )
2014-01-19 17:59:27 +00:00
if lang_locale then
2014-03-13 13:52:43 +00:00
_.changeLang ( lang_locale )
2014-01-18 22:04:14 +00:00
end
2019-03-29 19:12:09 +00:00
-- Make the C blitter optional (ffi/blitbuffer.lua will check that env var)
local ffi = require ( " ffi " )
local dummy = require ( " ffi/posix_h " )
local C = ffi.C
if G_reader_settings : isTrue ( " dev_no_c_blitter " ) then
if ffi.os == " Windows " then
C._putenv ( " KO_NO_CBB=true " )
else
C.setenv ( " KO_NO_CBB " , " true " , 1 )
end
else
if ffi.os == " Windows " then
C._putenv ( " KO_NO_CBB=false " )
else
C.unsetenv ( " KO_NO_CBB " )
end
end
2019-12-06 21:55:30 +00:00
-- Should check DEBUG option in arg and turn on DEBUG before loading other
2019-09-11 18:00:44 +00:00
-- modules, otherwise DEBUG in some modules may not be printed.
local dbg = require ( " dbg " )
if G_reader_settings : isTrue ( " debug " ) then dbg : turnOn ( ) end
if G_reader_settings : isTrue ( " debug " ) and G_reader_settings : isTrue ( " debug_verbose " ) then dbg : setVerbose ( true ) end
2019-02-18 16:01:00 +00:00
2019-12-06 21:55:30 +00:00
-- Option parsing:
2013-10-18 20:38:07 +00:00
local longopts = {
2014-03-13 13:52:43 +00:00
debug = " d " ,
profile = " p " ,
help = " h " ,
2012-06-11 16:37:58 +00:00
}
2014-09-03 04:09:25 +00:00
local function showusage ( )
2014-06-05 06:58:53 +00:00
print ( " usage: ./reader.lua [OPTION] ... path " )
print ( " Read all the books on your E-Ink reader " )
2014-03-13 13:52:43 +00:00
print ( " " )
2014-06-05 06:58:53 +00:00
print ( " -d start in debug mode " )
2016-08-12 06:05:18 +00:00
print ( " -v debug in verbose mode " )
2014-06-05 11:06:35 +00:00
print ( " -p enable Lua code profiling " )
2014-06-05 06:58:53 +00:00
print ( " -h show this usage help " )
2014-03-13 13:52:43 +00:00
print ( " " )
2014-06-05 06:58:53 +00:00
print ( " If you give the name of a directory instead of a file path, a file " )
print ( " chooser will show up and let you select a file " )
2014-03-13 13:52:43 +00:00
print ( " " )
2014-06-05 06:58:53 +00:00
print ( " If you don't pass any path, the last viewed document will be opened " )
2014-03-13 13:52:43 +00:00
print ( " " )
2014-06-05 11:23:54 +00:00
print ( " This software is licensed under the AGPLv3. " )
2014-06-05 06:58:53 +00:00
print ( " See http://github.com/koreader/koreader for more info. " )
2012-06-11 16:37:58 +00:00
end
2014-11-06 07:07:50 +00:00
local Profiler = nil
2014-10-03 08:11:53 +00:00
local ARGV = arg
2012-11-01 02:02:53 +00:00
local argidx = 1
2013-08-06 14:53:44 +00:00
while argidx <= # ARGV do
2014-03-13 13:52:43 +00:00
local arg = ARGV [ argidx ]
argidx = argidx + 1
if arg == " -- " then break end
-- parse longopts
if arg : sub ( 1 , 2 ) == " -- " then
local opt = longopts [ arg : sub ( 3 ) ]
if opt ~= nil then arg = " - " .. opt end
end
-- code for each option
if arg == " -h " then
return showusage ( )
elseif arg == " -d " then
2016-10-25 07:08:47 +00:00
dbg : turnOn ( )
2016-08-12 06:05:18 +00:00
elseif arg == " -v " then
2016-10-25 07:08:47 +00:00
dbg : setVerbose ( true )
2014-03-13 13:52:43 +00:00
elseif arg == " -p " then
2014-05-01 03:58:05 +00:00
Profiler = require ( " jit.p " )
Profiler.start ( " la " )
2014-03-13 13:52:43 +00:00
else
-- not a recognized option, should be a filename
argidx = argidx - 1
break
end
2012-06-11 16:37:58 +00:00
end
2019-12-06 21:55:30 +00:00
-- Setup device
2019-09-11 18:00:44 +00:00
local Device = require ( " device " )
2019-12-06 21:55:30 +00:00
-- DPI
2019-09-11 18:00:44 +00:00
local dpi_override = G_reader_settings : readSetting ( " screen_dpi " )
if dpi_override ~= nil then
Device : setScreenDPI ( dpi_override )
end
2019-12-06 21:55:30 +00:00
-- Night mode
2019-04-08 21:05:08 +00:00
if G_reader_settings : isTrue ( " night_mode " ) then
2016-03-21 23:30:45 +00:00
Device.screen : toggleNightMode ( )
2014-06-08 06:06:04 +00:00
end
2019-12-06 21:55:30 +00:00
-- Dithering
2019-04-18 21:26:53 +00:00
if Device : hasEinkScreen ( ) then
Device.screen : setupDithering ( )
if Device.screen . hw_dithering and G_reader_settings : isTrue ( " dev_no_hw_dither " ) then
Device.screen : toggleHWDithering ( )
end
if Device.screen . sw_dithering and G_reader_settings : isTrue ( " dev_no_sw_dither " ) then
Device.screen : toggleSWDithering ( )
end
end
2012-06-11 16:37:58 +00:00
2019-12-06 21:55:30 +00:00
-- Handle global settings migration
local SettingsMigration = require ( " ui/data/settings_migration " )
SettingsMigration : migrateSettings ( G_reader_settings )
-- Document renderers canvas
local CanvasContext = require ( " document/canvascontext " )
CanvasContext : init ( Device )
2020-01-02 13:00:55 +00:00
-- Touch screen (this may display some widget, on first install on Kobo Touch,
-- so have it done after CanvasContext:init() but before Bidi.setup() to not
-- have mirroring mess x/y probing).
if Device : needsTouchScreenProbe ( ) then
Device : touchScreenProbe ( )
end
2019-12-06 21:55:33 +00:00
-- UI mirroring for RTL languages, and text shaping configuration
local Bidi = require ( " ui/bidi " )
Bidi.setup ( lang_locale )
-- Avoid loading UIManager and widgets before here, as they may
-- cache Bidi mirroring settings. Check that with:
-- for name, _ in pairs(package.loaded) do print(name) end
2019-12-06 21:55:30 +00:00
-- User fonts override
local fontmap = G_reader_settings : readSetting ( " fontmap " )
if fontmap ~= nil then
local Font = require ( " ui/font " )
for k , v in pairs ( fontmap ) do
Font.fontmap [ k ] = v
end
end
local UIManager = require ( " ui/uimanager " )
2017-10-02 13:17:17 +00:00
-- Inform once about color rendering on newly supported devices
-- (there are some android devices that may not have a color screen,
-- and we are not (yet?) able to guess that fact)
2019-04-08 21:05:08 +00:00
if Device : hasColorScreen ( ) and not G_reader_settings : has ( " color_rendering " ) then
2017-10-02 13:17:17 +00:00
-- enable it to prevent further display of this message
G_reader_settings : saveSetting ( " color_rendering " , true )
local InfoMessage = require ( " ui/widget/infomessage " )
UIManager : show ( InfoMessage : new {
text = _ ( " Documents will be rendered in color on this device. \n If your device is grayscale, you can disable color rendering in the screen sub-menu for reduced memory usage. " ) ,
} )
end
2019-12-06 21:55:30 +00:00
-- Helpers
local lfs = require ( " libs/libkoreader-lfs " )
local function retryLastFile ( )
local ConfirmBox = require ( " ui/widget/confirmbox " )
return ConfirmBox : new {
text = _ ( " Cannot open last file. \n This could be because it was deleted or because external storage is still being mounted. \n Do you want to retry? " ) ,
ok_callback = function ( )
local last_file = G_reader_settings : readSetting ( " lastfile " )
if lfs.attributes ( last_file , " mode " ) == " file " then
local ReaderUI = require ( " apps/reader/readerui " )
UIManager : nextTick ( function ( )
ReaderUI : showReader ( last_file )
end )
else
UIManager : show ( retryLastFile ( ) )
end
end ,
}
end
2017-05-16 09:11:11 +00:00
2019-09-01 13:54:41 +00:00
local function getPathFromURI ( str )
local hexToChar = function ( x )
return string.char ( tonumber ( x , 16 ) )
end
local unescape = function ( url )
return url : gsub ( " %%(%x%x) " , hexToChar )
end
local prefix = " file:// "
if str : sub ( 1 , # prefix ) ~= prefix then
return str
end
return unescape ( str ) : sub ( # prefix + 1 )
end
2019-12-06 21:55:30 +00:00
-- Get which file to start with
local last_file = G_reader_settings : readSetting ( " lastfile " )
local start_with = G_reader_settings : readSetting ( " start_with " )
local open_last = start_with == " last "
if open_last and last_file and lfs.attributes ( last_file , " mode " ) ~= " file " then
UIManager : show ( retryLastFile ( ) )
last_file = nil
else
local QuickStart = require ( " ui/quickstart " )
if not QuickStart : isShown ( ) then
open_last = true
last_file = QuickStart : getQuickStart ( )
end
end
-- Start app
local exit_code
2013-03-16 02:12:19 +00:00
if ARGV [ argidx ] and ARGV [ argidx ] ~= " " then
2017-10-08 14:33:59 +00:00
local file
2019-09-01 13:54:41 +00:00
local sanitized_path = getPathFromURI ( ARGV [ argidx ] )
if lfs.attributes ( sanitized_path , " mode " ) == " file " then
file = sanitized_path
2014-06-05 11:06:35 +00:00
elseif open_last and last_file then
2014-09-03 04:09:25 +00:00
file = last_file
end
2016-02-25 08:54:41 +00:00
-- if file is given in command line argument or open last document is set
-- true, the given file or the last file is opened in the reader
2019-09-01 13:54:41 +00:00
if file and file ~= " " then
2014-09-03 04:09:25 +00:00
local ReaderUI = require ( " apps/reader/readerui " )
2016-03-09 06:52:36 +00:00
UIManager : nextTick ( function ( )
ReaderUI : showReader ( file )
end )
2014-09-03 04:09:25 +00:00
-- we assume a directory is given in command line argument
-- the filemanger will show the files in that path
2014-03-13 13:52:43 +00:00
else
2014-09-03 04:09:25 +00:00
local FileManager = require ( " apps/filemanager/filemanager " )
2016-02-25 08:54:41 +00:00
local home_dir =
G_reader_settings : readSetting ( " home_dir " ) or ARGV [ argidx ]
2016-03-09 06:52:36 +00:00
UIManager : nextTick ( function ( )
FileManager : showFiles ( home_dir )
end )
2017-08-14 11:15:12 +00:00
-- always open history on top of filemanager so closing history
-- doesn't result in exit
if start_with == " history " then
local FileManagerHistory = require ( " apps/filemanager/filemanagerhistory " )
UIManager : nextTick ( function ( )
FileManagerHistory : onShowHist ( last_file )
end )
2018-09-12 19:42:24 +00:00
elseif start_with == " folder_shortcuts " then
local FileManagerShortcuts = require ( " apps/filemanager/filemanagershortcuts " )
UIManager : nextTick ( function ( )
2019-03-11 10:10:46 +00:00
FileManagerShortcuts : new {
ui = FileManager.instance ,
} : onShowFolderShortcutsDialog ( )
2018-09-12 19:42:24 +00:00
end )
2017-08-14 11:15:12 +00:00
end
2014-03-13 13:52:43 +00:00
end
2017-05-16 09:11:11 +00:00
exit_code = UIManager : run ( )
2014-01-17 18:41:44 +00:00
elseif last_file then
2014-09-03 04:09:25 +00:00
local ReaderUI = require ( " apps/reader/readerui " )
2016-03-09 06:52:36 +00:00
UIManager : nextTick ( function ( )
ReaderUI : showReader ( last_file )
end )
2017-05-16 09:11:11 +00:00
exit_code = UIManager : run ( )
2012-10-02 22:45:45 +00:00
else
2014-03-13 13:52:43 +00:00
return showusage ( )
2012-10-02 22:45:45 +00:00
end
2019-12-06 21:55:30 +00:00
-- Exit
2014-11-06 07:07:50 +00:00
local function exitReader ( )
2016-02-25 08:54:41 +00:00
local ReaderActivityIndicator =
require ( " apps/reader/modules/readeractivityindicator " )
2014-11-06 07:07:50 +00:00
2017-09-04 19:05:05 +00:00
-- Save any device settings before closing G_reader_settings
Device : saveSettings ( )
2014-11-06 07:07:50 +00:00
G_reader_settings : close ( )
-- Close lipc handles
ReaderActivityIndicator : coda ( )
-- shutdown hardware abstraction
Device : exit ( )
if Profiler then Profiler.stop ( ) end
2017-05-16 09:11:11 +00:00
if type ( exit_code ) == " number " then
os.exit ( exit_code )
else
os.exit ( 0 )
end
2014-11-06 07:07:50 +00:00
end
2013-03-16 02:02:08 +00:00
exitReader ( )