diff --git a/src/calibre/devices/__init__.py b/src/calibre/devices/__init__.py index 5c7da00861..37ec55c149 100644 --- a/src/calibre/devices/__init__.py +++ b/src/calibre/devices/__init__.py @@ -56,6 +56,12 @@ def get_connected_device(): return dev def debug(ioreg_to_tmp=False, buf=None, plugins=None): + ''' + If plugins is None, then this method calls startup and shutdown on the + device plugins. So if you are using it in a context where startup could + already have been called (for example in the main GUI), pass in the list of + device plugins as the plugins parameter. + ''' import textwrap from calibre.customize.ui import device_plugins from calibre.devices.scanner import DeviceScanner, win_pnp_drives diff --git a/src/calibre/devices/mtp/base.py b/src/calibre/devices/mtp/base.py index f29f525b30..7f20b70b39 100644 --- a/src/calibre/devices/mtp/base.py +++ b/src/calibre/devices/mtp/base.py @@ -7,8 +7,17 @@ __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from functools import wraps + from calibre.devices.interface import DevicePlugin +def synchronous(func): + @wraps(func) + def synchronizer(self, *args, **kwargs): + with self.lock: + return func(self, *args, **kwargs) + return synchronizer + class MTPDeviceBase(DevicePlugin): name = 'SmartDevice App Interface' gui_name = _('MTP Device') diff --git a/src/calibre/devices/mtp/unix/driver.py b/src/calibre/devices/mtp/unix/driver.py index 86f2c9b573..d8cd7ee01d 100644 --- a/src/calibre/devices/mtp/unix/driver.py +++ b/src/calibre/devices/mtp/unix/driver.py @@ -9,23 +9,15 @@ __docformat__ = 'restructuredtext en' import time, operator from threading import RLock -from functools import wraps from itertools import chain from collections import deque, OrderedDict from io import BytesIO from calibre import prints from calibre.devices.errors import OpenFailed -from calibre.devices.mtp.base import MTPDeviceBase +from calibre.devices.mtp.base import MTPDeviceBase, synchronous from calibre.devices.mtp.unix.detect import MTPDetect -def synchronous(func): - @wraps(func) - def synchronizer(self, *args, **kwargs): - with self.lock: - return func(self, *args, **kwargs) - return synchronizer - class FilesystemCache(object): def __init__(self, files, folders): @@ -190,15 +182,19 @@ class MTP_DEVICE(MTPDeviceBase): if len(storage) > 2: self._cardb_id = storage[2]['id'] - files, errs = self.dev.get_filelist(self) - if errs and not files: - raise OpenFailed('Failed to read files from device. Underlying errors:\n' - +self.format_errorstack(errs)) - folders, errs = self.dev.get_folderlist() - if errs and not folders: - raise OpenFailed('Failed to read folders from device. Underlying errors:\n' - +self.format_errorstack(errs)) - self.filesystem_cache = FilesystemCache(files, folders) + try: + files, errs = self.dev.get_filelist(self) + if errs and not files: + raise OpenFailed('Failed to read files from device. Underlying errors:\n' + +self.format_errorstack(errs)) + folders, errs = self.dev.get_folderlist() + if errs and not folders: + raise OpenFailed('Failed to read folders from device. Underlying errors:\n' + +self.format_errorstack(errs)) + self.filesystem_cache = FilesystemCache(files, folders) + except: + self.dev = self._main_id = self._carda_id = self._cardb_id = None + raise @synchronous def get_device_information(self, end_session=True):