def get_connected_device(): from calibre.customize.ui import device_plugins from calibre.devices.scanner import DeviceScanner dev = None scanner = DeviceScanner() scanner.scan() connected_devices = [] for d in device_plugins(): ok, det = scanner.is_device_connected(d) if ok: dev = d dev.reset(log_packets=False, detected_device=det) connected_devices.append((det, dev)) if dev is None: print('Unable to find a connected ebook reader.', file=sys.stderr) return for det, d in connected_devices: try: d.open(det, None) except: continue else: dev = d break return dev
def develop(): # {{{ from calibre.customize.ui import device_plugins usb_devices = scan_usb_devices() drive_letters = set() pprint(usb_devices) print() devplugins = list(sorted(device_plugins(), cmp=lambda x,y:cmp(x.__class__.__name__, y.__class__.__name__))) for dev in devplugins: dev.startup() for dev in devplugins: if dev.MANAGES_DEVICE_PRESENCE: continue connected, usbdev = dev.is_usb_connected(usb_devices, debug=True) if connected: print('\n') print('Potentially connected device: %s at %s' % (dev.get_gui_name(), usbdev)) print() print('Drives for this device:') data = get_drive_letters_for_device(usbdev, debug=True) pprint(data) drive_letters |= set(data['drive_letters']) print() print('Is device connected:', is_usb_device_connected(*usbdev[:2])) print() print('Device USB data:', get_usb_info(usbdev, debug=True))
def develop(): # {{{ from calibre.customize.ui import device_plugins usb_devices = scan_usb_devices() drive_letters = set() pprint(usb_devices) print() devplugins = list( sorted(device_plugins(), key=lambda x: x.__class__.__name__)) for dev in devplugins: dev.startup() for dev in devplugins: if dev.MANAGES_DEVICE_PRESENCE: continue connected, usbdev = dev.is_usb_connected(usb_devices, debug=True) if connected: print('\n') print('Potentially connected device: %s at %s' % (dev.get_gui_name(), usbdev)) print() print('Drives for this device:') data = get_drive_letters_for_device(usbdev, debug=True) pprint(data) drive_letters |= set(data['drive_letters']) print() print('Is device connected:', is_usb_device_connected(*usbdev[:2])) print() print('Device USB data:', get_usb_info(usbdev, debug=True))
def _find_device_books(self, book_lookup, log): '''Look for the Kindle and return the list of books on it''' dev = None scanner = DeviceScanner() scanner.scan() connected_devices = [] for device in device_plugins(): dev_connected = scanner.is_device_connected(device) if isinstance(dev_connected, tuple): device_ok, det = dev_connected if device_ok: dev = device connected_devices.append((det, dev)) if dev is None: return None for det, device in connected_devices: try: device.open(det, None) except (NotImplementedError, TypeError): continue else: dev = device break self._num_of_formats_found_on_device = 0 try: books = defaultdict(dict) for book in dev.books(): uuid = getattr(book, 'uuid', None) if uuid in book_lookup: book_id = book_lookup[uuid].book_id fmt = book.path.split('.')[-1].lower() if fmt not in self._settings['formats']: continue books[book_id][fmt] = { 'device_book': book.path, 'device_sdr': '.'.join(book.path.split('.')[:-1]) + '.sdr' } self._num_of_formats_found_on_device += 1 return books except (TypeError, AttributeError): self._num_of_formats_found_on_device = -1 log(('{0} Device found but cannot be accessed. ' 'It may have been ejected but not unplugged.').format( datetime.now().strftime('%m-%d-%Y %H:%M:%S'))) return None
def _find_device_books(self, book_lookup, log): '''Look for the Kindle and return the list of books on it''' dev = None scanner = DeviceScanner() scanner.scan() connected_devices = [] for device in device_plugins(): dev_connected = scanner.is_device_connected(device) if isinstance(dev_connected, tuple): device_ok, det = dev_connected if device_ok: dev = device connected_devices.append((det, dev)) if dev is None: return None for det, device in connected_devices: try: device.open(det, None) except (NotImplementedError, TypeError): continue else: dev = device break self._num_of_formats_found_on_device = 0 try: books = defaultdict(dict) for book in dev.books(): uuid = getattr(book, 'uuid', None) if book_lookup.has_key(uuid): book_id = book_lookup[uuid].book_id fmt = book.path.split('.')[-1].lower() if fmt not in self._settings['formats']: continue books[book_id][fmt] = {'device_book': book.path, 'device_sdr': '.'.join(book.path.split('.')[:-1]) + '.sdr'} self._num_of_formats_found_on_device += 1 return books except (TypeError, AttributeError): self._num_of_formats_found_on_device = -1 log(('{0} Device found but cannot be accessed. ' 'It may have been ejected but not unplugged.').format(datetime.now().strftime('%m-%d-%Y %H:%M:%S'))) return None
def initialize(self): ConfigWidgetBase.initialize(self) self.current_plugboards = copy.deepcopy( self.db.prefs.get('plugboards', {})) self.current_device = None self.current_format = None if self.gui.device_manager.connected_device is not None: self.device_label.setText( _('Device currently connected: ') + self.gui.device_manager.connected_device.__class__.__name__) else: self.device_label.setText(_('Device currently connected: None')) self.devices = ['', 'APPLE', 'FOLDER_DEVICE'] self.disabled_devices = [] self.device_to_formats_map = {} for device in device_plugins(): n = device_name_for_plugboards(device) self.device_to_formats_map[n] = set(device.settings().format_map) if getattr(device, 'CAN_DO_DEVICE_DB_PLUGBOARD', False): self.device_to_formats_map[n].add('device_db') if n not in self.devices: self.devices.append(n) for device in disabled_device_plugins(): n = device_name_for_plugboards(device) if n not in self.disabled_devices: self.disabled_devices.append(n) self.devices.sort(key=lambda x: x.lower()) self.devices.insert(1, plugboard_save_to_disk_value) self.devices.insert(1, plugboard_content_server_value) self.device_to_formats_map[plugboard_content_server_value] = \ plugboard_content_server_formats self.devices.insert(1, plugboard_email_value) self.device_to_formats_map[plugboard_email_value] = \ plugboard_email_formats self.devices.insert(1, plugboard_any_device_value) self.new_device.addItems(self.devices) self.formats = [''] self.format_to_writers_map = defaultdict(list) for w in metadata_writers(): for f in w.file_types: if f not in self.formats: self.formats.append(f) self.format_to_writers_map[f].append(w) self.formats.append('device_db') self.formats.sort() self.formats.insert(1, plugboard_any_format_value) self.new_format.addItems(self.formats) self.dest_fields = [ '', 'authors', 'author_sort', 'language', 'publisher', 'series', 'tags', 'title', 'title_sort', 'comments' ] self.source_widgets = [] self.dest_widgets = [] for i in range(0, len(self.dest_fields) - 1): w = TemplateLineEditor(self) self.source_widgets.append(w) self.fields_layout.addWidget(w, 5 + i, 0, 1, 1) w = QComboBox(self) self.dest_widgets.append(w) self.fields_layout.addWidget(w, 5 + i, 1, 1, 1) self.edit_device.currentIndexChanged[native_string_type].connect( self.edit_device_changed) self.edit_format.currentIndexChanged[native_string_type].connect( self.edit_format_changed) self.new_device.currentIndexChanged[native_string_type].connect( self.new_device_changed) self.new_format.currentIndexChanged[native_string_type].connect( self.new_format_changed) self.existing_plugboards.itemClicked.connect(self.existing_pb_clicked) self.ok_button.clicked.connect(self.ok_clicked) self.del_button.clicked.connect(self.del_clicked) self.refilling = False self.refill_all_boxes()
def shutdown_plugins(): for d in device_plugins(): try: d.shutdown() except: pass
def initialize(self): def field_cmp(x, y): if x.startswith('#'): if y.startswith('#'): return cmp(x.lower(), y.lower()) else: return 1 elif y.startswith('#'): return -1 else: return cmp(x.lower(), y.lower()) ConfigWidgetBase.initialize(self) self.current_plugboards = copy.deepcopy(self.db.prefs.get('plugboards',{})) self.current_device = None self.current_format = None if self.gui.device_manager.connected_device is not None: self.device_label.setText(_('Device currently connected: ') + self.gui.device_manager.connected_device.__class__.__name__) else: self.device_label.setText(_('Device currently connected: None')) self.devices = ['', 'APPLE', 'FOLDER_DEVICE'] self.disabled_devices = [] self.device_to_formats_map = {} for device in device_plugins(): n = device_name_for_plugboards(device) self.device_to_formats_map[n] = set(device.settings().format_map) if getattr(device, 'CAN_DO_DEVICE_DB_PLUGBOARD', False): self.device_to_formats_map[n].add('device_db') if n not in self.devices: self.devices.append(n) for device in disabled_device_plugins(): n = device_name_for_plugboards(device) if n not in self.disabled_devices: self.disabled_devices.append(n) self.devices.sort(cmp=lambda x, y: cmp(x.lower(), y.lower())) self.devices.insert(1, plugboard_save_to_disk_value) self.devices.insert(1, plugboard_content_server_value) self.device_to_formats_map[plugboard_content_server_value] = \ plugboard_content_server_formats self.devices.insert(1, plugboard_email_value) self.device_to_formats_map[plugboard_email_value] = \ plugboard_email_formats self.devices.insert(1, plugboard_any_device_value) self.new_device.addItems(self.devices) self.formats = [''] self.format_to_writers_map = defaultdict(list) for w in metadata_writers(): for f in w.file_types: if f not in self.formats: self.formats.append(f) self.format_to_writers_map[f].append(w) self.formats.append('device_db') self.formats.sort() self.formats.insert(1, plugboard_any_format_value) self.new_format.addItems(self.formats) self.dest_fields = ['', 'authors', 'author_sort', 'language', 'publisher', 'tags', 'title', 'title_sort'] self.source_widgets = [] self.dest_widgets = [] for i in range(0, len(self.dest_fields)-1): w = TemplateLineEditor(self) self.source_widgets.append(w) self.fields_layout.addWidget(w, 5+i, 0, 1, 1) w = QComboBox(self) self.dest_widgets.append(w) self.fields_layout.addWidget(w, 5+i, 1, 1, 1) self.edit_device.currentIndexChanged[str].connect(self.edit_device_changed) self.edit_format.currentIndexChanged[str].connect(self.edit_format_changed) self.new_device.currentIndexChanged[str].connect(self.new_device_changed) self.new_format.currentIndexChanged[str].connect(self.new_format_changed) self.existing_plugboards.itemClicked.connect(self.existing_pb_clicked) self.ok_button.clicked.connect(self.ok_clicked) self.del_button.clicked.connect(self.del_clicked) self.refilling = False self.refill_all_boxes()
def commit(cls): super(Android, cls).commit() for plugin in device_plugins(include_disabled=True): if hasattr(plugin, 'configure_for_kindle_app'): plugin.configure_for_kindle_app()
def commit(cls): super(Android, cls).commit() for plugin in device_plugins(include_disabled=True): if plugin.name == 'Android driver': plugin.configure_for_kindle_app()
def debug(ioreg_to_tmp=False, buf=None): import textwrap from calibre.customize.ui import device_plugins from calibre.devices.scanner import DeviceScanner, win_pnp_drives from calibre.constants import iswindows, isosx, __version__ from calibre import prints oldo, olde = sys.stdout, sys.stderr if buf is None: buf = StringIO() sys.stdout = sys.stderr = buf try: out = partial(prints, file=buf) out('Version:', __version__) s = DeviceScanner() s.scan() devices = (s.devices) if not iswindows: devices = [list(x) for x in devices] for d in devices: for i in range(3): d[i] = hex(d[i]) out('USB devices on system:') out(pprint.pformat(devices)) if iswindows: drives = win_pnp_drives(debug=True) out('Drives detected:') for drive in sorted(drives.keys(), key=operator.attrgetter('order')): prints(u'\t(%d)'%drive.order, drive, '~', drives[drive]) ioreg = None if isosx: from calibre.devices.usbms.device import Device mount = repr(Device.osx_run_mount()) drives = pprint.pformat(Device.osx_get_usb_drives()) ioreg = 'Output from mount:\n'+mount+'\n\n' ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n' ioreg += Device.run_ioreg() connected_devices = [] devplugins = list(sorted(device_plugins(), cmp=lambda x,y:cmp(x.__class__.__name__, y.__class__.__name__))) out('Available plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in devplugins]))) out(' ') out('Looking for devices...') for dev in devplugins: connected, det = s.is_device_connected(dev, debug=True) if connected: out('\t\tDetected possible device', dev.__class__.__name__) connected_devices.append((dev, det)) out(' ') errors = {} success = False out('Devices possibly connected:', end=' ') for dev, det in connected_devices: out(dev.name, end=', ') if not connected_devices: out('None', end='') out(' ') for dev, det in connected_devices: out('Trying to open', dev.name, '...', end=' ') try: dev.reset(detected_device=det) dev.open(det, None) out('OK') except: import traceback errors[dev] = traceback.format_exc() out('failed') continue success = True if hasattr(dev, '_main_prefix'): out('Main memory:', repr(dev._main_prefix)) out('Total space:', dev.total_space()) break if not success and errors: out('Opening of the following devices failed') for dev,msg in errors.items(): out(dev) out(msg) out(' ') if ioreg is not None: ioreg = 'IOREG Output\n'+ioreg out(' ') if ioreg_to_tmp: open('/tmp/ioreg.txt', 'wb').write(ioreg) out('Dont forget to send the contents of /tmp/ioreg.txt') out('You can open it with the command: open /tmp/ioreg.txt') else: out(ioreg) if hasattr(buf, 'getvalue'): return buf.getvalue().decode('utf-8') finally: sys.stdout = oldo sys.stderr = olde
def main(): from calibre.utils.terminal import geometry cols = geometry()[0] parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+ "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"+ "For help on a particular command: %prog command", version=__appname__+" version: " + __version__) parser.add_option("--log-packets", help="print out packet stream to stdout. "+\ "The numbers in the left column are byte offsets that allow the packet size to be read off easily.", dest="log_packets", action="store_true", default=False) parser.remove_option("-h") parser.disable_interspersed_args() # Allow unrecognized options options, args = parser.parse_args() if len(args) < 1: parser.print_help() return 1 command = args[0] args = args[1:] dev = None scanner = DeviceScanner() scanner.scan() connected_devices = [] for d in device_plugins(): try: d.startup() except: print ('Startup failed for device plugin: %s'%d) if d.MANAGES_DEVICE_PRESENCE: cd = d.detect_managed_devices(scanner.devices) if cd is not None: connected_devices.append((cd, d)) dev = d break continue ok, det = scanner.is_device_connected(d) if ok: dev = d dev.reset(log_packets=options.log_packets, detected_device=det) connected_devices.append((det, dev)) if dev is None: print >>sys.stderr, 'Unable to find a connected ebook reader.' shutdown_plugins() return 1 for det, d in connected_devices: try: d.open(det, None) except: continue else: dev = d d.specialize_global_preferences(device_prefs) break try: if command == "df": total = dev.total_space(end_session=False) free = dev.free_space() where = ("Memory", "Card A", "Card B") print "Filesystem\tSize \tUsed \tAvail \tUse%" for i in range(3): print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\ str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%") elif command == 'eject': dev.eject() elif command == "books": print "Books in main memory:" for book in dev.books(): print book print "\nBooks on storage carda:" for book in dev.books(oncard='carda'): print book print "\nBooks on storage cardb:" for book in dev.books(oncard='cardb'): print book elif command == "mkdir": parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/") if len(args) != 1: parser.print_help() sys.exit(1) dev.mkdir(args[0]) elif command == "ls": parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/") parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", dest="ll", action="store_true", default=False) parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False) parser.remove_option("-h") parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 print ls(dev, args[0], recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols), elif command == "info": info(dev) elif command == "cp": usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\ "One of source or destination must be a path on the device. \n\nDevice paths have the form\n"+\ "dev:mountpoint/my/path\n"+\ "where mountpoint is one of / or card:/\n\n"+\ "source must point to a file for which you have read permissions\n"+\ "destination must point to a file or directory for which you have write permissions" parser = OptionParser(usage=usage) parser.add_option('-f', '--force', dest='force', action='store_true', default=False, help='Overwrite the destination file if it exists already.') options, args = parser.parse_args(args) if len(args) != 2: parser.print_help() return 1 if args[0].startswith("dev:"): outfile = args[1] path = args[0][7:] if path.endswith("/"): path = path[:-1] if os.path.isdir(outfile): outfile = os.path.join(outfile, path[path.rfind("/")+1:]) try: outfile = open(outfile, "wb") except IOError as e: print >> sys.stderr, e parser.print_help() return 1 dev.get_file(path, outfile) outfile.close() elif args[1].startswith("dev:"): try: infile = open(args[0], "rb") except IOError as e: print >> sys.stderr, e parser.print_help() return 1 try: dev.put_file(infile, args[1][7:]) except PathError as err: if options.force and 'exists' in str(err): dev.del_file(err.path, False) dev.put_file(infile, args[1][7:]) else: raise infile.close() else: parser.print_help() return 1 elif command == "cat": outfile = sys.stdout parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/") options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 if args[0].endswith("/"): path = args[0][:-1] else: path = args[0] outfile = sys.stdout dev.get_file(path, outfile) elif command == "rm": parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+\ "and must begin with / or card:/\n\n"+\ "rm will DELETE the file. Be very CAREFUL") options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 dev.rm(args[0]) elif command == "touch": parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+ "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" ) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 dev.touch(args[0]) elif command == 'test_file': parser = OptionParser(usage=("usage: %prog test_file path\n" 'Open device, copy file specified by path to device and ' 'then eject device.')) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 path = args[0] from calibre.ebooks.metadata.meta import get_metadata mi = get_metadata(open(path, 'rb'), path.rpartition('.')[-1].lower()) print dev.upload_books([args[0]], [os.path.basename(args[0])], end_session=False, metadata=[mi]) dev.eject() else: parser.print_help() if getattr(dev, 'handle', False): dev.close() return 1 except DeviceLocked: print >> sys.stderr, "The device is locked. Use the --unlock option" except (ArgumentError, DeviceError) as e: print >>sys.stderr, e return 1 finally: shutdown_plugins() return 0
def commit(cls): from calibre.customize.ui import device_plugins super(Android, cls).commit() for plugin in device_plugins(include_disabled=True): if hasattr(plugin, 'configure_for_kindle_app'): plugin.configure_for_kindle_app()
def book_to_json(ctx, rd, db, book_id, get_category_urls=True, device_compatible=False, device_for_template=None): mi = db.get_metadata(book_id, get_cover=False) codec = JsonCodec(db.field_metadata) if not device_compatible: try: mi.rating = mi.rating/2. except Exception: mi.rating = 0.0 data = codec.encode_book_metadata(mi) for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime', 'rights', 'book_producer'): data.pop(x, None) get = partial(ctx.url_for, get_content, book_id=book_id, library_id=db.server_library_id) data['cover'] = get(what='cover') data['thumbnail'] = get(what='thumb') if not device_compatible: mi.format_metadata = {k.lower():dict(v) for k, v in mi.format_metadata.iteritems()} for v in mi.format_metadata.itervalues(): mtime = v.get('mtime', None) if mtime is not None: v['mtime'] = isoformat(mtime, as_utc=True) data['format_metadata'] = mi.format_metadata fmts = set(x.lower() for x in mi.format_metadata.iterkeys()) pf = prefs['output_format'].lower() other_fmts = list(fmts) try: fmt = pf if pf in fmts else other_fmts[0] except: fmt = None if fmts and fmt: other_fmts = [x for x in fmts if x != fmt] data['formats'] = sorted(fmts) if fmt: data['main_format'] = {fmt:get(what=fmt)} else: data['main_format'] = None data['other_formats'] = {fmt:get(what=fmt) for fmt in other_fmts} if get_category_urls: category_urls = data['category_urls'] = {} all_cats = ctx.get_categories(rd, db) for key in mi.all_field_keys(): fm = mi.metadata_for_field(key) if (fm and fm['is_category'] and not fm['is_csp'] and key != 'formats' and fm['datatype'] != 'rating'): categories = mi.get(key) or [] if isinstance(categories, basestring): categories = [categories] category_urls[key] = dbtags = {} for category in categories: for tag in all_cats.get(key, ()): if tag.original_name == category: dbtags[category] = ctx.url_for( books_in, encoded_category=encode_name(tag.category if tag.category else key), encoded_item=encode_name(tag.original_name if tag.id is None else unicode(tag.id)), library_id=db.server_library_id ) break else: series = data.get('series', None) or '' if series: tsorder = tweaks['save_template_title_series_sorting'] series = title_sort(series, order=tsorder) data['_series_sort_'] = series if device_for_template: import posixpath from calibre.devices.utils import create_upload_path from calibre.utils.filenames import ascii_filename as sanitize from calibre.customize.ui import device_plugins for device_class in device_plugins(): if device_class.__class__.__name__ == device_for_template: template = device_class.save_template() data['_filename_'] = create_upload_path(mi, book_id, template, sanitize, path_type=posixpath) break return data, mi.last_modified
def debug(ioreg_to_tmp=False, buf=None, plugins=None, disabled_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, disabled_device_plugins from calibre.debug import print_basic_debug_info from calibre.devices.scanner import DeviceScanner from calibre.constants import iswindows, ismacos from calibre import prints from polyglot.io import PolyglotStringIO oldo, olde = sys.stdout, sys.stderr if buf is None: buf = PolyglotStringIO() sys.stdout = sys.stderr = buf out = partial(prints, file=buf) devplugins = device_plugins() if plugins is None else plugins devplugins = list(sorted(devplugins, key=lambda x: x.__class__.__name__)) if plugins is None: for d in devplugins: try: d.startup() except: out('Startup failed for device plugin: %s' % d) if disabled_plugins is None: disabled_plugins = list(disabled_device_plugins()) try: print_basic_debug_info(out=buf) s = DeviceScanner() s.scan() devices = (s.devices) if not iswindows: devices = [list(x) for x in devices] for d in devices: for i in range(3): d[i] = hex(d[i]) out('USB devices on system:') out(pprint.pformat(devices)) ioreg = None if ismacos: from calibre.devices.usbms.device import Device mount = '\n'.join( repr(x) for x in Device.osx_run_mount().splitlines()) drives = pprint.pformat(Device.osx_get_usb_drives()) ioreg = 'Output from mount:\n' + mount + '\n\n' ioreg += 'Output from osx_get_usb_drives:\n' + drives + '\n\n' ioreg += Device.run_ioreg().decode('utf-8') connected_devices = [] if disabled_plugins: out( '\nDisabled plugins:', textwrap.fill(' '.join( [x.__class__.__name__ for x in disabled_plugins]))) out(' ') else: out('\nNo disabled plugins') found_dev = False for dev in devplugins: if not dev.MANAGES_DEVICE_PRESENCE: continue out('Looking for devices of type:', dev.__class__.__name__) if dev.debug_managed_device_detection(s.devices, buf): found_dev = True break out(' ') if not found_dev: out('Looking for devices...') for dev in devplugins: if dev.MANAGES_DEVICE_PRESENCE: continue connected, det = s.is_device_connected(dev, debug=True) if connected: out('\t\tDetected possible device', dev.__class__.__name__) connected_devices.append((dev, det)) out(' ') errors = {} success = False out('Devices possibly connected:', end=' ') for dev, det in connected_devices: out(dev.name, end=', ') if not connected_devices: out('None', end='') out(' ') for dev, det in connected_devices: out('Trying to open', dev.name, '...', end=' ') dev.do_device_debug = True try: dev.reset(detected_device=det) dev.open(det, None) out('OK') except: import traceback errors[dev] = traceback.format_exc() out('failed') continue dev.do_device_debug = False success = True if hasattr(dev, '_main_prefix'): out('Main memory:', repr(dev._main_prefix)) out('Total space:', dev.total_space()) break if not success and errors: out('Opening of the following devices failed') for dev, msg in errors.items(): out(dev) out(msg) out(' ') if ioreg is not None: ioreg = 'IOREG Output\n' + ioreg out(' ') if ioreg_to_tmp: lopen('/tmp/ioreg.txt', 'w').write(ioreg) out('Dont forget to send the contents of /tmp/ioreg.txt') out('You can open it with the command: open /tmp/ioreg.txt' ) else: out(ioreg) if hasattr(buf, 'getvalue'): return buf.getvalue() finally: sys.stdout = oldo sys.stderr = olde if plugins is None: for d in devplugins: try: d.shutdown() except: pass
def main(): from calibre.utils.terminal import geometry cols = geometry()[0] parser = OptionParser( usage="usage: %prog [options] command args\n\ncommand " + "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n" + "For help on a particular command: %prog command", version=__appname__ + " version: " + __version__) parser.add_option( "--log-packets", help="print out packet stream to stdout. " + "The numbers in the left column are byte offsets that allow the packet size to be read off easily.", dest="log_packets", action="store_true", default=False) parser.remove_option("-h") parser.disable_interspersed_args() # Allow unrecognized options options, args = parser.parse_args() if len(args) < 1: parser.print_help() return 1 command = args[0] args = args[1:] dev = None scanner = DeviceScanner() scanner.scan() connected_devices = [] for d in device_plugins(): try: d.startup() except: print('Startup failed for device plugin: %s' % d) if d.MANAGES_DEVICE_PRESENCE: cd = d.detect_managed_devices(scanner.devices) if cd is not None: connected_devices.append((cd, d)) dev = d break continue ok, det = scanner.is_device_connected(d) if ok: dev = d dev.reset(log_packets=options.log_packets, detected_device=det) connected_devices.append((det, dev)) if dev is None: print('Unable to find a connected ebook reader.', file=sys.stderr) shutdown_plugins() return 1 for det, d in connected_devices: try: d.open(det, None) except: continue else: dev = d d.specialize_global_preferences(device_prefs) break try: if command == "df": total = dev.total_space(end_session=False) free = dev.free_space() where = ("Memory", "Card A", "Card B") print("Filesystem\tSize \tUsed \tAvail \tUse%") for i in range(3): print("%-10s\t%s\t%s\t%s\t%s" % (where[i], human_readable( total[i]), human_readable(total[i] - free[i]), human_readable(free[i]), unicode_type(0 if total[i] == 0 else int(100 * (total[i] - free[i]) / (total[i] * 1.))) + "%")) elif command == 'eject': dev.eject() elif command == "books": print("Books in main memory:") for book in dev.books(): print(book) print("\nBooks on storage carda:") for book in dev.books(oncard='carda'): print(book) print("\nBooks on storage cardb:") for book in dev.books(oncard='cardb'): print(book) elif command == "mkdir": parser = OptionParser( usage= "usage: %prog mkdir [options] path\nCreate a folder on the device\n\npath must begin with / or card:/" ) if len(args) != 1: parser.print_help() sys.exit(1) dev.mkdir(args[0]) elif command == "ls": parser = OptionParser( usage= "usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/" ) parser.add_option( "-l", help= "In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", # noqa dest="ll", action="store_true", default=False) parser.add_option( "-R", help= "Recursively list subfolders encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False) parser.remove_option("-h") parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 print(ls(dev, args[0], recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols), end=' ') elif command == "info": info(dev) elif command == "cp": usage="usage: %prog cp [options] source destination\nCopy files to/from the device\n\n"+\ "One of source or destination must be a path on the device. \n\nDevice paths have the form\n"+\ "dev:mountpoint/my/path\n"+\ "where mountpoint is one of / or carda: or cardb:/\n\n"+\ "source must point to a file for which you have read permissions\n"+\ "destination must point to a file or folder for which you have write permissions" parser = OptionParser(usage=usage) parser.add_option( '-f', '--force', dest='force', action='store_true', default=False, help='Overwrite the destination file if it exists already.') options, args = parser.parse_args(args) if len(args) != 2: parser.print_help() return 1 if args[0].startswith("dev:"): outfile = args[1] path = args[0][4:] if path.endswith("/"): path = path[:-1] if os.path.isdir(outfile): outfile = os.path.join(outfile, path[path.rfind("/") + 1:]) try: outfile = lopen(outfile, "wb") except IOError as e: print(e, file=sys.stderr) parser.print_help() return 1 dev.get_file(path, outfile) fsync(outfile) outfile.close() elif args[1].startswith("dev:"): try: infile = lopen(args[0], "rb") except IOError as e: print(e, file=sys.stderr) parser.print_help() return 1 dev.put_file(infile, args[1][4:], replace_file=options.force) infile.close() else: parser.print_help() return 1 elif command == "cat": outfile = sys.stdout parser = OptionParser( usage= "usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/" ) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 if args[0].endswith("/"): path = args[0][:-1] else: path = args[0] outfile = sys.stdout dev.get_file(path, outfile) elif command == "rm": parser = OptionParser( usage= "usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty folder on the device " + "and must begin with / or card:/\n\n" + "rm will DELETE the file. Be very CAREFUL") options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 dev.rm(args[0]) elif command == "touch": parser = OptionParser( usage= "usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n" + # noqa "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" ) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 dev.touch(args[0]) elif command == 'test_file': parser = OptionParser(usage=( "usage: %prog test_file path\n" 'Open device, copy file specified by path to device and ' 'then eject device.')) options, args = parser.parse_args(args) if len(args) != 1: parser.print_help() return 1 path = args[0] from calibre.ebooks.metadata.meta import get_metadata mi = get_metadata(lopen(path, 'rb'), path.rpartition('.')[-1].lower()) print( dev.upload_books([args[0]], [os.path.basename(args[0])], end_session=False, metadata=[mi])) dev.eject() else: parser.print_help() if getattr(dev, 'handle', False): dev.close() return 1 except DeviceLocked: print("The device is locked. Use the --unlock option", file=sys.stderr) except (ArgumentError, DeviceError) as e: print(e, file=sys.stderr) return 1 finally: shutdown_plugins() return 0
def debug(ioreg_to_tmp=False, buf=None): import textwrap from calibre.customize.ui import device_plugins from calibre.devices.scanner import DeviceScanner, win_pnp_drives from calibre.constants import iswindows, isosx, __version__ from calibre import prints oldo, olde = sys.stdout, sys.stderr if buf is None: buf = StringIO() sys.stdout = sys.stderr = buf try: out = partial(prints, file=buf) out('Version:', __version__) s = DeviceScanner() s.scan() devices = (s.devices) if not iswindows: devices = [list(x) for x in devices] for d in devices: for i in range(3): d[i] = hex(d[i]) out('USB devices on system:') out(pprint.pformat(devices)) if iswindows: drives = win_pnp_drives(debug=True) out('Drives detected:') for drive in sorted(drives.keys(), key=operator.attrgetter('order')): prints(u'\t(%d)' % drive.order, drive, '~', drives[drive]) ioreg = None if isosx: from calibre.devices.usbms.device import Device mount = repr(Device.osx_run_mount()) drives = pprint.pformat(Device.osx_get_usb_drives()) ioreg = 'Output from mount:\n' + mount + '\n\n' ioreg += 'Output from osx_get_usb_drives:\n' + drives + '\n\n' ioreg += Device.run_ioreg() connected_devices = [] devplugins = list( sorted(device_plugins(), cmp=lambda x, y: cmp(x.__class__.__name__, y.__class__. __name__))) out( 'Available plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in devplugins]))) out(' ') out('Looking for devices...') for dev in devplugins: connected, det = s.is_device_connected(dev, debug=True) if connected: out('\t\tDetected possible device', dev.__class__.__name__) connected_devices.append((dev, det)) out(' ') errors = {} success = False out('Devices possibly connected:', end=' ') for dev, det in connected_devices: out(dev.name, end=', ') if not connected_devices: out('None', end='') out(' ') for dev, det in connected_devices: out('Trying to open', dev.name, '...', end=' ') try: dev.reset(detected_device=det) dev.open(det, None) out('OK') except: import traceback errors[dev] = traceback.format_exc() out('failed') continue success = True if hasattr(dev, '_main_prefix'): out('Main memory:', repr(dev._main_prefix)) out('Total space:', dev.total_space()) break if not success and errors: out('Opening of the following devices failed') for dev, msg in errors.items(): out(dev) out(msg) out(' ') if ioreg is not None: ioreg = 'IOREG Output\n' + ioreg out(' ') if ioreg_to_tmp: open('/tmp/ioreg.txt', 'wb').write(ioreg) out('Dont forget to send the contents of /tmp/ioreg.txt') out('You can open it with the command: open /tmp/ioreg.txt') else: out(ioreg) if hasattr(buf, 'getvalue'): return buf.getvalue().decode('utf-8') finally: sys.stdout = oldo sys.stderr = olde
def debug(ioreg_to_tmp=False, buf=None, plugins=None, disabled_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, disabled_device_plugins from calibre.debug import print_basic_debug_info from calibre.devices.scanner import DeviceScanner from calibre.constants import iswindows, isosx from calibre import prints from polyglot.io import PolyglotBytesIO oldo, olde = sys.stdout, sys.stderr if buf is None: buf = PolyglotBytesIO() sys.stdout = sys.stderr = buf out = partial(prints, file=buf) devplugins = device_plugins() if plugins is None else plugins devplugins = list(sorted(devplugins, key=lambda x: x.__class__.__name__)) if plugins is None: for d in devplugins: try: d.startup() except: out('Startup failed for device plugin: %s'%d) if disabled_plugins is None: disabled_plugins = list(disabled_device_plugins()) try: print_basic_debug_info(out=buf) s = DeviceScanner() s.scan() devices = (s.devices) if not iswindows: devices = [list(x) for x in devices] for d in devices: for i in range(3): d[i] = hex(d[i]) out('USB devices on system:') out(pprint.pformat(devices)) ioreg = None if isosx: from calibre.devices.usbms.device import Device mount = '\n'.join(repr(x) for x in Device.osx_run_mount().splitlines()) drives = pprint.pformat(Device.osx_get_usb_drives()) ioreg = 'Output from mount:\n'+mount+'\n\n' ioreg += 'Output from osx_get_usb_drives:\n'+drives+'\n\n' ioreg += Device.run_ioreg() connected_devices = [] if disabled_plugins: out('\nDisabled plugins:', textwrap.fill(' '.join([x.__class__.__name__ for x in disabled_plugins]))) out(' ') else: out('\nNo disabled plugins') found_dev = False for dev in devplugins: if not dev.MANAGES_DEVICE_PRESENCE: continue out('Looking for devices of type:', dev.__class__.__name__) if dev.debug_managed_device_detection(s.devices, buf): found_dev = True break out(' ') if not found_dev: out('Looking for devices...') for dev in devplugins: if dev.MANAGES_DEVICE_PRESENCE: continue connected, det = s.is_device_connected(dev, debug=True) if connected: out('\t\tDetected possible device', dev.__class__.__name__) connected_devices.append((dev, det)) out(' ') errors = {} success = False out('Devices possibly connected:', end=' ') for dev, det in connected_devices: out(dev.name, end=', ') if not connected_devices: out('None', end='') out(' ') for dev, det in connected_devices: out('Trying to open', dev.name, '...', end=' ') dev.do_device_debug = True try: dev.reset(detected_device=det) dev.open(det, None) out('OK') except: import traceback errors[dev] = traceback.format_exc() out('failed') continue dev.do_device_debug = False success = True if hasattr(dev, '_main_prefix'): out('Main memory:', repr(dev._main_prefix)) out('Total space:', dev.total_space()) break if not success and errors: out('Opening of the following devices failed') for dev,msg in errors.items(): out(dev) out(msg) out(' ') if ioreg is not None: ioreg = 'IOREG Output\n'+ioreg out(' ') if ioreg_to_tmp: lopen('/tmp/ioreg.txt', 'wb').write(ioreg) out('Dont forget to send the contents of /tmp/ioreg.txt') out('You can open it with the command: open /tmp/ioreg.txt') else: out(ioreg) if hasattr(buf, 'getvalue'): return buf.getvalue().decode('utf-8', 'replace') finally: sys.stdout = oldo sys.stderr = olde if plugins is None: for d in devplugins: try: d.shutdown() except: pass
def ajax_book_to_json(self, book_id, get_category_urls=True, device_compatible=False, device_for_template=None): mi = self.db.get_metadata(book_id, index_is_id=True) if not device_compatible: try: mi.rating = mi.rating/2. except: mi.rating = 0.0 data = self.ajax_json_codec.encode_book_metadata(mi) for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime', 'rights', 'book_producer'): data.pop(x, None) data['cover'] = absurl(self.opts.url_prefix, u'/get/cover/%d'%book_id) data['thumbnail'] = absurl(self.opts.url_prefix, u'/get/thumb/%d'%book_id) if not device_compatible: mi.format_metadata = {k.lower():dict(v) for k, v in mi.format_metadata.iteritems()} for v in mi.format_metadata.itervalues(): mtime = v.get('mtime', None) if mtime is not None: v['mtime'] = isoformat(mtime, as_utc=True) data['format_metadata'] = mi.format_metadata fmts = set(x.lower() for x in mi.format_metadata.iterkeys()) pf = prefs['output_format'].lower() other_fmts = list(fmts) try: fmt = pf if pf in fmts else other_fmts[0] except: fmt = None if fmts and fmt: other_fmts = [x for x in fmts if x != fmt] data['formats'] = sorted(fmts) if fmt: data['main_format'] = {fmt: absurl(self.opts.url_prefix, u'/get/%s/%d'%(fmt, book_id))} else: data['main_format'] = None data['other_formats'] = {fmt: absurl(self.opts.url_prefix, u'/get/%s/%d'%(fmt, book_id)) for fmt in other_fmts} if get_category_urls: category_urls = data['category_urls'] = {} ccache = self.categories_cache() for key in mi.all_field_keys(): fm = mi.metadata_for_field(key) if (fm and fm['is_category'] and not fm['is_csp'] and key != 'formats' and fm['datatype'] not in ['rating']): categories = mi.get(key) if isinstance(categories, basestring): categories = [categories] if categories is None: categories = [] dbtags = {} for category in categories: for tag in ccache.get(key, []): if tag.original_name == category: dbtags[category] = books_in_url(self.opts.url_prefix, tag.category if tag.category else key, tag.original_name if tag.id is None else unicode(tag.id)) break category_urls[key] = dbtags else: series = data.get('series', None) if series: tsorder = tweaks['save_template_title_series_sorting'] series = title_sort(series, order=tsorder) else: series = '' data['_series_sort_'] = series if device_for_template: import posixpath from calibre.devices.utils import create_upload_path from calibre.utils.filenames import ascii_filename as sanitize from calibre.customize.ui import device_plugins for device_class in device_plugins(): if device_class.__class__.__name__ == device_for_template: template = device_class.save_template() data['_filename_'] = create_upload_path(mi, book_id, template, sanitize, path_type=posixpath) break return data, mi.last_modified
def ajax_book_to_json(self, book_id, get_category_urls=True, device_compatible=False, device_for_template=None): mi = self.db.get_metadata(book_id, index_is_id=True) if not device_compatible: try: mi.rating = mi.rating / 2. except: mi.rating = 0.0 data = self.ajax_json_codec.encode_book_metadata(mi) for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime', 'rights', 'book_producer'): data.pop(x, None) data['cover'] = absurl(self.opts.url_prefix, u'/get/cover/%d' % book_id) data['thumbnail'] = absurl(self.opts.url_prefix, u'/get/thumb/%d' % book_id) if not device_compatible: mi.format_metadata = { k.lower(): dict(v) for k, v in mi.format_metadata.iteritems() } for v in mi.format_metadata.itervalues(): mtime = v.get('mtime', None) if mtime is not None: v['mtime'] = isoformat(mtime, as_utc=True) data['format_metadata'] = mi.format_metadata fmts = set(x.lower() for x in mi.format_metadata.iterkeys()) pf = prefs['output_format'].lower() other_fmts = list(fmts) try: fmt = pf if pf in fmts else other_fmts[0] except: fmt = None if fmts and fmt: other_fmts = [x for x in fmts if x != fmt] data['formats'] = sorted(fmts) if fmt: data['main_format'] = { fmt: absurl(self.opts.url_prefix, u'/get/%s/%d' % (fmt, book_id)) } else: data['main_format'] = None data['other_formats'] = { fmt: absurl(self.opts.url_prefix, u'/get/%s/%d' % (fmt, book_id)) for fmt in other_fmts } if get_category_urls: category_urls = data['category_urls'] = {} ccache = self.categories_cache() for key in mi.all_field_keys(): fm = mi.metadata_for_field(key) if (fm and fm['is_category'] and not fm['is_csp'] and key != 'formats' and fm['datatype'] not in ['rating']): categories = mi.get(key) if isinstance(categories, basestring): categories = [categories] if categories is None: categories = [] dbtags = {} for category in categories: for tag in ccache.get(key, []): if tag.original_name == category: dbtags[category] = books_in_url( self.opts.url_prefix, tag.category if tag.category else key, tag.original_name if tag.id is None else unicode(tag.id)) break category_urls[key] = dbtags else: series = data.get('series', None) if series: tsorder = tweaks['save_template_title_series_sorting'] series = title_sort(series, order=tsorder) else: series = '' data['_series_sort_'] = series if device_for_template: import posixpath from calibre.devices.utils import create_upload_path from calibre.utils.filenames import ascii_filename as sanitize from calibre.customize.ui import device_plugins for device_class in device_plugins(): if device_class.__class__.__name__ == device_for_template: template = device_class.save_template() data['_filename_'] = create_upload_path( mi, book_id, template, sanitize, path_type=posixpath) break return data, mi.last_modified