mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GwR early apple driver
This commit is contained in:
parent
ddda93ea7a
commit
007cf9d6c1
@ -430,7 +430,7 @@ from calibre.ebooks.txt.output import TXTOutput
|
||||
|
||||
from calibre.customize.profiles import input_profiles, output_profiles
|
||||
|
||||
|
||||
from calibre.devices.apple.driver import ITUNES
|
||||
from calibre.devices.hanlin.driver import HANLINV3, HANLINV5, BOOX
|
||||
from calibre.devices.blackberry.driver import BLACKBERRY
|
||||
from calibre.devices.cybook.driver import CYBOOK
|
||||
@ -495,6 +495,7 @@ plugins += [
|
||||
]
|
||||
# Order here matters. The first matched device is the one used.
|
||||
plugins += [
|
||||
ITUNES,
|
||||
HANLINV3,
|
||||
HANLINV5,
|
||||
BLACKBERRY,
|
||||
|
@ -5,22 +5,83 @@
|
||||
|
||||
22 May 2010
|
||||
'''
|
||||
import datetime
|
||||
|
||||
from calibre.constants import isosx, iswindows
|
||||
from calibre.devices.interface import DevicePlugin
|
||||
#from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.utils.config import Config
|
||||
|
||||
class iDevice(DevicePlugin):
|
||||
if isosx:
|
||||
print "running in OSX"
|
||||
import appscript
|
||||
|
||||
if iswindows:
|
||||
print "running in Windows"
|
||||
import win32com.client
|
||||
|
||||
class ITUNES(DevicePlugin):
|
||||
name = 'Apple device interface'
|
||||
gui_name = 'Apple device'
|
||||
icon = I('devices/iPad.png')
|
||||
description = _('Communicate with iBooks through iTunes.')
|
||||
supported_platforms = ['windows','osx']
|
||||
author = 'GRiker'
|
||||
|
||||
FORMATS = ['epub']
|
||||
|
||||
VENDOR_ID = [0x0830]
|
||||
PRODUCT_ID = [0x8004, 0x8002, 0x0101]
|
||||
BCD = [0x0316]
|
||||
VENDOR_ID = [0x05ac]
|
||||
# 0x129a:iPad 0x1292:iPhone 3G
|
||||
PRODUCT_ID = [0x129a,0x1292]
|
||||
BCD = [0x01]
|
||||
|
||||
def is_usb_connected(self, device_on_system):
|
||||
app = None
|
||||
is_connected = False
|
||||
|
||||
|
||||
# Public methods
|
||||
|
||||
def add_books_to_metadata(cls, locations, metadata, booklists):
|
||||
'''
|
||||
Add locations to the booklists. This function must not communicate with
|
||||
the device.
|
||||
@param locations: Result of a call to L{upload_books}
|
||||
@param metadata: List of MetaInformation objects, same as for
|
||||
:method:`upload_books`.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def books(self, oncard=None, end_session=True):
|
||||
"""
|
||||
Return a list of ebooks on the device.
|
||||
@param oncard: If 'carda' or 'cardb' return a list of ebooks on the
|
||||
specific storage card, otherwise return list of ebooks
|
||||
in main memory of device. If a card is specified and no
|
||||
books are on the card return empty list.
|
||||
@return: A BookList.
|
||||
"""
|
||||
print "ITUNES:books(oncard=%s)" % oncard
|
||||
if not oncard:
|
||||
myBooks = BookList()
|
||||
book = Book()
|
||||
|
||||
myBooks.add_book(book, False)
|
||||
print "len(myBooks): %d" % len(myBooks)
|
||||
return myBooks
|
||||
else:
|
||||
return []
|
||||
|
||||
def can_handle(self, device_info, debug=False):
|
||||
'''
|
||||
Unix version of :method:`can_handle_windows`
|
||||
|
||||
:param device_info: Is a tupe of (vid, pid, bcd, manufacturer, product,
|
||||
serial number)
|
||||
'''
|
||||
print "ITUNES:can_handle()"
|
||||
return True
|
||||
|
||||
def can_handle_windows(self, device_id, debug=False):
|
||||
@ -35,17 +96,68 @@ class iDevice(DevicePlugin):
|
||||
:param device_info: On windows a device ID string. On Unix a tuple of
|
||||
``(vendor_id, product_id, bcd)``.
|
||||
'''
|
||||
print "ITUNES:can_handle_windows()"
|
||||
return True
|
||||
|
||||
def can_handle(self, device_info, debug=False):
|
||||
def card_prefix(self, end_session=True):
|
||||
'''
|
||||
Unix version of :method:`can_handle_windows`
|
||||
|
||||
:param device_info: Is a tupe of (vid, pid, bcd, manufacturer, product,
|
||||
serial number)
|
||||
Return a 2 element list of the prefix to paths on the cards.
|
||||
If no card is present None is set for the card's prefix.
|
||||
E.G.
|
||||
('/place', '/place2')
|
||||
(None, 'place2')
|
||||
('place', None)
|
||||
(None, None)
|
||||
'''
|
||||
print "ITUNES:card_prefix()"
|
||||
return (None,None)
|
||||
|
||||
return True
|
||||
def config_widget(cls):
|
||||
'''
|
||||
Should return a QWidget. The QWidget contains the settings for the device interface
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete_books(self, paths, end_session=True):
|
||||
'''
|
||||
Delete books at paths on device.
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def eject(self):
|
||||
'''
|
||||
Un-mount / eject the device from the OS. This does not check if there
|
||||
are pending GUI jobs that need to communicate with the device.
|
||||
'''
|
||||
print "ITUNES:eject()"
|
||||
|
||||
def free_space(self, end_session=True):
|
||||
"""
|
||||
Get free space available on the mountpoints:
|
||||
1. Main memory
|
||||
2. Card A
|
||||
3. Card B
|
||||
|
||||
@return: A 3 element list with free space in bytes of (1, 2, 3). If a
|
||||
particular device doesn't have any of these locations it should return -1.
|
||||
"""
|
||||
print "ITUNES:free_space()"
|
||||
return (0,-1,-1)
|
||||
|
||||
def get_device_information(self, end_session=True):
|
||||
"""
|
||||
Ask device for device information. See L{DeviceInfoQuery}.
|
||||
@return: (device name, device version, software version on device, mime type)
|
||||
"""
|
||||
print "ITUNES:get_device_information()"
|
||||
return ('iPad','hw v1.0','sw v1.0', 'mime type')
|
||||
|
||||
def get_file(self, path, outfile, end_session=True):
|
||||
'''
|
||||
Read the file at C{path} on the device and write it to outfile.
|
||||
@param outfile: file object like C{sys.stdout} or the result of an C{open} call
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def open(self):
|
||||
'''
|
||||
@ -58,14 +170,16 @@ class iDevice(DevicePlugin):
|
||||
this function that should serve as a good example for USB Mass storage
|
||||
devices.
|
||||
'''
|
||||
print "iDevice(): I am here!"
|
||||
|
||||
def eject(self):
|
||||
'''
|
||||
Un-mount / eject the device from the OS. This does not check if there
|
||||
are pending GUI jobs that need to communicate with the device.
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
print "ITUNES.open()"
|
||||
if isosx:
|
||||
# Launch iTunes if not already running
|
||||
running_apps = appscript.app('System Events')
|
||||
if not 'iTunes' in running_apps.processes.name():
|
||||
print " launching iTunes"
|
||||
app = appscript.app('iTunes', hide=True)
|
||||
app.run()
|
||||
self.app = app
|
||||
# May need to set focus back to calibre here?
|
||||
|
||||
def post_yank_cleanup(self):
|
||||
'''
|
||||
@ -73,6 +187,37 @@ class iDevice(DevicePlugin):
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def remove_books_from_metadata(cls, paths, booklists):
|
||||
'''
|
||||
Remove books from the metadata list. This function must not communicate
|
||||
with the device.
|
||||
@param paths: paths to books on the device.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||
detected_device=None) :
|
||||
"""
|
||||
:key: The key to unlock the device
|
||||
:log_packets: If true the packet stream to/from the device is logged
|
||||
:report_progress: Function that is called with a % progress
|
||||
(number between 0 and 100) for various tasks
|
||||
If it is called with -1 that means that the
|
||||
task does not have any progress information
|
||||
:detected_device: Device information from the device scanner
|
||||
"""
|
||||
print "ITUNE.reset()"
|
||||
|
||||
def save_settings(cls, settings_widget):
|
||||
'''
|
||||
Should save settings to disk. Takes the widget created in config_widget
|
||||
and saves all settings to disk.
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_progress_reporter(self, report_progress):
|
||||
'''
|
||||
@param report_progress: Function that is called with a % progress
|
||||
@ -80,26 +225,28 @@ class iDevice(DevicePlugin):
|
||||
If it is called with -1 that means that the
|
||||
task does not have any progress information
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
print "ITUNES:set_progress_reporter()"
|
||||
|
||||
def get_device_information(self, end_session=True):
|
||||
"""
|
||||
Ask device for device information. See L{DeviceInfoQuery}.
|
||||
@return: (device name, device version, software version on device, mime type)
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
def settings(cls):
|
||||
'''
|
||||
Should return an opts object. The opts object should have one attribute
|
||||
`format_map` which is an ordered list of formats for the device.
|
||||
'''
|
||||
print "ITUNES.settings()"
|
||||
klass = cls if isinstance(cls, type) else cls.__class__
|
||||
c = Config('device_drivers_%s' % klass.__name__, _('settings for device drivers'))
|
||||
c.add_opt('format_map', default=cls.FORMATS,
|
||||
help=_('Ordered list of formats the device will accept'))
|
||||
return c.parse()
|
||||
|
||||
def card_prefix(self, end_session=True):
|
||||
def sync_booklists(self, booklists, end_session=True):
|
||||
'''
|
||||
Return a 2 element list of the prefix to paths on the cards.
|
||||
If no card is present None is set for the card's prefix.
|
||||
E.G.
|
||||
('/place', '/place2')
|
||||
(None, 'place2')
|
||||
('place', None)
|
||||
(None, None)
|
||||
Update metadata on device.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
print "ITUNES:sync_booklists():"
|
||||
|
||||
def total_space(self, end_session=True):
|
||||
"""
|
||||
@ -111,30 +258,7 @@ class iDevice(DevicePlugin):
|
||||
@return: A 3 element list with total space in bytes of (1, 2, 3). If a
|
||||
particular device doesn't have any of these locations it should return 0.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def free_space(self, end_session=True):
|
||||
"""
|
||||
Get free space available on the mountpoints:
|
||||
1. Main memory
|
||||
2. Card A
|
||||
3. Card B
|
||||
|
||||
@return: A 3 element list with free space in bytes of (1, 2, 3). If a
|
||||
particular device doesn't have any of these locations it should return -1.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def books(self, oncard=None, end_session=True):
|
||||
"""
|
||||
Return a list of ebooks on the device.
|
||||
@param oncard: If 'carda' or 'cardb' return a list of ebooks on the
|
||||
specific storage card, otherwise return list of ebooks
|
||||
in main memory of device. If a card is specified and no
|
||||
books are on the card return empty list.
|
||||
@return: A BookList.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
print "ITUNES:total_space()"
|
||||
|
||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||
metadata=None):
|
||||
@ -158,79 +282,16 @@ class iDevice(DevicePlugin):
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def add_books_to_metadata(cls, locations, metadata, booklists):
|
||||
'''
|
||||
Add locations to the booklists. This function must not communicate with
|
||||
the device.
|
||||
@param locations: Result of a call to L{upload_books}
|
||||
@param metadata: List of MetaInformation objects, same as for
|
||||
:method:`upload_books`.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError
|
||||
# Private methods
|
||||
|
||||
def delete_books(self, paths, end_session=True):
|
||||
def _get_source(self):
|
||||
'''
|
||||
Delete books at paths on device.
|
||||
Get iTunes sources (Library, iPod, Radio ...)
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def remove_books_from_metadata(cls, paths, booklists):
|
||||
'''
|
||||
Remove books from the metadata list. This function must not communicate
|
||||
with the device.
|
||||
@param paths: paths to books on the device.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def sync_booklists(self, booklists, end_session=True):
|
||||
'''
|
||||
Update metadata on device.
|
||||
@param booklists: A tuple containing the result of calls to
|
||||
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||
L{books}(oncard='cardb')).
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_file(self, path, outfile, end_session=True):
|
||||
'''
|
||||
Read the file at C{path} on the device and write it to outfile.
|
||||
@param outfile: file object like C{sys.stdout} or the result of an C{open} call
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def config_widget(cls):
|
||||
'''
|
||||
Should return a QWidget. The QWidget contains the settings for the device interface
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def save_settings(cls, settings_widget):
|
||||
'''
|
||||
Should save settings to disk. Takes the widget created in config_widget
|
||||
and saves all settings to disk.
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def settings(cls):
|
||||
'''
|
||||
Should return an opts object. The opts object should have one attribute
|
||||
`format_map` which is an ordered list of formats for the device.
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
||||
sources = self._app.sources()
|
||||
names = [s.name() for s in sources]
|
||||
kinds = [s.kind() for s in sources]
|
||||
return dict(zip(kinds,names))
|
||||
|
||||
class BookList(list):
|
||||
'''
|
||||
@ -249,19 +310,20 @@ class BookList(list):
|
||||
__getslice__ = None
|
||||
__setslice__ = None
|
||||
|
||||
def __init__(self, oncard, prefix, settings):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def supports_collections(self):
|
||||
''' Return True if the the device supports collections for this book list. '''
|
||||
raise NotImplementedError()
|
||||
return False
|
||||
|
||||
def add_book(self, book, replace_metadata):
|
||||
'''
|
||||
Add the book to the booklist. Intent is to maintain any device-internal
|
||||
metadata. Return True if booklists must be sync'ed
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
print "adding %s" % book
|
||||
self.append(book)
|
||||
|
||||
def remove_book(self, book):
|
||||
'''
|
||||
@ -281,4 +343,22 @@ class BookList(list):
|
||||
|
||||
:param collection_attributes: A list of attributes of the Book object
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
return {}
|
||||
|
||||
class Book(object):
|
||||
'''
|
||||
A simple class describing a book in the iTunes Books Library.
|
||||
These seem to be the minimum Book attributes needed.
|
||||
'''
|
||||
def __init__(self):
|
||||
setattr(self,'title','A Book Title')
|
||||
setattr(self,'authors',['John Doe'])
|
||||
setattr(self,'path','some/path.epub')
|
||||
setattr(self,'size',1234567)
|
||||
setattr(self,'datetime',datetime.datetime.now().timetuple())
|
||||
setattr(self,'thumbnail',None)
|
||||
setattr(self,'db_id',0)
|
||||
setattr(self,'device_collections',[])
|
||||
setattr(self,'tags',['Genre'])
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user