mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
MTP: Implement get_device_information()
This commit is contained in:
parent
47dd9752f3
commit
6627f20c2c
@ -35,13 +35,14 @@ class MTPDeviceBase(DevicePlugin):
|
||||
DevicePlugin.__init__(self, *args, **kwargs)
|
||||
self.progress_reporter = None
|
||||
self.current_friendly_name = None
|
||||
self.report_progress = lambda x, y: None
|
||||
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||
detected_device=None):
|
||||
pass
|
||||
|
||||
def set_progress_reporter(self, report_progress):
|
||||
self.progress_reporter = report_progress
|
||||
self.report_progress = report_progress
|
||||
|
||||
def get_gui_name(self):
|
||||
return self.current_friendly_name or self.name
|
||||
|
@ -7,14 +7,86 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from calibre.constants import iswindows
|
||||
import json, pprint
|
||||
from io import BytesIO
|
||||
|
||||
from calibre.constants import iswindows, numeric_version
|
||||
from calibre.utils.config import from_json, to_json
|
||||
from calibre.utils.date import now, isoformat
|
||||
|
||||
if iswindows:
|
||||
from calibre.devices.mtp.windows.driver import MTP_DEVICE as BASE
|
||||
BASE
|
||||
else:
|
||||
from calibre.devices.mtp.unix.driver import MTP_DEVICE as BASE
|
||||
pprint
|
||||
|
||||
class MTP_DEVICE(BASE):
|
||||
pass
|
||||
|
||||
METADATA_CACHE = 'metadata.calibre'
|
||||
DRIVEINFO = 'driveinfo.calibre'
|
||||
|
||||
def _update_drive_info(self, storage, location_code, name=None):
|
||||
import uuid
|
||||
f = storage.find_path((self.DRIVEINFO,))
|
||||
dinfo = {}
|
||||
if f is not None:
|
||||
stream = self.get_file(f)
|
||||
try:
|
||||
dinfo = json.load(stream, object_hook=from_json)
|
||||
except:
|
||||
dinfo = None
|
||||
if dinfo.get('device_store_uuid', None) is None:
|
||||
dinfo['device_store_uuid'] = unicode(uuid.uuid4())
|
||||
if dinfo.get('device_name', None) is None:
|
||||
dinfo['device_name'] = self.current_friendly_name
|
||||
if name is not None:
|
||||
dinfo['device_name'] = name
|
||||
dinfo['location_code'] = location_code
|
||||
dinfo['last_library_uuid'] = getattr(self, 'current_library_uuid', None)
|
||||
dinfo['calibre_version'] = '.'.join([unicode(i) for i in numeric_version])
|
||||
dinfo['date_last_connected'] = isoformat(now())
|
||||
dinfo['mtp_prefix'] = storage.storage_prefix
|
||||
raw = json.dumps(dinfo, default=to_json)
|
||||
self.put_file(storage, self.DRIVEINFO, BytesIO(raw), len(raw))
|
||||
self.driveinfo = dinfo
|
||||
|
||||
def open(self, devices, library_uuid):
|
||||
self.current_library_uuid = library_uuid
|
||||
BASE.open(self, devices, library_uuid)
|
||||
|
||||
def get_device_information(self, end_session=True):
|
||||
self.report_progress(1.0, _('Get device information...'))
|
||||
self.driveinfo = {}
|
||||
for sid, location_code in ( (self._main_id, 'main'), (self._carda_id,
|
||||
'A'), (self._cardb_id, 'B')):
|
||||
if sid is None: continue
|
||||
self._update_drive_info(self.filesystem_cache.storage(sid), location_code)
|
||||
dinfo = self.get_basic_device_information()
|
||||
return tuple( list(dinfo) + [self.driveinfo] )
|
||||
|
||||
def card_prefix(self, end_session=True):
|
||||
ans = [None, None]
|
||||
if self._carda_id is not None:
|
||||
ans[0] = self.filesystem_cache.storage(self._carda_id).storage_prefix
|
||||
if self._cardb_id is not None:
|
||||
ans[1] = self.filesystem_cache.storage(self._cardb_id).storage_prefix
|
||||
return tuple(ans)
|
||||
|
||||
if __name__ == '__main__':
|
||||
dev = MTP_DEVICE(None)
|
||||
dev.startup()
|
||||
try:
|
||||
from calibre.devices.scanner import DeviceScanner
|
||||
scanner = DeviceScanner()
|
||||
scanner.scan()
|
||||
devs = scanner.devices
|
||||
cd = dev.detect_managed_devices(devs)
|
||||
if cd is None:
|
||||
raise ValueError('Failed to detect MTP device')
|
||||
dev.open(cd, None)
|
||||
pprint.pprint(dev.get_device_information())
|
||||
finally:
|
||||
dev.shutdown()
|
||||
|
||||
|
||||
|
@ -47,6 +47,9 @@ class FileOrFolder(object):
|
||||
self.fs_cache = weakref.ref(fs_cache)
|
||||
self.deleted = False
|
||||
|
||||
if self.storage_id == self.object_id:
|
||||
self.storage_prefix = 'mtp:::%s:::'%self.persistent_id
|
||||
|
||||
def __repr__(self):
|
||||
name = 'Folder' if self.is_folder else 'File'
|
||||
try:
|
||||
@ -125,6 +128,26 @@ class FileOrFolder(object):
|
||||
return e
|
||||
return None
|
||||
|
||||
def find_path(self, path):
|
||||
'''
|
||||
Find a path in this folder, where path is a
|
||||
tuple of folder and file names like ('eBooks', 'newest',
|
||||
'calibre.epub'). Finding is case-insensitive.
|
||||
'''
|
||||
parent = self
|
||||
components = list(path)
|
||||
while components:
|
||||
child = components[0]
|
||||
components = components[1:]
|
||||
c = parent.folder_named(child)
|
||||
if c is None:
|
||||
c = parent.file_named(child)
|
||||
if c is None:
|
||||
return None
|
||||
parent = c
|
||||
return parent
|
||||
|
||||
|
||||
class FilesystemCache(object):
|
||||
|
||||
def __init__(self, all_storage, entries):
|
||||
@ -164,4 +187,9 @@ class FilesystemCache(object):
|
||||
for e in self.entries:
|
||||
e.dump(out=out)
|
||||
|
||||
def storage(self, storage_id):
|
||||
for e in self.entries:
|
||||
if e.storage_id == storage_id:
|
||||
return e
|
||||
|
||||
|
||||
|
@ -46,14 +46,6 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
def set_debug_level(self, lvl):
|
||||
self.libmtp.set_debug_level(lvl)
|
||||
|
||||
def report_progress(self, sent, total):
|
||||
try:
|
||||
p = int(sent/total * 100)
|
||||
except ZeroDivisionError:
|
||||
p = 100
|
||||
if self.progress_reporter is not None:
|
||||
self.progress_reporter(p)
|
||||
|
||||
@synchronous
|
||||
def detect_managed_devices(self, devices_on_system, force_refresh=False):
|
||||
if self.libmtp is None: return None
|
||||
@ -212,19 +204,10 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
return self._filesystem_cache
|
||||
|
||||
@synchronous
|
||||
def get_device_information(self, end_session=True):
|
||||
def get_basic_device_information(self):
|
||||
d = self.dev
|
||||
return (self.current_friendly_name, d.device_version, d.device_version, '')
|
||||
|
||||
@synchronous
|
||||
def card_prefix(self, end_session=True):
|
||||
ans = [None, None]
|
||||
if self._carda_id is not None:
|
||||
ans[0] = 'mtp:::%d:::'%self._carda_id
|
||||
if self._cardb_id is not None:
|
||||
ans[1] = 'mtp:::%d:::'%self._cardb_id
|
||||
return tuple(ans)
|
||||
|
||||
@synchronous
|
||||
def total_space(self, end_session=True):
|
||||
ans = [0, 0, 0]
|
||||
@ -298,6 +281,7 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
if not ok:
|
||||
raise DeviceError('Failed to get file: %s with errors: %s'%(
|
||||
f.full_path, self.format_errorstack(errs)))
|
||||
stream.seek(0)
|
||||
return stream
|
||||
|
||||
@synchronous
|
||||
|
@ -203,24 +203,11 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
self.current_friendly_name = devdata.get('friendly_name', None)
|
||||
|
||||
@same_thread
|
||||
def get_device_information(self, end_session=True):
|
||||
def get_basic_device_information(self):
|
||||
d = self.dev.data
|
||||
dv = d.get('device_version', '')
|
||||
for sid, location_code in ( (self._main_id, 'main'), (self._carda_id,
|
||||
'A'), (self._cardb_id, 'B')):
|
||||
if sid is None: continue
|
||||
# TODO: Implement the drive info dict
|
||||
return (self.current_friendly_name, dv, dv, '')
|
||||
|
||||
@same_thread
|
||||
def card_prefix(self, end_session=True):
|
||||
ans = [None, None]
|
||||
if self._carda_id is not None:
|
||||
ans[0] = 'mtp:::%s:::'%self._carda_id
|
||||
if self._cardb_id is not None:
|
||||
ans[1] = 'mtp:::%s:::'%self._cardb_id
|
||||
return tuple(ans)
|
||||
|
||||
@same_thread
|
||||
def total_space(self, end_session=True):
|
||||
ans = [0, 0, 0]
|
||||
@ -260,6 +247,7 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
except Exception as e:
|
||||
raise DeviceError('Failed to fetch the file %s with error: %s'%
|
||||
f.full_path, as_unicode(e))
|
||||
stream.seek(0)
|
||||
return stream
|
||||
|
||||
@same_thread
|
||||
|
@ -63,7 +63,7 @@ class USBMS(CLI, Device):
|
||||
dinfo = {}
|
||||
if dinfo.get('device_store_uuid', None) is None:
|
||||
dinfo['device_store_uuid'] = unicode(uuid.uuid4())
|
||||
if dinfo.get('device_name') is None:
|
||||
if dinfo.get('device_name', None) is None:
|
||||
dinfo['device_name'] = self.get_gui_name()
|
||||
if name is not None:
|
||||
dinfo['device_name'] = name
|
||||
|
Loading…
x
Reference in New Issue
Block a user