Mobileread
Derive full path of a book from device driver + lpath
#1  pazos 06-07-2020, 02:11 PM
background

I'm trying to improve a bit KOReader integration with calibre metadata.
KOReader supports some platforms that have a dedicated calibre driver (kobos, kindles, pocketbooks, bq cervantes, android).

problem

Need to figure out the full path of each book based on its lpath

more info

With certain calibre drivers (kobo, connect to folder, smart app device...) I can derive the full path of a book by joining the path of metadata files and the lpath of each book (as stored in {.}metadata.calibre).

In other drivers the path where calibre stores the books differs from the path where calibre stores the metadata. This happens, for example, on the BQ Cervantes driver, which stores metadata.calibre and driveinfo.calibre on the root of the USB share and books under the relative path books/

In these cases there's no way to derive the full path of a book by joining library path + book lpath as books don't store that part of the path as their lpath.

question

I would like to know if there's some string in driveinfo.calibre that I can use to determine if the driver places the book somewhere else.
Reply 

#2  pazos 06-07-2020, 03:12 PM
I don't know if is just a bug in the BQ Cervantes device driver and the lpath is always relative to where metadata is stored. It seems to be the case in Kindle devices. See https://github.com/koreader/koreader/pull/6177#issuecomment-640260257

In that case I would assume that I can always get the book full path knowing the root of the library + book lpath. A confirmation would be nice, specially for Android & pocketbook devices.
Reply 

#3  chaley 06-07-2020, 05:40 PM
The lpath (logical path) is supposed to be the path from the device/format root to the format to the file. There is no guaranteed relationship between the location of metadata.calibre, if it exists, and the lpath. In my experience the lpath is always right once one finds the right root.

Calibre puts the metadata.calibre etc in what it thinks is the root of the filesystem, which can vary according to the device driver. IIRC this is the mount point. For example and again IIRC, for the folder device the "root" is the mount point and always the prefix for the control files. The Android driver used MTP which imposes its own translations.

The driveinfo.calibre contains the lpath prefix that the driver uses to write files. Again, this value depends on the driver. For the folder device it is the path to the folder. For other devices it is the prefix that is used to navigate from whatever root the device supports.

It should be true that for a given device using the standard device interface, the concatenation of one of the values in driveinfo (possible roots for the library) and the lpath should get you to the book. The trick is to know whether that device has a "special" root folder that is exposed via the interface, and which of the 3 paths the book has used (main, card_a, card_b). However, looking at the code the MTP device doesn't seem to follow these rules, instead using a path-per-format specified by the user.

Is there something specific you are looking for?
Reply 

#4  pazos 06-07-2020, 06:20 PM
Thanks for the info, chaley

Quote chaley
Is there something specific you are looking for?
Yeah. I tried to figure out why the code I was writting didn't work on my BQ cervantes 4. I thought than other devices could have the same issues.

Basically is a function to search calibre metadata from n calibre libraries. Works with connect to folder, our own backed in wireless client and most of calibre device drivers, but fails on my BQ.

In the end I wrote a helper function to workaround the limitation. now looks this way:

Code
local function getAllMetadata(t) local books = {} for path, enabled in pairs(t) do if enabled and CalibreMetadata:init(path, true) then local books_path local ok_lpath, subdir = hasValidLpath(CalibreMetadata.drive.device_name) if not ok_lpath then books_path = path .. "/" .. subdir else books_path = path end for _, book in ipairs(CalibreMetadata.books) do local slim_book = {} slim_book.title = book.title slim_book.lpath = book.lpath slim_book.authors = book.authors slim_book.series = book.series slim_book.tags = book.tags slim_book.size = book.size slim_book.rootpath = books_path table.insert(books, #books + 1, slim_book) end CalibreMetadata:clean() end end return books
end
the helper function hasValidLpath is just a workaround for BQ devices:

Code
-- some calibre drivers don't report a valid lpath
local function hasValidLpath(name) if type(name) ~= "string" then return true end local function deviceIs(kind) return string.match(string.upper(name), string.upper(kind)) end if deviceIs("bq") then return false, "Books" else -- deviceIs "Kobo"/"Amazon"/"Folder"/"KOReader" return true end
end
The reason why I need the workaround is: when using BQ Cervantes device driver "metadata.calibre" is put on the root of the USB share. Books are placed on "Books/" but the lpath of books doesn't join "Books" to the name of the file.

If I disable the device driver and connect to the root dir with connect to folder then calibre is able to fix the issue and now books have the expected lpath.

I searched https://github.com/kovidgoyal/calibre/search?p=1&q=EBOOK_DIR_MAIN&unscoped_q=EBOOK_DIR_M AIN and I'm now pretty sure it's the fault on that specific driver and not something that need s special care on every device I'm trying to support.
Reply 

Today's Posts | Search this Thread | Login | Register