Add support for new cover handling in Kobo Aura

The new Kobo Aura has firmware version 2.9.0. The main change needed for
the driver is that cover images are stored in a different place.

Version number is set to 2.9.1 to handle the later release for other
Kobo devices.
This commit is contained in:
David Forrester 2013-09-18 23:08:56 +10:00 committed by Kovid Goyal
parent 07547628cc
commit c893f0de7e

View File

@ -31,6 +31,25 @@ from calibre.utils.config_base import prefs
EPUB_EXT = '.epub'
# Implementation of QtQHash for strings. This doesn't seem to be in the Python implemention.
def qhash (inputstr):
instr = ""
if isinstance (inputstr, str):
instr = inputstr
elif isinstance (inputstr, unicode):
instr = inputstr.encode ("utf8")
else:
return -1
h = 0x00000000
for i in range (0, len (instr)):
h = (h << 4) + ord(instr[i])
h ^= (h & 0xf0000000) >> 23
h &= 0x0fffffff
return h
class DummyCSSPreProcessor(object):
def __call__(self, data, add_namespace=False):
@ -44,11 +63,11 @@ class KOBO(USBMS):
gui_name = 'Kobo Reader'
description = _('Communicate with the Kobo Reader')
author = 'Timothy Legge and David Forrester'
version = (2, 1, 2)
version = (2, 1, 3)
dbversion = 0
fwversion = 0
supported_dbversion = 80
supported_dbversion = 90
has_kepubs = False
supported_platforms = ['windows', 'osx', 'linux']
@ -1221,16 +1240,18 @@ class KOBOTOUCH(KOBO):
description = 'Communicate with the Kobo Touch, Glo, Mini and Aura HD ereaders. Based on the existing Kobo driver by %s.' % (KOBO.author)
# icon = I('devices/kobotouch.jpg')
supported_dbversion = 80
supported_dbversion = 90
min_supported_dbversion = 53
min_dbversion_series = 65
min_dbversion_externalid = 65
min_dbversion_archive = 71
min_dbversion_images_on_sdcard = 77
min_dbversion_activiy = 77
min_dbversion_keywords = 82
max_supported_fwversion = (2,8,1)
max_supported_fwversion = (2,9,1)
min_fwversion_images_on_sdcard = (2,4,1)
min_fwversion_images_tree = (2,9,0) # Cover images stored in tree under .kobo-images
has_kepubs = True
@ -1331,15 +1352,16 @@ class KOBOTOUCH(KOBO):
BCD = [0x0110, 0x0326]
# Image file name endings. Made up of: image size, min_dbversion, max_dbversion,
# Image file name endings. Made up of: image size, min_dbversion, max_dbversion, isFullSize,
COVER_FILE_ENDINGS = {
' - N3_FULL.parsed':[(600,800),0, 99,True,], # Used for screensaver, home screen
' - N3_LIBRARY_FULL.parsed':[(355,473),0, 99,False,], # Used for Details screen
' - N3_LIBRARY_FULL.parsed':[(355,473),0, 81,False,], # Used for Details screen
' - N3_LIBRARY_GRID.parsed':[(149,198),0, 99,False,], # Used for library lists
' - N3_LIBRARY_LIST.parsed':[(60,90),0, 53,False,],
' - AndroidBookLoadTablet_Aspect.parsed':[(355,473), 82, 99,False,], # Used for Details screen
# ' - N3_LIBRARY_SHELF.parsed': [(40,60),0, 52,],
}
GLO_COVER_FILE_ENDINGS = {
GLO_COVER_FILE_ENDINGS = { # Glo and Aura share resolution, so the image sizes should be the same.
' - N3_FULL.parsed':[(758,1024),0, 99,True,], # Used for screensaver, home screen
' - N3_LIBRARY_FULL.parsed':[(355,479),0, 99,False,], # Used for Details screen
' - N3_LIBRARY_GRID.parsed':[(149,201),0, 99,False,], # Used for library lists
@ -1404,6 +1426,7 @@ class KOBOTOUCH(KOBO):
debug_print('Kobo device: %s' % self.gui_name)
debug_print('Version of driver:', self.version, 'Has kepubs:', self.has_kepubs)
debug_print('Version of firmware:', self.fwversion, 'Has kepubs:', self.has_kepubs)
debug_print('Firmware supports cover image tree:', self.fwversion >= self.min_fwversion_images_tree)
self.booklist_class.rebuild_collections = self.rebuild_collections
@ -1526,7 +1549,7 @@ class KOBOTOUCH(KOBO):
if (ContentType == '6' and MimeType != 'application/x-kobo-epub+zip'):
if os.path.exists(self.normalize_path(os.path.join(prefix, lpath))):
if self.update_metadata_item(bl[idx]):
print 'update_metadata_item returned true'
# print 'update_metadata_item returned true'
changed = True
else:
debug_print(" Strange: The file: ", prefix, lpath, " does not exist!")
@ -1741,8 +1764,9 @@ class KOBOTOUCH(KOBO):
bookshelves = get_bookshelvesforbook(connection, row[3])
prefix = self._card_a_prefix if oncard == 'carda' else self._main_prefix
changed = update_booklist(prefix, path, row[0], row[1], mime, row[2], row[3], row[5], row[
6], row[7], row[4], row[8], row[9], row[10], row[11], row[12], row[13], row[14], bookshelves)
changed = update_booklist(prefix, path, row[0], row[1], mime, row[2], row[3], row[5],
row[6], row[7], row[4], row[8], row[9], row[10], row[11],
row[12], row[13], row[14], bookshelves)
if changed:
need_sync = True
@ -1812,11 +1836,11 @@ class KOBOTOUCH(KOBO):
def imagefilename_from_imageID(self, prefix, ImageID):
show_debug = self.is_debugging_title(ImageID)
path = self.images_path(prefix)
path = self.normalize_path(path.replace('/', os.sep))
path = self.images_path(prefix, ImageID)
# path = self.normalize_path(path.replace('/', os.sep))
for ending, cover_options in self.cover_file_endings().items():
fpath = path + ImageID + ending
fpath = path + ending
if os.path.exists(fpath):
if show_debug:
debug_print("KoboTouch:imagefilename_from_imageID - have cover image fpath=%s" % (fpath))
@ -1917,8 +1941,6 @@ class KOBOTOUCH(KOBO):
else:
debug_print("KoboTouch:_modify_epub: received container")
# cssnames = [n for n in container.name_path_map if n.endswith('.css')]
# for cssname in cssnames:
from calibre.ebooks.oeb.base import OEB_STYLES
for cssname, mt in container.mime_map.iteritems():
if mt in OEB_STYLES:
@ -2009,16 +2031,22 @@ class KOBOTOUCH(KOBO):
def delete_images(self, ImageID, book_path):
debug_print("KoboTouch:delete_images - ImageID=", ImageID)
if ImageID != None:
path = self.images_path(book_path)
path = path + ImageID
path = self.images_path(book_path, ImageID)
debug_print("KoboTouch:delete_images - path=%s" % path)
for ending in self.cover_file_endings().keys():
fpath = path + ending
fpath = self.normalize_path(fpath)
debug_print("KoboTouch:delete_images - fpath=%s" % fpath)
if os.path.exists(fpath):
# print 'Image File Exists: ' + fpath
debug_print("KoboTouch:delete_images - Image File Exists")
os.unlink(fpath)
try:
os.removedirs(os.path.dirname(path))
except:
pass
def contentid_from_path(self, path, ContentType):
show_debug = self.is_debugging_title(path) and True
@ -2297,14 +2325,22 @@ class KOBOTOUCH(KOBO):
ImageID = ImageID.replace('.', '_')
return ImageID
def images_path(self, path):
def images_path(self, path, imageId=None):
if self._card_a_prefix and os.path.abspath(path).startswith(os.path.abspath(self._card_a_prefix)) and self.supports_covers_on_sdcard():
path_prefix = 'koboExtStorage/images/'
path_prefix = 'koboExtStorage/images-cache/' if self.supports_images_tree() else 'koboExtStorage/images/'
path = os.path.join(self._card_a_prefix, path_prefix)
else:
path_prefix = '.kobo/images/'
path_prefix = '.kobo-images/' if self.supports_images_tree() else '.kobo/images/'
path = os.path.join(self._main_prefix, path_prefix)
if self.supports_images_tree() and imageId:
hash1 = qhash(imageId)
dir1 = hash1 & (0xff * 1)
dir2 = (hash1 & (0xff00 * 1)) >> 8
path = os.path.join(path, "%s" % dir1, "%s" % dir2)
if imageId:
path = os.path.join(path, imageId)
return path
def _upload_cover(self, path, filename, metadata, filepath, uploadgrayscale, keep_cover_aspect=False):
@ -2326,8 +2362,7 @@ class KOBOTOUCH(KOBO):
try:
import sqlite3 as sqlite
with closing(sqlite.connect(self.normalize_path(self._main_prefix +
'.kobo/KoboReader.sqlite'))) as connection:
with closing(sqlite.connect(self.device_database_path())) as connection:
# return bytestrings if the content cannot the decoded as unicode
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
@ -2347,7 +2382,7 @@ class KOBOTOUCH(KOBO):
cursor.close()
if ImageID != None:
path = os.path.join(self.images_path(path), ImageID)
path = self.images_path(path, ImageID)
if show_debug:
debug_print("KoboTouch:_upload_cover - About to loop over cover endings")
@ -2762,6 +2797,9 @@ class KOBOTOUCH(KOBO):
def supports_covers_on_sdcard(self):
return self.dbversion >= self.min_dbversion_images_on_sdcard and self.fwversion >= self.min_fwversion_images_on_sdcard
def supports_images_tree(self):
return self.fwversion >= self.min_fwversion_images_tree
def has_externalid(self):
return self.dbversion >= self.min_dbversion_externalid