mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kobo driver: Update for new firmware from Kobo
Also fix incorrect cover size being uploaded to the Glo HD Merge branch 'master' of https://github.com/davidfor/calibre
This commit is contained in:
commit
1d0d413f8f
@ -65,7 +65,7 @@ class KOBO(USBMS):
|
|||||||
gui_name = 'Kobo Reader'
|
gui_name = 'Kobo Reader'
|
||||||
description = _('Communicate with the Kobo Reader')
|
description = _('Communicate with the Kobo Reader')
|
||||||
author = 'Timothy Legge and David Forrester'
|
author = 'Timothy Legge and David Forrester'
|
||||||
version = (2, 3, 2)
|
version = (2, 3, 3)
|
||||||
|
|
||||||
dbversion = 0
|
dbversion = 0
|
||||||
fwversion = (0,0,0)
|
fwversion = (0,0,0)
|
||||||
@ -1325,7 +1325,7 @@ class KOBOTOUCH(KOBO):
|
|||||||
# Starting with firmware version 3.19.x, the last number appears to be is a
|
# Starting with firmware version 3.19.x, the last number appears to be is a
|
||||||
# build number. A number will be recorded here but it can be safely ignored
|
# build number. A number will be recorded here but it can be safely ignored
|
||||||
# when testing the firmware version.
|
# when testing the firmware version.
|
||||||
max_supported_fwversion = (4, 2, 8094)
|
max_supported_fwversion = (4, 2, 8283)
|
||||||
# The following document firwmare versions where new function or devices were added.
|
# The following document firwmare versions where new function or devices were added.
|
||||||
# Not all are used, but this feels a good place to record it.
|
# Not all are used, but this feels a good place to record it.
|
||||||
min_fwversion_shelves = (2, 0, 0)
|
min_fwversion_shelves = (2, 0, 0)
|
||||||
@ -1397,19 +1397,29 @@ class KOBOTOUCH(KOBO):
|
|||||||
# Used for Details screen from FW2.8.1
|
# Used for Details screen from FW2.8.1
|
||||||
' - AndroidBookLoadTablet_Aspect.parsed':[(355,479), 88, 100,False,],
|
' - AndroidBookLoadTablet_Aspect.parsed':[(355,479), 88, 100,False,],
|
||||||
}
|
}
|
||||||
|
GLO_HD_COVER_FILE_ENDINGS = {
|
||||||
|
# Used for screensaver, home screen
|
||||||
|
' - N3_FULL.parsed': [(1072,1448), 0, 200,True,],
|
||||||
|
# Used for Details screen before FW2.8.1, then for current book tile on home screen
|
||||||
|
' - N3_LIBRARY_FULL.parsed':[(355, 479), 0, 200,False,],
|
||||||
|
# Used for library lists
|
||||||
|
' - N3_LIBRARY_GRID.parsed':[(149, 201), 0, 200,False,],
|
||||||
|
# Used for Details screen from FW2.8.1
|
||||||
|
' - AndroidBookLoadTablet_Aspect.parsed':[(355, 471), 88, 100,False,],
|
||||||
|
}
|
||||||
AURA_HD_COVER_FILE_ENDINGS = {
|
AURA_HD_COVER_FILE_ENDINGS = {
|
||||||
# Used for screensaver, home screen
|
# Used for screensaver, home screen
|
||||||
' - N3_FULL.parsed': [(1080,1440), 0, 200,True,], # Used for screensaver, home screen
|
' - N3_FULL.parsed': [(1080,1440), 0, 200,True,],
|
||||||
# Used for Details screen before FW2.8.1, then for current book tile on home screen
|
# Used for Details screen before FW2.8.1, then for current book tile on home screen
|
||||||
' - N3_LIBRARY_FULL.parsed':[(355, 471), 0, 200,False,],
|
' - N3_LIBRARY_FULL.parsed':[(355, 471), 0, 200,False,],
|
||||||
# Used for library lists
|
# Used for library lists
|
||||||
' - N3_LIBRARY_GRID.parsed':[(149, 198), 0, 200,False,], # Used for library lists
|
' - N3_LIBRARY_GRID.parsed':[(149, 198), 0, 200,False,],
|
||||||
# Used for Details screen from FW2.8.1
|
# Used for Details screen from FW2.8.1
|
||||||
' - AndroidBookLoadTablet_Aspect.parsed':[(355, 471), 88, 100,False,],
|
' - AndroidBookLoadTablet_Aspect.parsed':[(355, 471), 88, 100,False,],
|
||||||
}
|
}
|
||||||
AURA_ONE_COVER_FILE_ENDINGS = {
|
AURA_ONE_COVER_FILE_ENDINGS = {
|
||||||
# Used for screensaver, home screen
|
# Used for screensaver, home screen
|
||||||
' - N3_FULL.parsed': [(1404,1872), 0, 200,True,], # Used for screensaver, home screen
|
' - N3_FULL.parsed': [(1404,1872), 0, 200,True,],
|
||||||
# Used for Details screen before FW2.8.1, then for current book tile on home screen
|
# Used for Details screen before FW2.8.1, then for current book tile on home screen
|
||||||
' - N3_LIBRARY_FULL.parsed':[(355, 473), 0, 200,False,],
|
' - N3_LIBRARY_FULL.parsed':[(355, 473), 0, 200,False,],
|
||||||
# Used for library lists
|
# Used for library lists
|
||||||
@ -2428,19 +2438,55 @@ class KOBOTOUCH(KOBO):
|
|||||||
path = os.path.join(path, imageId)
|
path = os.path.join(path, imageId)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _upload_cover(self, path, filename, metadata, filepath, uploadgrayscale, keep_cover_aspect=False):
|
def _calculate_kobo_cover_size(self, library_size, kobo_size, keep_cover_aspect, is_full_size):
|
||||||
from calibre.utils.img import save_cover_data_to
|
if keep_cover_aspect:
|
||||||
from calibre.utils.imghdr import identify
|
library_aspect = library_size[0] / library_size[1]
|
||||||
debug_print("KoboTouch:_upload_cover - filename='%s' uploadgrayscale='%s' "%(filename, uploadgrayscale))
|
kobo_aspect = kobo_size[0] / kobo_size[1]
|
||||||
|
if library_aspect > kobo_aspect:
|
||||||
|
kobo_size = (kobo_size[0], int(kobo_size[0] / library_aspect))
|
||||||
|
else:
|
||||||
|
kobo_size = (int(library_aspect * kobo_size[1]), kobo_size[1])
|
||||||
|
return kobo_size
|
||||||
|
|
||||||
|
def _create_cover_data(self, cover_data, resize_to, kobo_size, upload_grayscale=False, keep_cover_aspect=False, is_full_size=False):
|
||||||
|
'''
|
||||||
|
This will generate the new cover image from the cover in the library. It is a wrapper
|
||||||
|
for save_cover_data_to to allow it to be overriden in a subclass. For this reason,
|
||||||
|
options are passed in that are not used by this implementation.
|
||||||
|
|
||||||
|
:param cover_data: original cover data
|
||||||
|
:param resize_to: Size to resize the cover to (width, height). None means do not resize.
|
||||||
|
:param kobo_size: Size of the cover image on the device.
|
||||||
|
:param upload_grayscale: boolean True if driver configured to send grayscale thumbnails
|
||||||
|
Passed to allow ability to decide to quantize to 16-col grayscale
|
||||||
|
at calibre end
|
||||||
|
:param keep_cover_aspect: bookean - True if the aspect ratio of the cover in the library is to be kept.
|
||||||
|
:param is_full_size: True if this is the kobo_size is for the full size cover image
|
||||||
|
Passed to allow ability to process screensaver differently
|
||||||
|
to smaller thumbnails
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.utils.img import save_cover_data_to
|
||||||
|
data = save_cover_data_to(cover_data, grayscale=upload_grayscale, resize_to=resize_to)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _upload_cover(self, path, filename, metadata, filepath, upload_grayscale, keep_cover_aspect=False):
|
||||||
|
from calibre.utils.imghdr import identify
|
||||||
|
debug_print("KoboTouch:_upload_cover - filename='%s' upload_grayscale='%s' "%(filename, upload_grayscale))
|
||||||
|
|
||||||
|
if not metadata.cover:
|
||||||
|
return
|
||||||
|
|
||||||
if metadata.cover:
|
|
||||||
show_debug = self.is_debugging_title(filename)
|
show_debug = self.is_debugging_title(filename)
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print("KoboTouch:_upload_cover - path='%s'"%path, "filename='%s'"%filename)
|
debug_print("KoboTouch:_upload_cover - path='%s'"%path, "filename='%s'"%filename)
|
||||||
debug_print(" filepath='%s'"%filepath)
|
debug_print(" filepath='%s'"%filepath)
|
||||||
cover = self.normalize_path(metadata.cover.replace('/', os.sep))
|
cover = self.normalize_path(metadata.cover.replace('/', os.sep))
|
||||||
|
|
||||||
if os.path.exists(cover):
|
if not os.path.exists(cover):
|
||||||
|
debug_print("KoboTouch:_upload_cover - Cover file does not exist in library")
|
||||||
|
return
|
||||||
|
|
||||||
# Get ContentID for Selected Book
|
# Get ContentID for Selected Book
|
||||||
extension = os.path.splitext(filepath)[1]
|
extension = os.path.splitext(filepath)[1]
|
||||||
ContentType = self.get_content_type_from_extension(extension) if extension != '' else self.get_content_type_from_path(filepath)
|
ContentType = self.get_content_type_from_extension(extension) if extension != '' else self.get_content_type_from_path(filepath)
|
||||||
@ -2472,33 +2518,27 @@ class KOBOTOUCH(KOBO):
|
|||||||
debug_print("KoboTouch:_upload_cover - Image directory does not exust. Creating path='%s'" % (image_dir))
|
debug_print("KoboTouch:_upload_cover - Image directory does not exust. Creating path='%s'" % (image_dir))
|
||||||
os.makedirs(image_dir)
|
os.makedirs(image_dir)
|
||||||
|
|
||||||
|
with lopen(cover, 'rb') as f:
|
||||||
|
cover_data = f.read()
|
||||||
|
|
||||||
|
fmt, width, height = identify(cover_data)
|
||||||
|
library_cover_size = (width, height)
|
||||||
|
|
||||||
for ending, cover_options in self.cover_file_endings().items():
|
for ending, cover_options in self.cover_file_endings().items():
|
||||||
resize, min_dbversion, max_dbversion, isFullsize = cover_options
|
kobo_size, min_dbversion, max_dbversion, is_full_size = cover_options
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print("KoboTouch:_upload_cover - resize=%s min_dbversion=%d max_dbversion=%d" % (resize, min_dbversion, max_dbversion))
|
debug_print("KoboTouch:_upload_cover - library_cover_size=%s min_dbversion=%d max_dbversion=%d" % (
|
||||||
|
library_cover_size, min_dbversion, max_dbversion))
|
||||||
if self.dbversion >= min_dbversion and self.dbversion <= max_dbversion:
|
if self.dbversion >= min_dbversion and self.dbversion <= max_dbversion:
|
||||||
if show_debug:
|
if show_debug:
|
||||||
debug_print("KoboTouch:_upload_cover - creating cover for ending='%s'"%ending) # , "resize'%s'"%resize)
|
debug_print("KoboTouch:_upload_cover - creating cover for ending='%s'"%ending) # , "library_cover_size'%s'"%library_cover_size)
|
||||||
fpath = path + ending
|
fpath = path + ending
|
||||||
fpath = self.normalize_path(fpath.replace('/', os.sep))
|
fpath = self.normalize_path(fpath.replace('/', os.sep))
|
||||||
|
|
||||||
with lopen(cover, 'rb') as f:
|
resize_to = self._calculate_kobo_cover_size(library_cover_size, kobo_size, keep_cover_aspect, is_full_size)
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
if keep_cover_aspect:
|
# Return the data resized and in Grayscale if required
|
||||||
if isFullsize:
|
data = self._create_cover_data(cover_data, resize_to, kobo_size, upload_grayscale, keep_cover_aspect, is_full_size)
|
||||||
resize = None
|
|
||||||
else:
|
|
||||||
fmt, width, height = identify(data)
|
|
||||||
cover_aspect = width / height
|
|
||||||
if cover_aspect > 1:
|
|
||||||
resize = (resize[0], int(resize[0] / cover_aspect))
|
|
||||||
elif cover_aspect < 1:
|
|
||||||
resize = (int(cover_aspect * resize[1]), resize[1])
|
|
||||||
|
|
||||||
# Return the data resized and in Grayscale if
|
|
||||||
# required
|
|
||||||
data = save_cover_data_to(data, grayscale=uploadgrayscale, resize_to=resize)
|
|
||||||
|
|
||||||
with lopen(fpath, 'wb') as f:
|
with lopen(fpath, 'wb') as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
@ -2507,8 +2547,6 @@ class KOBOTOUCH(KOBO):
|
|||||||
err = str(e)
|
err = str(e)
|
||||||
debug_print("KoboTouch:_upload_cover - Exception string: %s"%err)
|
debug_print("KoboTouch:_upload_cover - Exception string: %s"%err)
|
||||||
raise
|
raise
|
||||||
else:
|
|
||||||
debug_print("KoboTouch:_upload_cover - ImageID could not be retrieved from the database")
|
|
||||||
|
|
||||||
def remove_book_from_device_bookshelves(self, connection, book):
|
def remove_book_from_device_bookshelves(self, connection, book):
|
||||||
show_debug = self.is_debugging_title(book.title) # or True
|
show_debug = self.is_debugging_title(book.title) # or True
|
||||||
@ -2914,10 +2952,30 @@ class KOBOTOUCH(KOBO):
|
|||||||
return self.detected_device.idProduct in self.TOUCH2_PRODUCT_ID
|
return self.detected_device.idProduct in self.TOUCH2_PRODUCT_ID
|
||||||
|
|
||||||
def cover_file_endings(self):
|
def cover_file_endings(self):
|
||||||
return self.GLO_COVER_FILE_ENDINGS if self.isGlo() or self.isAura() or self.isAuraEdition2() \
|
if self.isAura():
|
||||||
else self.AURA_HD_COVER_FILE_ENDINGS if self.isAuraHD() or self.isAuraH2O() or self.isGloHD() \
|
_cover_file_endings = self.GLO_COVER_FILE_ENDINGS
|
||||||
else self.AURA_ONE_COVER_FILE_ENDINGS if self.isAuraOne() \
|
elif self.isAuraEdition2():
|
||||||
else self.COVER_FILE_ENDINGS
|
_cover_file_endings = self.GLO_COVER_FILE_ENDINGS
|
||||||
|
elif self.isAuraHD():
|
||||||
|
_cover_file_endings = self.AURA_HD_COVER_FILE_ENDINGS
|
||||||
|
elif self.isAuraH2O():
|
||||||
|
_cover_file_endings = self.AURA_HD_COVER_FILE_ENDINGS
|
||||||
|
elif self.isAuraOne():
|
||||||
|
_cover_file_endings = self.AURA_ONE_COVER_FILE_ENDINGS
|
||||||
|
elif self.isGlo():
|
||||||
|
_cover_file_endings = self.GLO_COVER_FILE_ENDINGS
|
||||||
|
elif self.isGloHD():
|
||||||
|
_cover_file_endings = self.GLO_HD_COVER_FILE_ENDINGS
|
||||||
|
elif self.isMini():
|
||||||
|
_cover_file_endings = self.COVER_FILE_ENDINGS
|
||||||
|
elif self.isTouch():
|
||||||
|
_cover_file_endings = self.COVER_FILE_ENDINGS
|
||||||
|
elif self.isTouch2():
|
||||||
|
_cover_file_endings = self.COVER_FILE_ENDINGS
|
||||||
|
else:
|
||||||
|
_cover_file_endings = self.COVER_FILE_ENDINGS
|
||||||
|
|
||||||
|
return _cover_file_endings
|
||||||
|
|
||||||
def set_device_name(self):
|
def set_device_name(self):
|
||||||
device_name = self.gui_name
|
device_name = self.gui_name
|
||||||
|
Loading…
x
Reference in New Issue
Block a user