mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Refactor and clean up of device drivers.
This commit is contained in:
parent
024d47046e
commit
1e19801b37
@ -1,21 +1,18 @@
|
|||||||
#!/usr/bin/env python
|
# -*- coding: utf-8 -*-
|
||||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class ANDROID(USBMS):
|
class ANDROID(USBMS):
|
||||||
|
|
||||||
name = 'Android driver'
|
name = 'Android driver'
|
||||||
description = _('Communicate with Android phones.')
|
description = _('Communicate with Android phones.')
|
||||||
author = 'Kovid Goyal'
|
author = 'Kovid Goyal'
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['epub']
|
FORMATS = ['epub']
|
||||||
|
|
||||||
@ -34,5 +31,3 @@ class ANDROID(USBMS):
|
|||||||
MAIN_MEMORY_VOLUME_LABEL = 'Android Internal Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'Android Internal Memory'
|
||||||
|
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, Tijmen Ruizendaal <tijmen at mybebook.com>'
|
__copyright__ = '2009, Tijmen Ruizendaal <tijmen at mybebook.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for BeBook
|
Device driver for BeBook
|
||||||
@ -10,12 +13,12 @@ import re
|
|||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class BEBOOK(USBMS):
|
class BEBOOK(USBMS):
|
||||||
|
|
||||||
name = 'BeBook driver'
|
name = 'BeBook driver'
|
||||||
description = _('Communicate with the BeBook eBook reader.')
|
description = _('Communicate with the BeBook eBook reader.')
|
||||||
author = 'Tijmen Ruizendaal'
|
author = 'Tijmen Ruizendaal'
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['mobi', 'epub', 'pdf', 'txt']
|
FORMATS = ['mobi', 'epub', 'pdf', 'txt']
|
||||||
|
|
||||||
@ -94,4 +97,3 @@ class BEBOOK_MINI(BEBOOK):
|
|||||||
|
|
||||||
MAIN_MEMORY_VOLUME_LABEL = 'BeBook Mini Internal Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'BeBook Mini Internal Memory'
|
||||||
STORAGE_CARD_VOLUME_LABEL = 'BeBook Mini Storage Card'
|
STORAGE_CARD_VOLUME_LABEL = 'BeBook Mini Storage Card'
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
from __future__ import with_statement
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL 3'
|
__license__ = 'GPL 3'
|
||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class BLACKBERRY(USBMS):
|
class BLACKBERRY(USBMS):
|
||||||
@ -15,18 +15,17 @@ class BLACKBERRY(USBMS):
|
|||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['mobi', 'prc']
|
FORMATS = ['mobi', 'prc']
|
||||||
|
|
||||||
VENDOR_ID = [0x0fca]
|
VENDOR_ID = [0x0fca]
|
||||||
PRODUCT_ID = [0x8004]
|
PRODUCT_ID = [0x8004]
|
||||||
BCD = [0x0200]
|
BCD = [0x0200]
|
||||||
|
|
||||||
VENDOR_NAME = 'RIM'
|
VENDOR_NAME = 'RIM'
|
||||||
WINDOWS_MAIN_MEM = 'BLACKBERRY_SD'
|
WINDOWS_MAIN_MEM = 'BLACKBERRY_SD'
|
||||||
|
|
||||||
#OSX_MAIN_MEM = 'Kindle Internal Storage Media'
|
#OSX_MAIN_MEM = 'Kindle Internal Storage Media'
|
||||||
|
|
||||||
MAIN_MEMORY_VOLUME_LABEL = 'Blackberry Main Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'Blackberry Main Memory'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = 'ebooks'
|
EBOOK_DIR_MAIN = 'ebooks'
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for Bookeen's Cybook Gen 3
|
Device driver for Bookeen's Cybook Gen 3
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre.utils.filenames import ascii_filename as sanitize
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
import calibre.devices.cybookg3.t2b as t2b
|
import calibre.devices.cybookg3.t2b as t2b
|
||||||
|
|
||||||
class CYBOOKG3(USBMS):
|
class CYBOOKG3(USBMS):
|
||||||
name = 'Cybook Gen 3/Opus Device Interface'
|
|
||||||
description = _('Communicate with the Cybook eBook reader.')
|
name = 'Cybook Gen 3 Device Interface'
|
||||||
|
description = _('Communicate with the Cybook Gen 3 eBook reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
# Be sure these have an entry in calibre.devices.mime
|
# Be sure these have an entry in calibre.devices.mime
|
||||||
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt']
|
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt']
|
||||||
@ -31,19 +33,21 @@ class CYBOOKG3(USBMS):
|
|||||||
WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD'
|
WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD'
|
||||||
WINDOWS_CARD_A_MEM = 'CYBOOK_GEN3__-SD'
|
WINDOWS_CARD_A_MEM = 'CYBOOK_GEN3__-SD'
|
||||||
|
|
||||||
OSX_MAIN_MEM = ['Bookeen Cybook Gen3 -FD Media', 'Bookeen Cybook Opus -FD Media']
|
OSX_MAIN_MEM = 'Bookeen Cybook Gen3 -FD Media'
|
||||||
OSX_CARD_A_MEM = 'Bookeen Cybook Gen3 -SD Media'
|
OSX_CARD_A_MEM = 'Bookeen Cybook Gen3 -SD Media'
|
||||||
|
|
||||||
MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory'
|
||||||
STORAGE_CARD_VOLUME_LABEL = 'Cybook Gen 3 Storage Card'
|
STORAGE_CARD_VOLUME_LABEL = 'Cybook Gen 3 Storage Card'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = "eBooks"
|
EBOOK_DIR_MAIN = 'eBooks'
|
||||||
EBOOK_DIR_CARD_A = "eBooks"
|
EBOOK_DIR_CARD_A = 'eBooks'
|
||||||
THUMBNAIL_HEIGHT = 144
|
THUMBNAIL_HEIGHT = 144
|
||||||
|
DELETE_EXTS = ['.mbp', '.dat', '_6090.t2b']
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
metadata=None):
|
metadata=None):
|
||||||
|
|
||||||
path = self._sanity_check(on_card, files)
|
path = self._sanity_check(on_card, files)
|
||||||
|
|
||||||
paths = []
|
paths = []
|
||||||
@ -51,45 +55,16 @@ class CYBOOKG3(USBMS):
|
|||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
|
|
||||||
for i, infile in enumerate(files):
|
for i, infile in enumerate(files):
|
||||||
newpath = path
|
mdata, fname = metadata.next(), names.next()
|
||||||
mdata = metadata.next()
|
filepath = self.create_upload_path(path, mdata, fname)
|
||||||
|
|
||||||
if 'tags' in mdata.keys():
|
|
||||||
for tag in mdata['tags']:
|
|
||||||
if tag.startswith(_('News')):
|
|
||||||
newpath = os.path.join(newpath, 'news')
|
|
||||||
newpath = os.path.join(newpath, sanitize(mdata.get('title', '')))
|
|
||||||
newpath = os.path.join(newpath, sanitize(mdata.get('timestamp', '')))
|
|
||||||
elif tag.startswith('/'):
|
|
||||||
newpath += tag
|
|
||||||
newpath = os.path.normpath(newpath)
|
|
||||||
break
|
|
||||||
|
|
||||||
if newpath == path:
|
|
||||||
newpath = os.path.join(newpath, sanitize(mdata.get('authors', _('Unknown'))))
|
|
||||||
newpath = os.path.join(newpath, sanitize(mdata.get('title', _('Unknown'))))
|
|
||||||
|
|
||||||
if not os.path.exists(newpath):
|
|
||||||
os.makedirs(newpath)
|
|
||||||
|
|
||||||
filepath = os.path.join(newpath, sanitize(names.next()))
|
|
||||||
paths.append(filepath)
|
paths.append(filepath)
|
||||||
|
|
||||||
if hasattr(infile, 'read'):
|
self.put_file(infile, filepath, replace_file=True)
|
||||||
infile.seek(0)
|
|
||||||
|
|
||||||
dest = open(filepath, 'wb')
|
|
||||||
shutil.copyfileobj(infile, dest, 10*1024*1024)
|
|
||||||
|
|
||||||
dest.flush()
|
|
||||||
dest.close()
|
|
||||||
else:
|
|
||||||
shutil.copy2(infile, filepath)
|
|
||||||
|
|
||||||
coverdata = None
|
coverdata = None
|
||||||
if 'cover' in mdata.keys():
|
cover = mdata.get('cover', None)
|
||||||
if mdata['cover'] != None:
|
if cover:
|
||||||
coverdata = mdata['cover'][2]
|
coverdata = cover[2]
|
||||||
|
|
||||||
t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb')
|
t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb')
|
||||||
t2b.write_t2b(t2bfile, coverdata)
|
t2b.write_t2b(t2bfile, coverdata)
|
||||||
@ -101,31 +76,13 @@ class CYBOOKG3(USBMS):
|
|||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
|
||||||
for i, path in enumerate(paths):
|
|
||||||
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
|
||||||
if os.path.exists(path):
|
|
||||||
os.unlink(path)
|
|
||||||
|
|
||||||
filepath, ext = os.path.splitext(path)
|
class CYBOOK_OPUS(USBMS):
|
||||||
|
|
||||||
# Delete the ebook auxiliary file
|
name = 'Cybook Opus Device Interface'
|
||||||
if os.path.exists(filepath + '.mbp'):
|
description = _('Communicate with the Cybook Opus eBook reader.')
|
||||||
os.unlink(filepath + '.mbp')
|
author = _('John Schember')
|
||||||
if os.path.exists(filepath + '.dat'):
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
os.unlink(filepath + '.dat')
|
|
||||||
|
|
||||||
# Delete the thumbnails file auto generated for the ebook
|
|
||||||
if os.path.exists(filepath + '_6090.t2b'):
|
|
||||||
os.unlink(filepath + '_6090.t2b')
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.removedirs(os.path.dirname(path))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
self.report_progress(1.0, _('Removing books from device...'))
|
|
||||||
|
|
||||||
class CYBOOK_OPUS(CYBOOKG3):
|
|
||||||
|
|
||||||
FORMATS = ['epub', 'pdf', 'txt']
|
FORMATS = ['epub', 'pdf', 'txt']
|
||||||
|
|
||||||
@ -133,14 +90,13 @@ class CYBOOK_OPUS(CYBOOKG3):
|
|||||||
PRODUCT_ID = [0x0703]
|
PRODUCT_ID = [0x0703]
|
||||||
BCD = [0x110]
|
BCD = [0x110]
|
||||||
|
|
||||||
|
VENDOR_NAME = 'BOOKEEN'
|
||||||
WINDOWS_MAIN_MEM = 'CYBOOK_OPUS__-FD'
|
WINDOWS_MAIN_MEM = 'CYBOOK_OPUS__-FD'
|
||||||
WINDOWS_CARD_A_MEM = 'CYBOOK_OPUS__-SD'
|
WINDOWS_CARD_A_MEM = 'CYBOOK_OPUS__-SD'
|
||||||
|
|
||||||
OSX_MAIN_MEM = 'Bookeen Cybook Opus -FD Media'
|
OSX_MAIN_MEM = 'Bookeen Cybook Opus -FD Media'
|
||||||
OSX_CARD_A_MEM = 'Bookeen Cybook Opus -SD Media'
|
OSX_CARD_A_MEM = 'Bookeen Cybook Opus -SD Media'
|
||||||
|
|
||||||
def upload_books(self, *args, **kwargs):
|
EBOOK_DIR_MAIN = 'eBooks'
|
||||||
USBMS.upload_books(self, *args, **kwargs)
|
EBOOK_DIR_CARD_A = 'eBooks'
|
||||||
|
SUPPORTS_SUB_DIRS = True
|
||||||
def delete_books(self, *args, **kwargs):
|
|
||||||
USBMS.delete_books(self, *args, **kwargs)
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for the Netronix EB600
|
Device driver for the Netronix EB600
|
||||||
|
|
||||||
@ -14,13 +18,15 @@ Windows PNP strings:
|
|||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class EB600(USBMS):
|
class EB600(USBMS):
|
||||||
|
|
||||||
name = 'Netronix EB600 Device Interface'
|
name = 'Netronix EB600 Device Interface'
|
||||||
description = _('Communicate with the EB600 eBook reader.')
|
description = _('Communicate with the EB600 eBook reader.')
|
||||||
author = _('Kovid Goyal')
|
author = _('Kovid Goyal')
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['epub', 'mobi', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt', 'pdf']
|
FORMATS = ['epub', 'mobi', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt',
|
||||||
|
'pdf']
|
||||||
DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt']
|
DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt']
|
||||||
|
|
||||||
VENDOR_ID = [0x1f85]
|
VENDOR_ID = [0x1f85]
|
||||||
@ -59,4 +65,3 @@ class COOL_ER(EB600):
|
|||||||
WINDOWS_MAIN_MEM = 'EREADER'
|
WINDOWS_MAIN_MEM = 'EREADER'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = 'my docs'
|
EBOOK_DIR_MAIN = 'my docs'
|
||||||
|
|
||||||
|
@ -8,17 +8,15 @@ __docformat__ = 'restructuredtext en'
|
|||||||
Device driver for IRex Iliad
|
Device driver for IRex Iliad
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class ILIAD(USBMS):
|
class ILIAD(USBMS):
|
||||||
|
|
||||||
name = 'IRex Iliad Device Interface'
|
name = 'IRex Iliad Device Interface'
|
||||||
description = _('Communicate with the IRex Iliad eBook reader.')
|
description = _('Communicate with the IRex Iliad eBook reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
supported_platforms = ['windows', 'linux']
|
supported_platforms = ['windows', 'linux']
|
||||||
|
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
# Be sure these have an entry in calibre.devices.mime
|
# Be sure these have an entry in calibre.devices.mime
|
||||||
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'txt']
|
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'txt']
|
||||||
@ -35,23 +33,5 @@ class ILIAD(USBMS):
|
|||||||
MAIN_MEMORY_VOLUME_LABEL = 'IRex Iliad Main Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'IRex Iliad Main Memory'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = 'books'
|
EBOOK_DIR_MAIN = 'books'
|
||||||
|
DELETE_EXTS = ['.mbp']
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
|
||||||
for i, path in enumerate(paths):
|
|
||||||
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
|
||||||
if os.path.exists(path):
|
|
||||||
os.unlink(path)
|
|
||||||
|
|
||||||
filepath, ext = os.path.splitext(path)
|
|
||||||
|
|
||||||
# Delete the ebook auxiliary file
|
|
||||||
if os.path.exists(filepath + '.mbp'):
|
|
||||||
os.unlink(filepath + '.mbp')
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.removedirs(os.path.dirname(path))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.report_progress(1.0, _('Removing books from device...'))
|
|
||||||
|
@ -8,17 +8,16 @@ __docformat__ = 'restructuredtext en'
|
|||||||
Device driver for IRex Digiatal Reader
|
Device driver for IRex Digiatal Reader
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class IREXDR1000(USBMS):
|
class IREXDR1000(USBMS):
|
||||||
|
|
||||||
name = 'IRex Digital Reader 1000 Device Interface'
|
name = 'IRex Digital Reader 1000 Device Interface'
|
||||||
description = _('Communicate with the IRex Digital Reader 1000 eBook reader.')
|
description = _('Communicate with the IRex Digital Reader 1000 eBook ' \
|
||||||
|
'reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
# Be sure these have an entry in calibre.devices.mime
|
# Be sure these have an entry in calibre.devices.mime
|
||||||
FORMATS = ['epub', 'mobi', 'prc', 'html', 'pdf', 'txt']
|
FORMATS = ['epub', 'mobi', 'prc', 'html', 'pdf', 'txt']
|
||||||
@ -35,23 +34,5 @@ class IREXDR1000(USBMS):
|
|||||||
MAIN_MEMORY_VOLUME_LABEL = 'IRex Digital Reader 1000 Main Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'IRex Digital Reader 1000 Main Memory'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = 'ebooks'
|
EBOOK_DIR_MAIN = 'ebooks'
|
||||||
|
DELETE_EXTS = ['.mbp']
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
|
||||||
for i, path in enumerate(paths):
|
|
||||||
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
|
||||||
if os.path.exists(path):
|
|
||||||
os.unlink(path)
|
|
||||||
|
|
||||||
filepath, ext = os.path.splitext(path)
|
|
||||||
|
|
||||||
# Delete the ebook auxiliary file
|
|
||||||
if os.path.exists(filepath + '.mbp'):
|
|
||||||
os.unlink(filepath + '.mbp')
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.removedirs(os.path.dirname(path))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.report_progress(1.0, _('Removing books from device...'))
|
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, James Ralston <jralston at mindspring.com>'
|
__copyright__ = '2009, James Ralston <jralston at mindspring.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for Ectaco Jetbook firmware >= JL04_v030e
|
Device driver for Ectaco Jetbook firmware >= JL04_v030e
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os, re, sys, shutil
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
@ -54,46 +60,18 @@ class JETBOOK(USBMS):
|
|||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
|
|
||||||
for i, infile in enumerate(files):
|
for i, infile in enumerate(files):
|
||||||
newpath = path
|
mdata, fname = metadata.next(), names.next()
|
||||||
|
path = os.path.dirname(self.create_upload_path(path, mdata, fname))
|
||||||
mdata = metadata.next()
|
|
||||||
|
|
||||||
if 'tags' in mdata.keys():
|
|
||||||
for tag in mdata['tags']:
|
|
||||||
if tag.startswith(_('News')):
|
|
||||||
newpath = os.path.join(newpath, 'news')
|
|
||||||
newpath = os.path.join(newpath, mdata.get('title', ''))
|
|
||||||
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
|
||||||
break
|
|
||||||
elif tag.startswith('/'):
|
|
||||||
newpath += tag
|
|
||||||
newpath = os.path.normpath(newpath)
|
|
||||||
break
|
|
||||||
|
|
||||||
author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_')
|
author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_')
|
||||||
title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_')
|
title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_')
|
||||||
fileext = os.path.splitext(os.path.basename(names.next()))[1]
|
fileext = os.path.splitext(os.path.basename(fname))[1]
|
||||||
fname = '%s#%s%s' % (author, title, fileext)
|
fname = '%s#%s%s' % (author, title, fileext)
|
||||||
|
|
||||||
if newpath == path:
|
filepath = os.path.join(path, fname)
|
||||||
newpath = os.path.join(newpath, author, title)
|
|
||||||
|
|
||||||
if not os.path.exists(newpath):
|
|
||||||
os.makedirs(newpath)
|
|
||||||
|
|
||||||
filepath = os.path.join(newpath, fname)
|
|
||||||
paths.append(filepath)
|
paths.append(filepath)
|
||||||
|
|
||||||
if hasattr(infile, 'read'):
|
self.put_file(infile, filepath, replace_file=True)
|
||||||
infile.seek(0)
|
|
||||||
|
|
||||||
dest = open(filepath, 'wb')
|
|
||||||
shutil.copyfileobj(infile, dest, 10*1024*1024)
|
|
||||||
|
|
||||||
dest.flush()
|
|
||||||
dest.close()
|
|
||||||
else:
|
|
||||||
shutil.copy2(infile, filepath)
|
|
||||||
|
|
||||||
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
@ -132,6 +110,3 @@ class JETBOOK(USBMS):
|
|||||||
drives['carda'] = main
|
drives['carda'] = main
|
||||||
|
|
||||||
return drives
|
return drives
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for Amazon's Kindle
|
Device driver for Amazon's Kindle
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os, re, sys
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
|
|
||||||
class KINDLE(USBMS):
|
class KINDLE(USBMS):
|
||||||
|
|
||||||
name = 'Kindle Device Interface'
|
name = 'Kindle Device Interface'
|
||||||
description = _('Communicate with the Kindle eBook reader.')
|
description = _('Communicate with the Kindle eBook reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
@ -31,26 +38,14 @@ class KINDLE(USBMS):
|
|||||||
MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory'
|
MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory'
|
||||||
STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
|
STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = "documents"
|
EBOOK_DIR_MAIN = 'documents'
|
||||||
EBOOK_DIR_CARD_A = "documents"
|
EBOOK_DIR_CARD_A = 'documents'
|
||||||
|
DELETE_EXTS = ['.mbp']
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
WIRELESS_FILE_NAME_PATTERN = re.compile(
|
WIRELESS_FILE_NAME_PATTERN = re.compile(
|
||||||
r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*')
|
r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*')
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
|
||||||
for i, path in enumerate(paths):
|
|
||||||
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
|
||||||
if os.path.exists(path):
|
|
||||||
os.unlink(path)
|
|
||||||
|
|
||||||
filepath = os.path.splitext(path)[0]
|
|
||||||
|
|
||||||
# Delete the ebook auxiliary file
|
|
||||||
if os.path.exists(filepath + '.mbp'):
|
|
||||||
os.unlink(filepath + '.mbp')
|
|
||||||
self.report_progress(1.0, _('Removing books from device...'))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def metadata_from_path(cls, path):
|
def metadata_from_path(cls, path):
|
||||||
mi = cls.metadata_from_formats([path])
|
mi = cls.metadata_from_formats([path])
|
||||||
@ -65,6 +60,7 @@ class KINDLE(USBMS):
|
|||||||
|
|
||||||
|
|
||||||
class KINDLE2(KINDLE):
|
class KINDLE2(KINDLE):
|
||||||
|
|
||||||
name = 'Kindle 2 Device Interface'
|
name = 'Kindle 2 Device Interface'
|
||||||
description = _('Communicate with the Kindle 2 eBook reader.')
|
description = _('Communicate with the Kindle 2 eBook reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
@ -73,7 +69,9 @@ class KINDLE2(KINDLE):
|
|||||||
PRODUCT_ID = [0x0002]
|
PRODUCT_ID = [0x0002]
|
||||||
BCD = [0x0100]
|
BCD = [0x0100]
|
||||||
|
|
||||||
|
|
||||||
class KINDLE_DX(KINDLE):
|
class KINDLE_DX(KINDLE):
|
||||||
|
|
||||||
name = 'Kindle DX Device Interface'
|
name = 'Kindle DX Device Interface'
|
||||||
description = _('Communicate with the Kindle 2 eBook reader.')
|
description = _('Communicate with the Kindle 2 eBook reader.')
|
||||||
author = _('John Schember')
|
author = _('John Schember')
|
||||||
@ -83,5 +81,3 @@ class KINDLE_DX(KINDLE):
|
|||||||
|
|
||||||
PRODUCT_ID = [0x0003]
|
PRODUCT_ID = [0x0003]
|
||||||
BCD = [0x0100]
|
BCD = [0x0100]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net> ' \
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net> ' \
|
||||||
'2009, John Schember <john at nachtimwald.com>'
|
'2009, John Schember <john at nachtimwald.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for the SONY PRS-505
|
Device driver for the SONY PRS-505
|
||||||
'''
|
'''
|
||||||
import os, re, time
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre.devices.usbms.cli import CLI
|
from calibre.devices.usbms.cli import CLI
|
||||||
from calibre.devices.usbms.device import Device
|
from calibre.devices.usbms.device import Device
|
||||||
from calibre.devices.errors import DeviceError, FreeSpaceError
|
|
||||||
from calibre.devices.prs505.books import BookList, fix_ids
|
from calibre.devices.prs505.books import BookList, fix_ids
|
||||||
from calibre import __appname__
|
from calibre import __appname__
|
||||||
|
|
||||||
@ -80,7 +86,6 @@ class PRS505(CLI, Device):
|
|||||||
self.report_progress(1.0, _('Get device information...'))
|
self.report_progress(1.0, _('Get device information...'))
|
||||||
return (self.__class__.__name__, '', '', '')
|
return (self.__class__.__name__, '', '', '')
|
||||||
|
|
||||||
|
|
||||||
def books(self, oncard=None, end_session=True):
|
def books(self, oncard=None, end_session=True):
|
||||||
if oncard == 'carda' and not self._card_a_prefix:
|
if oncard == 'carda' and not self._card_a_prefix:
|
||||||
self.report_progress(1.0, _('Getting list of books on device...'))
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
@ -105,48 +110,13 @@ class PRS505(CLI, Device):
|
|||||||
|
|
||||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
metadata=None):
|
metadata=None):
|
||||||
if on_card == 'carda' and not self._card_a_prefix:
|
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card == 'cardb' and not self._card_b_prefix:
|
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card and on_card not in ('carda', 'cardb'):
|
|
||||||
raise DeviceError(_('The reader has no storage card in this slot.'))
|
|
||||||
|
|
||||||
if on_card == 'carda':
|
path = self._sanity_check(on_card, files)
|
||||||
path = os.path.join(self._card_a_prefix, self.CARD_PATH_PREFIX)
|
|
||||||
elif on_card == 'cardb':
|
|
||||||
path = os.path.join(self._card_b_prefix, self.CARD_PATH_PREFIX)
|
|
||||||
else:
|
|
||||||
path = os.path.join(self._main_prefix, 'database', 'media', 'books')
|
|
||||||
|
|
||||||
def get_size(obj):
|
|
||||||
if hasattr(obj, 'seek'):
|
|
||||||
obj.seek(0, 2)
|
|
||||||
size = obj.tell()
|
|
||||||
obj.seek(0)
|
|
||||||
return size
|
|
||||||
return os.path.getsize(obj)
|
|
||||||
|
|
||||||
sizes = [get_size(f) for f in files]
|
|
||||||
size = sum(sizes)
|
|
||||||
|
|
||||||
if not on_card and size > self.free_space()[0] - 2*1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space in main memory"))
|
|
||||||
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
|
|
||||||
paths, ctimes = [], []
|
paths, ctimes = [], []
|
||||||
|
|
||||||
names = iter(names)
|
names = iter(names)
|
||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
for i, infile in enumerate(files):
|
for i, infile in enumerate(files):
|
||||||
close = False
|
|
||||||
if not hasattr(infile, 'read'):
|
|
||||||
infile, close = open(infile, 'rb'), True
|
|
||||||
infile.seek(0)
|
|
||||||
|
|
||||||
mdata, fname = metadata.next(), names.next()
|
mdata, fname = metadata.next(), names.next()
|
||||||
filepath = self.create_upload_path(path, mdata, fname)
|
filepath = self.create_upload_path(path, mdata, fname)
|
||||||
|
|
||||||
@ -154,8 +124,6 @@ class PRS505(CLI, Device):
|
|||||||
|
|
||||||
self.put_file(infile, paths[-1], replace_file=True)
|
self.put_file(infile, paths[-1], replace_file=True)
|
||||||
|
|
||||||
if close:
|
|
||||||
infile.close()
|
|
||||||
ctimes.append(os.path.getctime(paths[-1]))
|
ctimes.append(os.path.getctime(paths[-1]))
|
||||||
|
|
||||||
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Device driver for the SONY PRS-700
|
Device driver for the SONY PRS-700
|
||||||
@ -13,9 +16,9 @@ class PRS700(PRS505):
|
|||||||
description = _('Communicate with the Sony PRS-700 eBook reader.')
|
description = _('Communicate with the Sony PRS-700 eBook reader.')
|
||||||
author = _('Kovid Goyal and John Schember')
|
author = _('Kovid Goyal and John Schember')
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
BCD = [0x31a]
|
BCD = [0x31a]
|
||||||
|
|
||||||
WINDOWS_MAIN_MEM = 'PRS-700'
|
WINDOWS_MAIN_MEM = 'PRS-700'
|
||||||
WINDOWS_CARD_A_MEM = 'PRS-700/UC:MS'
|
WINDOWS_CARD_A_MEM = 'PRS-700/UC:MS'
|
||||||
WINDOWS_CARD_B_MEM = 'PRS-700/UC:SD'
|
WINDOWS_CARD_B_MEM = 'PRS-700/UC:SD'
|
||||||
@ -23,4 +26,3 @@ class PRS700(PRS505):
|
|||||||
OSX_MAIN_MEM = 'Sony PRS-700/UC Media'
|
OSX_MAIN_MEM = 'Sony PRS-700/UC Media'
|
||||||
OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media'
|
OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media'
|
||||||
OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD'
|
OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD'
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
__license__ = 'GPL v3'
|
# -*- coding: utf-8 -*-
|
||||||
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
|
||||||
'''
|
|
||||||
'''
|
|
||||||
|
|
||||||
import os, fnmatch, re, time
|
__license__ = 'GPL 3'
|
||||||
|
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
from calibre.devices.interface import BookList as _BookList
|
from calibre.devices.interface import BookList as _BookList
|
||||||
|
|
||||||
class Book(object):
|
class Book(object):
|
||||||
|
|
||||||
def __init__(self, path, title, authors, mime):
|
def __init__(self, path, title, authors, mime):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.authors = authors
|
self.authors = authors
|
||||||
@ -17,30 +21,33 @@ class Book(object):
|
|||||||
self.path = path
|
self.path = path
|
||||||
self.thumbnail = None
|
self.thumbnail = None
|
||||||
self.tags = []
|
self.tags = []
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.path == other.path
|
return self.path == other.path
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def title_sorter(self):
|
def title_sorter(self):
|
||||||
doc = '''String to sort the title. If absent, title is returned'''
|
doc = '''String to sort the title. If absent, title is returned'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', self.title).rstrip()
|
return re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', self.title).rstrip()
|
||||||
return property(doc=doc, fget=fget)
|
return property(doc=doc, fget=fget)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def thumbnail(self):
|
def thumbnail(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" Return a utf-8 encoded string with title author and path information """
|
'''
|
||||||
|
Return a utf-8 encoded string with title author and path information
|
||||||
|
'''
|
||||||
return self.title.encode('utf-8') + " by " + \
|
return self.title.encode('utf-8') + " by " + \
|
||||||
self.authors.encode('utf-8') + " at " + self.path.encode('utf-8')
|
self.authors.encode('utf-8') + " at " + self.path.encode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
class BookList(_BookList):
|
class BookList(_BookList):
|
||||||
|
|
||||||
def supports_tags(self):
|
def supports_tags(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_tags(self, book, tags):
|
def set_tags(self, book, tags):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import with_statement
|
|
||||||
|
|
||||||
__license__ = 'GPL 3'
|
__license__ = 'GPL 3'
|
||||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os, shutil
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
from calibre.devices.errors import PathError
|
from calibre.devices.errors import PathError
|
||||||
|
|
||||||
@ -33,6 +33,10 @@ class CLI(object):
|
|||||||
|
|
||||||
def put_file(self, infile, path, replace_file=False, end_session=True):
|
def put_file(self, infile, path, replace_file=False, end_session=True):
|
||||||
path = self.munge_path(path)
|
path = self.munge_path(path)
|
||||||
|
close = False
|
||||||
|
if not hasattr(infile, 'read'):
|
||||||
|
infile, close = open(infile, 'rb'), True
|
||||||
|
infile.seek(0)
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
path = os.path.join(path, infile.name)
|
path = os.path.join(path, infile.name)
|
||||||
if not replace_file and os.path.exists(path):
|
if not replace_file and os.path.exists(path):
|
||||||
@ -44,6 +48,8 @@ class CLI(object):
|
|||||||
shutil.copyfileobj(infile, dest, 10*1024*1024)
|
shutil.copyfileobj(infile, dest, 10*1024*1024)
|
||||||
dest.flush()
|
dest.flush()
|
||||||
dest.close()
|
dest.close()
|
||||||
|
if close:
|
||||||
|
infile.close()
|
||||||
|
|
||||||
def munge_path(self, path):
|
def munge_path(self, path):
|
||||||
if path.startswith('/') and not (path.startswith(self._main_prefix) or \
|
if path.startswith('/') and not (path.startswith(self._main_prefix) or \
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '''2009, John Schember <john at nachtimwald.com>
|
__copyright__ = '2009, John Schember <john at nachtimwald.com> ' \
|
||||||
and Kovid Goyal <kovid@kovidgoyal.net>'''
|
'2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Generic device driver. This is not a complete stand alone driver. It is
|
Generic device driver. This is not a complete stand alone driver. It is
|
||||||
intended to be subclassed with the relevant parts implemented for a particular
|
intended to be subclassed with the relevant parts implemented for a particular
|
||||||
device. This class handles device detection.
|
device. This class handles device detection.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os, subprocess, time, re, sys, glob, shutil
|
import os
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
import shutil
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
||||||
@ -18,6 +28,7 @@ from calibre import iswindows, islinux, isosx, __appname__
|
|||||||
from calibre.utils.filenames import ascii_filename as sanitize
|
from calibre.utils.filenames import ascii_filename as sanitize
|
||||||
|
|
||||||
class Device(DeviceConfig, DevicePlugin):
|
class Device(DeviceConfig, DevicePlugin):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This class provides logic common to all drivers for devices that export themselves
|
This class provides logic common to all drivers for devices that export themselves
|
||||||
as USB Mass Storage devices. If you are writing such a driver, inherit from this
|
as USB Mass Storage devices. If you are writing such a driver, inherit from this
|
||||||
@ -240,7 +251,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
time.sleep(6)
|
time.sleep(6)
|
||||||
drives = {}
|
drives = {}
|
||||||
wmi = __import__('wmi', globals(), locals(), [], -1)
|
wmi = __import__('wmi', globals(), locals(), [], -1)
|
||||||
@ -294,7 +304,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_osx_mountpoints(self, raw=None):
|
def get_osx_mountpoints(self, raw=None):
|
||||||
raw = self.run_ioreg(raw)
|
raw = self.run_ioreg(raw)
|
||||||
lines = raw.splitlines()
|
lines = raw.splitlines()
|
||||||
@ -458,7 +467,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return node
|
return node
|
||||||
return nodes[-1][0]
|
return nodes[-1][0]
|
||||||
|
|
||||||
|
|
||||||
def open_linux(self):
|
def open_linux(self):
|
||||||
|
|
||||||
def mount(node, type):
|
def mount(node, type):
|
||||||
@ -497,7 +505,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
return None, ret
|
return None, ret
|
||||||
return self.node_mountpoint(node)+'/', 0
|
return self.node_mountpoint(node)+'/', 0
|
||||||
|
|
||||||
|
|
||||||
main, carda, cardb = self.find_device_nodes()
|
main, carda, cardb = self.find_device_nodes()
|
||||||
if main is None:
|
if main is None:
|
||||||
raise DeviceError(_('Unable to detect the %s disk drive.')
|
raise DeviceError(_('Unable to detect the %s disk drive.')
|
||||||
@ -600,7 +607,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def eject(self):
|
def eject(self):
|
||||||
if islinux:
|
if islinux:
|
||||||
try:
|
try:
|
||||||
@ -619,6 +625,40 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
pass
|
pass
|
||||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
||||||
|
|
||||||
|
def _sanity_check(self, on_card, files):
|
||||||
|
if on_card == 'carda' and not self._card_a_prefix:
|
||||||
|
raise ValueError(_('The reader has no storage card in this slot.'))
|
||||||
|
elif on_card == 'cardb' and not self._card_b_prefix:
|
||||||
|
raise ValueError(_('The reader has no storage card in this slot.'))
|
||||||
|
elif on_card and on_card not in ('carda', 'cardb'):
|
||||||
|
raise DeviceError(_('Selected slot: %s is not supported.') % on_card)
|
||||||
|
|
||||||
|
if on_card == 'carda':
|
||||||
|
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
|
||||||
|
elif on_card == 'cardb':
|
||||||
|
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
|
||||||
|
else:
|
||||||
|
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
|
||||||
|
|
||||||
|
def get_size(obj):
|
||||||
|
if hasattr(obj, 'seek'):
|
||||||
|
obj.seek(0, os.SEEK_END)
|
||||||
|
size = obj.tell()
|
||||||
|
obj.seek(0)
|
||||||
|
return size
|
||||||
|
return os.path.getsize(obj)
|
||||||
|
|
||||||
|
sizes = [get_size(f) for f in files]
|
||||||
|
size = sum(sizes)
|
||||||
|
|
||||||
|
if not on_card and size > self.free_space()[0] - 2*1024*1024:
|
||||||
|
raise FreeSpaceError(_("There is insufficient free space in main memory"))
|
||||||
|
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
|
||||||
|
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
||||||
|
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
|
||||||
|
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
||||||
|
return path
|
||||||
|
|
||||||
def create_upload_path(self, path, mdata, fname):
|
def create_upload_path(self, path, mdata, fname):
|
||||||
resizable = []
|
resizable = []
|
||||||
newpath = path
|
newpath = path
|
||||||
@ -681,10 +721,7 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
filepath = filepath.replace(os.sep+os.sep, os.sep)
|
filepath = filepath.replace(os.sep+os.sep, os.sep)
|
||||||
newpath = os.path.dirname(filepath)
|
newpath = os.path.dirname(filepath)
|
||||||
|
|
||||||
|
|
||||||
if not os.path.exists(newpath):
|
if not os.path.exists(newpath):
|
||||||
os.makedirs(newpath)
|
os.makedirs(newpath)
|
||||||
|
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class DeviceConfig(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def settings(cls):
|
def settings(cls):
|
||||||
return cls._config().parse()
|
return cls._config().parse()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def customization_help(cls, gui=False):
|
def customization_help(cls, gui=False):
|
||||||
return cls.HELP_MESSAGE
|
return cls.HELP_MESSAGE
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Generic USB Mass storage device driver. This is not a complete stand alone
|
Generic USB Mass storage device driver. This is not a complete stand alone
|
||||||
driver. It is intended to be subclassed with the relevant parts implemented
|
driver. It is intended to be subclassed with the relevant parts implemented
|
||||||
@ -9,14 +13,12 @@ for a particular device.
|
|||||||
import os
|
import os
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
from calibre.devices.usbms.cli import CLI
|
from calibre.devices.usbms.cli import CLI
|
||||||
from calibre.devices.usbms.device import Device
|
from calibre.devices.usbms.device import Device
|
||||||
from calibre.devices.usbms.books import BookList, Book
|
from calibre.devices.usbms.books import BookList, Book
|
||||||
from calibre.devices.errors import DeviceError, FreeSpaceError
|
|
||||||
from calibre.devices.mime import mime_type_ext
|
from calibre.devices.mime import mime_type_ext
|
||||||
|
|
||||||
# CLI must come before Device as it implments the CLI functions that
|
# CLI must come before Device as it implments the CLI functions that
|
||||||
@ -32,6 +34,7 @@ class USBMS(CLI, Device):
|
|||||||
EBOOK_DIR_MAIN = ''
|
EBOOK_DIR_MAIN = ''
|
||||||
EBOOK_DIR_CARD_A = ''
|
EBOOK_DIR_CARD_A = ''
|
||||||
EBOOK_DIR_CARD_B = ''
|
EBOOK_DIR_CARD_B = ''
|
||||||
|
DELETE_EXTS = []
|
||||||
CAN_SET_METADATA = False
|
CAN_SET_METADATA = False
|
||||||
|
|
||||||
def reset(self, key='-1', log_packets=False, report_progress=None):
|
def reset(self, key='-1', log_packets=False, report_progress=None):
|
||||||
@ -80,40 +83,6 @@ class USBMS(CLI, Device):
|
|||||||
|
|
||||||
return bl
|
return bl
|
||||||
|
|
||||||
def _sanity_check(self, on_card, files):
|
|
||||||
if on_card == 'carda' and not self._card_a_prefix:
|
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card == 'cardb' and not self._card_b_prefix:
|
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card and on_card not in ('carda', 'cardb'):
|
|
||||||
raise DeviceError(_('Selected slot: %s is not supported.') % on_card)
|
|
||||||
|
|
||||||
if on_card == 'carda':
|
|
||||||
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
|
|
||||||
elif on_card == 'cardb':
|
|
||||||
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
|
|
||||||
else:
|
|
||||||
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
|
|
||||||
|
|
||||||
def get_size(obj):
|
|
||||||
if hasattr(obj, 'seek'):
|
|
||||||
obj.seek(0, os.SEEK_END)
|
|
||||||
size = obj.tell()
|
|
||||||
obj.seek(0)
|
|
||||||
return size
|
|
||||||
return os.path.getsize(obj)
|
|
||||||
|
|
||||||
sizes = [get_size(f) for f in files]
|
|
||||||
size = sum(sizes)
|
|
||||||
|
|
||||||
if not on_card and size > self.free_space()[0] - 2*1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space in main memory"))
|
|
||||||
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
return path
|
|
||||||
|
|
||||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
metadata=None):
|
metadata=None):
|
||||||
|
|
||||||
@ -129,16 +98,7 @@ class USBMS(CLI, Device):
|
|||||||
|
|
||||||
paths.append(filepath)
|
paths.append(filepath)
|
||||||
|
|
||||||
if hasattr(infile, 'read'):
|
self.put_file(infile, filepath, replace_file=True)
|
||||||
infile.seek(0)
|
|
||||||
|
|
||||||
dest = open(filepath, 'wb')
|
|
||||||
shutil.copyfileobj(infile, dest, 10*1024*1024)
|
|
||||||
|
|
||||||
dest.flush()
|
|
||||||
dest.close()
|
|
||||||
else:
|
|
||||||
shutil.copy2(infile, filepath)
|
|
||||||
|
|
||||||
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
@ -146,7 +106,6 @@ class USBMS(CLI, Device):
|
|||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
|
|
||||||
def add_books_to_metadata(self, locations, metadata, booklists):
|
def add_books_to_metadata(self, locations, metadata, booklists):
|
||||||
for i, location in enumerate(locations):
|
for i, location in enumerate(locations):
|
||||||
self.report_progress((i+1) / float(len(locations)), _('Adding books to device metadata listing...'))
|
self.report_progress((i+1) / float(len(locations)), _('Adding books to device metadata listing...'))
|
||||||
@ -159,13 +118,18 @@ class USBMS(CLI, Device):
|
|||||||
booklists[blist].append(book)
|
booklists[blist].append(book)
|
||||||
self.report_progress(1.0, _('Adding books to device metadata listing...'))
|
self.report_progress(1.0, _('Adding books to device metadata listing...'))
|
||||||
|
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
for i, path in enumerate(paths):
|
for i, path in enumerate(paths):
|
||||||
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
# Delete the ebook
|
# Delete the ebook
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
|
||||||
|
filepath = os.path.splitext(path)[0]
|
||||||
|
for ext in self.DELETE_EXTS:
|
||||||
|
if os.path.exists(filepath + ext):
|
||||||
|
os.unlink(filepath + ext)
|
||||||
|
|
||||||
if self.SUPPORTS_SUB_DIRS:
|
if self.SUPPORTS_SUB_DIRS:
|
||||||
try:
|
try:
|
||||||
os.removedirs(os.path.dirname(path))
|
os.removedirs(os.path.dirname(path))
|
||||||
@ -199,7 +163,6 @@ class USBMS(CLI, Device):
|
|||||||
with quick_metadata:
|
with quick_metadata:
|
||||||
return metadata_from_formats(fmts)
|
return metadata_from_formats(fmts)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def book_from_path(cls, path):
|
def book_from_path(cls, path):
|
||||||
from calibre.ebooks.metadata.meta import path_to_ext
|
from calibre.ebooks.metadata.meta import path_to_ext
|
||||||
|
Loading…
x
Reference in New Issue
Block a user