Pluginize device drivers.

This commit is contained in:
John Schember 2009-04-30 17:17:56 -04:00
parent 3a2da56ccc
commit d794904319
15 changed files with 91 additions and 37 deletions

View File

@ -221,5 +221,4 @@ class MetadataWriterPlugin(Plugin):
'''
pass

View File

@ -295,9 +295,19 @@ from calibre.ebooks.pdf.output import PDFOutput
from calibre.ebooks.pdb.ereader.output import EREADEROutput
from calibre.customize.profiles import input_profiles, output_profiles
from calibre.devices.prs500.driver import PRS500
from calibre.devices.prs505.driver import PRS505
from calibre.devices.prs700.driver import PRS700
from calibre.devices.cybookg3.driver import CYBOOKG3
from calibre.devices.kindle.driver import KINDLE
from calibre.devices.kindle.driver import KINDLE2
from calibre.devices.blackberry.driver import BLACKBERRY
from calibre.devices.eb600.driver import EB600
plugins = [HTML2ZIP, EPUBInput, MOBIInput, PDBInput, PDFInput, HTMLInput,
TXTInput, OEBOutput, TXTOutput, PDFOutput, LITInput, ComicInput,
FB2Input, ODTInput, RTFInput, EPUBOutput, EREADEROutput, RecipeInput]
plugins += [PRS505, PRS700, CYBOOKG3, KINDLE, KINDLE2, BLACKBERRY, EB600]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \

View File

@ -10,6 +10,7 @@ from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
from calibre.customize.profiles import InputProfile, OutputProfile
from calibre.customize.builtins import plugins as builtin_plugins
from calibre.constants import __version__, iswindows, isosx
from calibre.devices.interface import DevicePlugin
from calibre.ebooks.metadata import MetaInformation
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
plugin_dir, OptionParser
@ -286,6 +287,12 @@ def available_output_formats():
formats.add(plugin.file_type)
return formats
def device_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, DevicePlugin):
if not is_disabled(plugin):
yield plugin
def disable_plugin(plugin_or_name):
x = getattr(plugin_or_name, 'name', plugin_or_name)
plugin = find_plugin(x)

View File

@ -5,18 +5,6 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
Device drivers.
'''
def devices():
from calibre.devices.prs500.driver import PRS500
from calibre.devices.prs505.driver import PRS505
from calibre.devices.prs700.driver import PRS700
from calibre.devices.cybookg3.driver import CYBOOKG3
from calibre.devices.kindle.driver import KINDLE
from calibre.devices.kindle.driver import KINDLE2
from calibre.devices.blackberry.driver import BLACKBERRY
from calibre.devices.eb600.driver import EB600
return (PRS500, PRS505, PRS700, CYBOOKG3, KINDLE, KINDLE2,
BLACKBERRY, EB600)
import time
DAY_MAP = dict(Sun=0, Mon=1, Tue=2, Wed=3, Thu=4, Fri=5, Sat=6)

View File

@ -7,6 +7,12 @@ __docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS
class BLACKBERRY(USBMS):
name = 'Blackberry Device Interface'
description = _('Communicate with the Blackberry smart phone.')
author = _('Kovid Goyal')
supported_platforms = ['windows', 'linux']
# Ordered list of supported formats
FORMATS = ['mobi', 'prc']
@ -16,15 +22,11 @@ class BLACKBERRY(USBMS):
VENDOR_NAME = 'RIM'
WINDOWS_MAIN_MEM = 'BLACKBERRY_SD'
#WINDOWS_CARD_MEM = 'CARD_STORAGE'
#OSX_MAIN_MEM = 'Kindle Internal Storage Media'
#OSX_CARD_MEM = 'Kindle Card Storage Media'
MAIN_MEMORY_VOLUME_LABEL = 'Blackberry Main Memory'
#STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
EBOOK_DIR_MAIN = 'ebooks'
#EBOOK_DIR_CARD = "documents"
SUPPORTS_SUB_DIRS = True

View File

@ -12,6 +12,12 @@ from calibre.devices.usbms.driver import USBMS
import calibre.devices.cybookg3.t2b as t2b
class CYBOOKG3(USBMS):
name = 'Cybook Gen 3 Device Interface'
description = _('Communicate with the Cybook 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']

View File

@ -7,6 +7,11 @@ Device driver for the Netronix EB600
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', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt', 'pdf']
DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt']

View File

@ -6,8 +6,9 @@ the GUI. A device backend must subclass the L{Device} class. See prs500.py for
a backend that implement the Device interface for the SONY PRS500 Reader.
"""
from calibre.customize import Plugin
class Device(object):
class DevicePlugin(Plugin):
"""
Defines the interface that should be implemented by backends that
communicate with an ebook reader.
@ -16,6 +17,8 @@ class Device(object):
the front-end needs to call several methods one after another, in which case
the USB session should not be closed after each method call.
"""
type = _('Device Interface')
# Ordered list of supported formats
FORMATS = ["lrf", "rtf", "pdf", "txt"]
VENDOR_ID = 0x0000
@ -27,8 +30,8 @@ class Device(object):
# Whether the metadata on books can be set via the GUI.
CAN_SET_METADATA = True
def __init__(self, key='-1', log_packets=False, report_progress=None) :
"""
def reset(self, key='-1', log_packets=False, report_progress=None) :
"""
@param key: The key to unlock the device
@param log_packets: If true the packet stream to/from the device is logged
@param report_progress: Function that is called with a % progress

View File

@ -6,9 +6,14 @@ Device driver for Amazon's Kindle
import os, re, sys
from calibre.devices.usbms.driver import USBMS, metadata_from_formats
from calibre.devices.usbms.driver import USBMS
class KINDLE(USBMS):
name = 'Kindle Device Interface'
description = _('Communicate with the Kindle eBook reader.')
author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['azw', 'mobi', 'prc', 'azw1', 'tpz', 'txt']
@ -46,6 +51,7 @@ class KINDLE(USBMS):
@classmethod
def metadata_from_path(cls, path):
from calibre.devices.usbms.driver import metadata_from_formats
mi = metadata_from_formats([path])
if mi.title == _('Unknown') or ('-asin' in mi.title and '-type' in mi.title):
match = cls.WIRELESS_FILE_NAME_PATTERN.match(os.path.basename(path))
@ -58,6 +64,10 @@ class KINDLE(USBMS):
class KINDLE2(KINDLE):
name = 'Kindle 2 Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.')
author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux']
PRODUCT_ID = [0x0002]
BCD = [0x0100]

View File

@ -40,7 +40,7 @@ from array import array
from functools import wraps
from StringIO import StringIO
from calibre.devices.interface import Device
from calibre.devices.interface import DevicePlugin
from calibre.devices.libusb import Error as USBError
from calibre.devices.libusb import get_device_by_id
from calibre.devices.prs500.prstypes import *
@ -76,12 +76,16 @@ class File(object):
return self.name
class PRS500(Device):
class PRS500(DevicePlugin):
"""
Implements the backend for communication with the SONY Reader.
Each method decorated by C{safe} performs a task.
"""
name = 'PRS-500 Device Interface'
description = _('Communicate with the Sony PRS-500 eBook reader.')
author = _('Kovid Goyal')
supported_platforms = ['windows', 'osx', 'linux']
VENDOR_ID = 0x054c #: SONY Vendor Id
PRODUCT_ID = 0x029b #: Product Id for the PRS-500
@ -181,7 +185,7 @@ class PRS500(Device):
return run_session
def __init__(self, key='-1', log_packets=False, report_progress=None) :
def reset(self, key='-1', log_packets=False, report_progress=None) :
"""
@param key: The key to unlock the device
@param log_packets: If true the packet stream to/from the device is logged

View File

@ -1,5 +1,6 @@
__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>'
'''
Device driver for the SONY PRS-505
'''
@ -14,6 +15,12 @@ from calibre import iswindows, islinux, isosx, __appname__
from calibre.devices.errors import PathError
class PRS505(CLI, Device):
name = 'PRS-505 Device Interface'
description = _('Communicate with the Sony PRS-505 eBook reader.')
author = _('Kovid Goyal and John Schember')
supported_platforms = ['windows', 'osx', 'linux']
FORMATS = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
VENDOR_ID = [0x054c] #: SONY Vendor Id

View File

@ -8,6 +8,11 @@ Device driver for the SONY PRS-700
from calibre.devices.prs505.driver import PRS505
class PRS700(PRS505):
name = 'PRS-700 Device Interface'
description = _('Communicate with the Sony PRS-700 eBook reader.')
author = _('Kovid Goyal and John Schember')
supported_platforms = ['windows', 'osx', 'linux']
BCD = [0x31a]

View File

@ -8,11 +8,11 @@ device. This class handles device detection.
import os, subprocess, time, re
from calibre.devices.interface import Device as _Device
from calibre.devices.interface import DevicePlugin as Device
from calibre.devices.errors import DeviceError
from calibre import iswindows, islinux, isosx, __appname__
class Device(_Device):
class Device(Device):
'''
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
@ -83,7 +83,7 @@ class Device(_Device):
FDI_BCD_TEMPLATE = '<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.device_revision_bcd" int="%(bcd)s">'
def __init__(self, key='-1', log_packets=False, report_progress=None) :
def reset(self, key='-1', log_packets=False, report_progress=None) :
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
@classmethod

View File

@ -10,7 +10,6 @@ for a particular device.
import os, fnmatch, shutil
from itertools import cycle
from calibre.ebooks.metadata.meta import metadata_from_formats, path_to_ext
from calibre.ebooks.metadata import authors_to_string
from calibre.devices.usbms.cli import CLI
from calibre.devices.usbms.device import Device
@ -21,6 +20,12 @@ from calibre.devices.mime import mime_type_ext
# CLI must come before Device as it implments the CLI functions that
# are inherited from the device interface in Device.
class USBMS(CLI, Device):
name = 'USBMS Base Device Interface'
description = _('Communicate with an eBook reader.')
author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux']
FORMATS = []
EBOOK_DIR_MAIN = ''
EBOOK_DIR_CARD_A = ''
@ -28,8 +33,8 @@ class USBMS(CLI, Device):
SUPPORTS_SUB_DIRS = False
CAN_SET_METADATA = False
def __init__(self, key='-1', log_packets=False, report_progress=None):
Device.__init__(self, key=key, log_packets=log_packets,
def reset(self, key='-1', log_packets=False, report_progress=None):
Device.reset(self, key=key, log_packets=log_packets,
report_progress=report_progress)
def get_device_information(self, end_session=True):
@ -40,6 +45,7 @@ class USBMS(CLI, Device):
return (self.__class__.__name__, '', '', '')
def books(self, oncard=None, end_session=True):
from calibre.ebooks.metadata.meta import path_to_ext
bl = BookList()
if oncard == 'carda' and not self._card_a_prefix:
@ -185,10 +191,12 @@ class USBMS(CLI, Device):
@classmethod
def metadata_from_path(cls, path):
from calibre.ebooks.metadata.meta import metadata_from_formats
return metadata_from_formats([path])
@classmethod
def book_from_path(cls, path):
from calibre.ebooks.metadata.meta import path_to_ext
fileext = path_to_ext(path)
mi = cls.metadata_from_path(path)
mime = mime_type_ext(fileext)

View File

@ -10,8 +10,8 @@ from binascii import unhexlify
from PyQt4.Qt import QMenu, QAction, QActionGroup, QIcon, SIGNAL, QPixmap, \
Qt
from calibre.customize.ui import available_input_formats, available_output_formats
from calibre.devices import devices
from calibre.customize.ui import available_input_formats, available_output_formats, \
device_plugins
from calibre.constants import iswindows
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
from calibre.parallel import Job
@ -21,7 +21,6 @@ from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \
info_dialog
from calibre.ebooks.metadata import authors_to_string
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
from calibre.devices.interface import Device
from calibre import sanitize_file_name, preferred_encoding
from calibre.utils.filenames import ascii_filename
from calibre.devices.errors import FreeSpaceError
@ -54,7 +53,7 @@ class DeviceManager(Thread):
'''
Thread.__init__(self)
self.setDaemon(True)
self.devices = [[d, False] for d in devices()]
self.devices = [[d, False] for d in device_plugins()]
self.device = None
self.device_class = None
self.sleep_time = sleep_time
@ -71,7 +70,8 @@ class DeviceManager(Thread):
connected = self.scanner.is_device_connected(device[0])
if connected and not device[1]:
try:
dev = device[0]()
dev = device[0]
dev.reset()
if iswindows:
import pythoncom
pythoncom.CoInitialize()