Refactor and clean up of device drivers.

This commit is contained in:
John Schember 2009-08-02 13:37:19 -04:00
parent 024d47046e
commit 1e19801b37
16 changed files with 181 additions and 309 deletions

View File

@ -1,21 +1,18 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS
class ANDROID(USBMS):
name = 'Android driver'
description = _('Communicate with Android phones.')
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['epub']
@ -34,5 +31,3 @@ class ANDROID(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'Android Internal Memory'
SUPPORTS_SUB_DIRS = True

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, Tijmen Ruizendaal <tijmen at mybebook.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for BeBook
@ -10,12 +13,12 @@ import re
from calibre.devices.usbms.driver import USBMS
class BEBOOK(USBMS):
name = 'BeBook driver'
description = _('Communicate with the BeBook eBook reader.')
author = 'Tijmen Ruizendaal'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['mobi', 'epub', 'pdf', 'txt']
@ -94,4 +97,3 @@ class BEBOOK_MINI(BEBOOK):
MAIN_MEMORY_VOLUME_LABEL = 'BeBook Mini Internal Memory'
STORAGE_CARD_VOLUME_LABEL = 'BeBook Mini Storage Card'

View File

@ -1,9 +1,9 @@
from __future__ import with_statement
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS
class BLACKBERRY(USBMS):
@ -29,4 +29,3 @@ class BLACKBERRY(USBMS):
EBOOK_DIR_MAIN = 'ebooks'
SUPPORTS_SUB_DIRS = True

View File

@ -1,24 +1,26 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for Bookeen's Cybook Gen 3
'''
import os
import shutil
from itertools import cycle
from calibre.utils.filenames import ascii_filename as sanitize
from calibre.devices.usbms.driver import USBMS
import calibre.devices.cybookg3.t2b as t2b
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')
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt']
@ -31,19 +33,21 @@ class CYBOOKG3(USBMS):
WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD'
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'
MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Cybook Gen 3 Storage Card'
EBOOK_DIR_MAIN = "eBooks"
EBOOK_DIR_CARD_A = "eBooks"
EBOOK_DIR_MAIN = 'eBooks'
EBOOK_DIR_CARD_A = 'eBooks'
THUMBNAIL_HEIGHT = 144
DELETE_EXTS = ['.mbp', '.dat', '_6090.t2b']
SUPPORTS_SUB_DIRS = True
def upload_books(self, files, names, on_card=None, end_session=True,
metadata=None):
path = self._sanity_check(on_card, files)
paths = []
@ -51,45 +55,16 @@ class CYBOOKG3(USBMS):
metadata = iter(metadata)
for i, infile in enumerate(files):
newpath = path
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, 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()))
mdata, fname = metadata.next(), names.next()
filepath = self.create_upload_path(path, mdata, fname)
paths.append(filepath)
if hasattr(infile, 'read'):
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
self.put_file(infile, filepath, replace_file=True)
coverdata = None
if 'cover' in mdata.keys():
if mdata['cover'] != None:
coverdata = mdata['cover'][2]
cover = mdata.get('cover', None)
if cover:
coverdata = cover[2]
t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb')
t2b.write_t2b(t2bfile, coverdata)
@ -101,31 +76,13 @@ class CYBOOKG3(USBMS):
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
if os.path.exists(filepath + '.mbp'):
os.unlink(filepath + '.mbp')
if os.path.exists(filepath + '.dat'):
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):
name = 'Cybook Opus Device Interface'
description = _('Communicate with the Cybook Opus eBook reader.')
author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux']
FORMATS = ['epub', 'pdf', 'txt']
@ -133,14 +90,13 @@ class CYBOOK_OPUS(CYBOOKG3):
PRODUCT_ID = [0x0703]
BCD = [0x110]
VENDOR_NAME = 'BOOKEEN'
WINDOWS_MAIN_MEM = 'CYBOOK_OPUS__-FD'
WINDOWS_CARD_A_MEM = 'CYBOOK_OPUS__-SD'
OSX_MAIN_MEM = 'Bookeen Cybook Opus -FD Media'
OSX_CARD_A_MEM = 'Bookeen Cybook Opus -SD Media'
def upload_books(self, *args, **kwargs):
USBMS.upload_books(self, *args, **kwargs)
def delete_books(self, *args, **kwargs):
USBMS.delete_books(self, *args, **kwargs)
EBOOK_DIR_MAIN = 'eBooks'
EBOOK_DIR_CARD_A = 'eBooks'
SUPPORTS_SUB_DIRS = True

View File

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
'''
Device driver for the Netronix EB600
@ -14,13 +18,15 @@ Windows PNP strings:
from calibre.devices.usbms.driver import USBMS
class EB600(USBMS):
name = 'Netronix EB600 Device Interface'
description = _('Communicate with the EB600 eBook reader.')
author = _('Kovid Goyal')
supported_platforms = ['windows', 'osx', 'linux']
# 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']
VENDOR_ID = [0x1f85]
@ -59,4 +65,3 @@ class COOL_ER(EB600):
WINDOWS_MAIN_MEM = 'EREADER'
EBOOK_DIR_MAIN = 'my docs'

View File

@ -8,17 +8,15 @@ __docformat__ = 'restructuredtext en'
Device driver for IRex Iliad
'''
import os
from calibre.devices.usbms.driver import USBMS
class ILIAD(USBMS):
name = 'IRex Iliad Device Interface'
description = _('Communicate with the IRex Iliad eBook reader.')
author = _('John Schember')
supported_platforms = ['windows', 'linux']
# Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'txt']
@ -35,23 +33,5 @@ class ILIAD(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'IRex Iliad Main Memory'
EBOOK_DIR_MAIN = 'books'
DELETE_EXTS = ['.mbp']
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...'))

View File

@ -8,17 +8,16 @@ __docformat__ = 'restructuredtext en'
Device driver for IRex Digiatal Reader
'''
import os
from calibre.devices.usbms.driver import USBMS
class IREXDR1000(USBMS):
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')
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime
FORMATS = ['epub', 'mobi', 'prc', 'html', 'pdf', 'txt']
@ -35,23 +34,5 @@ class IREXDR1000(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'IRex Digital Reader 1000 Main Memory'
EBOOK_DIR_MAIN = 'ebooks'
DELETE_EXTS = ['.mbp']
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...'))

View File

@ -1,10 +1,16 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, James Ralston <jralston at mindspring.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for Ectaco Jetbook firmware >= JL04_v030e
'''
import os, re, sys, shutil
import os
import re
import sys
from itertools import cycle
from calibre.devices.usbms.driver import USBMS
@ -54,46 +60,18 @@ class JETBOOK(USBMS):
metadata = iter(metadata)
for i, infile in enumerate(files):
newpath = path
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
mdata, fname = metadata.next(), names.next()
path = os.path.dirname(self.create_upload_path(path, mdata, fname))
author = sanitize(mdata.get('authors','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)
if newpath == path:
newpath = os.path.join(newpath, author, title)
if not os.path.exists(newpath):
os.makedirs(newpath)
filepath = os.path.join(newpath, fname)
filepath = os.path.join(path, fname)
paths.append(filepath)
if hasattr(infile, 'read'):
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
self.put_file(infile, filepath, replace_file=True)
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
@ -132,6 +110,3 @@ class JETBOOK(USBMS):
drives['carda'] = main
return drives

View File

@ -1,14 +1,21 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for Amazon's Kindle
'''
import os, re, sys
import os
import re
import sys
from calibre.devices.usbms.driver import USBMS
class KINDLE(USBMS):
name = 'Kindle Device Interface'
description = _('Communicate with the Kindle eBook reader.')
author = _('John Schember')
@ -31,26 +38,14 @@ class KINDLE(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
EBOOK_DIR_MAIN = "documents"
EBOOK_DIR_CARD_A = "documents"
EBOOK_DIR_MAIN = 'documents'
EBOOK_DIR_CARD_A = 'documents'
DELETE_EXTS = ['.mbp']
SUPPORTS_SUB_DIRS = True
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+).*')
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
def metadata_from_path(cls, path):
mi = cls.metadata_from_formats([path])
@ -65,6 +60,7 @@ class KINDLE(USBMS):
class KINDLE2(KINDLE):
name = 'Kindle 2 Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.')
author = _('John Schember')
@ -73,7 +69,9 @@ class KINDLE2(KINDLE):
PRODUCT_ID = [0x0002]
BCD = [0x0100]
class KINDLE_DX(KINDLE):
name = 'Kindle DX Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.')
author = _('John Schember')
@ -83,5 +81,3 @@ class KINDLE_DX(KINDLE):
PRODUCT_ID = [0x0003]
BCD = [0x0100]

View File

@ -1,15 +1,21 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net> ' \
'2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for the SONY PRS-505
'''
import os, re, time
import os
import re
import time
from itertools import cycle
from calibre.devices.usbms.cli import CLI
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 import __appname__
@ -80,7 +86,6 @@ class PRS505(CLI, Device):
self.report_progress(1.0, _('Get device information...'))
return (self.__class__.__name__, '', '', '')
def books(self, oncard=None, end_session=True):
if oncard == 'carda' and not self._card_a_prefix:
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,
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 = 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"))
path = self._sanity_check(on_card, files)
paths, ctimes = [], []
names = iter(names)
metadata = iter(metadata)
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()
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)
if close:
infile.close()
ctimes.append(os.path.getctime(paths[-1]))
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
'''
Device driver for the SONY PRS-700
@ -23,4 +26,3 @@ class PRS700(PRS505):
OSX_MAIN_MEM = 'Sony PRS-700/UC Media'
OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media'
OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD'

View File

@ -1,13 +1,17 @@
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
'''
'''
# -*- coding: utf-8 -*-
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
class Book(object):
def __init__(self, path, title, authors, mime):
self.title = title
self.authors = authors
@ -33,14 +37,17 @@ class Book(object):
return None
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 " + \
self.authors.encode('utf-8') + " at " + self.path.encode('utf-8')
class BookList(_BookList):
def supports_tags(self):
return False
def set_tags(self, book, tags):
pass

View File

@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
__license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import os, shutil
import os
import shutil
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):
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):
path = os.path.join(path, infile.name)
if not replace_file and os.path.exists(path):
@ -44,6 +48,8 @@ class CLI(object):
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
if close:
infile.close()
def munge_path(self, path):
if path.startswith('/') and not (path.startswith(self._main_prefix) or \

View File

@ -1,13 +1,23 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '''2009, John Schember <john at nachtimwald.com>
and Kovid Goyal <kovid@kovidgoyal.net>'''
__copyright__ = '2009, John Schember <john at nachtimwald.com> ' \
'2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
'''
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
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 math import ceil
@ -18,6 +28,7 @@ from calibre import iswindows, islinux, isosx, __appname__
from calibre.utils.filenames import ascii_filename as sanitize
class Device(DeviceConfig, DevicePlugin):
'''
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
@ -240,7 +251,6 @@ class Device(DeviceConfig, DevicePlugin):
return True
return False
time.sleep(6)
drives = {}
wmi = __import__('wmi', globals(), locals(), [], -1)
@ -294,7 +304,6 @@ class Device(DeviceConfig, DevicePlugin):
return True
return False
def get_osx_mountpoints(self, raw=None):
raw = self.run_ioreg(raw)
lines = raw.splitlines()
@ -458,7 +467,6 @@ class Device(DeviceConfig, DevicePlugin):
return node
return nodes[-1][0]
def open_linux(self):
def mount(node, type):
@ -497,7 +505,6 @@ class Device(DeviceConfig, DevicePlugin):
return None, ret
return self.node_mountpoint(node)+'/', 0
main, carda, cardb = self.find_device_nodes()
if main is None:
raise DeviceError(_('Unable to detect the %s disk drive.')
@ -600,7 +607,6 @@ class Device(DeviceConfig, DevicePlugin):
except:
pass
def eject(self):
if islinux:
try:
@ -619,6 +625,40 @@ class Device(DeviceConfig, DevicePlugin):
pass
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):
resizable = []
newpath = path
@ -681,10 +721,7 @@ class Device(DeviceConfig, DevicePlugin):
filepath = filepath.replace(os.sep+os.sep, os.sep)
newpath = os.path.dirname(filepath)
if not os.path.exists(newpath):
os.makedirs(newpath)
return filepath

View File

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
'''
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
@ -9,14 +13,12 @@ for a particular device.
import os
import fnmatch
import re
import shutil
from itertools import cycle
from calibre.ebooks.metadata import authors_to_string
from calibre.devices.usbms.cli import CLI
from calibre.devices.usbms.device import Device
from calibre.devices.usbms.books import BookList, Book
from calibre.devices.errors import DeviceError, FreeSpaceError
from calibre.devices.mime import mime_type_ext
# 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_CARD_A = ''
EBOOK_DIR_CARD_B = ''
DELETE_EXTS = []
CAN_SET_METADATA = False
def reset(self, key='-1', log_packets=False, report_progress=None):
@ -80,40 +83,6 @@ class USBMS(CLI, Device):
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,
metadata=None):
@ -129,16 +98,7 @@ class USBMS(CLI, Device):
paths.append(filepath)
if hasattr(infile, 'read'):
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
self.put_file(infile, filepath, replace_file=True)
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]))
def add_books_to_metadata(self, locations, metadata, booklists):
for i, location in enumerate(locations):
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)
self.report_progress(1.0, _('Adding books to device metadata listing...'))
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):
# Delete the ebook
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:
try:
os.removedirs(os.path.dirname(path))
@ -199,7 +163,6 @@ class USBMS(CLI, Device):
with quick_metadata:
return metadata_from_formats(fmts)
@classmethod
def book_from_path(cls, path):
from calibre.ebooks.metadata.meta import path_to_ext