Refactor and clean up of device drivers.

This commit is contained in:
John Schember 2009-08-02 13:37:19 -04:00
parent 024d47046e
commit 1e19801b37
16 changed files with 181 additions and 309 deletions

View File

@ -1,21 +1,18 @@
#!/usr/bin/env python # -*- coding: utf-8 -*-
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class ANDROID(USBMS): class ANDROID(USBMS):
name = 'Android driver' name = 'Android driver'
description = _('Communicate with Android phones.') description = _('Communicate with Android phones.')
author = 'Kovid Goyal' author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
FORMATS = ['epub'] FORMATS = ['epub']
@ -34,5 +31,3 @@ class ANDROID(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'Android Internal Memory' MAIN_MEMORY_VOLUME_LABEL = 'Android Internal Memory'
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, Tijmen Ruizendaal <tijmen at mybebook.com>' __copyright__ = '2009, Tijmen Ruizendaal <tijmen at mybebook.com>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for BeBook Device driver for BeBook
@ -10,12 +13,12 @@ import re
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class BEBOOK(USBMS): class BEBOOK(USBMS):
name = 'BeBook driver' name = 'BeBook driver'
description = _('Communicate with the BeBook eBook reader.') description = _('Communicate with the BeBook eBook reader.')
author = 'Tijmen Ruizendaal' author = 'Tijmen Ruizendaal'
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
FORMATS = ['mobi', 'epub', 'pdf', 'txt'] FORMATS = ['mobi', 'epub', 'pdf', 'txt']
@ -94,4 +97,3 @@ class BEBOOK_MINI(BEBOOK):
MAIN_MEMORY_VOLUME_LABEL = 'BeBook Mini Internal Memory' MAIN_MEMORY_VOLUME_LABEL = 'BeBook Mini Internal Memory'
STORAGE_CARD_VOLUME_LABEL = 'BeBook Mini Storage Card' STORAGE_CARD_VOLUME_LABEL = 'BeBook Mini Storage Card'

View File

@ -1,9 +1,9 @@
from __future__ import with_statement # -*- coding: utf-8 -*-
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class BLACKBERRY(USBMS): class BLACKBERRY(USBMS):
@ -29,4 +29,3 @@ class BLACKBERRY(USBMS):
EBOOK_DIR_MAIN = 'ebooks' EBOOK_DIR_MAIN = 'ebooks'
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True

View File

@ -1,24 +1,26 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>' __copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for Bookeen's Cybook Gen 3 Device driver for Bookeen's Cybook Gen 3
''' '''
import os import os
import shutil
from itertools import cycle from itertools import cycle
from calibre.utils.filenames import ascii_filename as sanitize
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
import calibre.devices.cybookg3.t2b as t2b import calibre.devices.cybookg3.t2b as t2b
class CYBOOKG3(USBMS): class CYBOOKG3(USBMS):
name = 'Cybook Gen 3/Opus Device Interface'
description = _('Communicate with the Cybook eBook reader.') name = 'Cybook Gen 3 Device Interface'
description = _('Communicate with the Cybook Gen 3 eBook reader.')
author = _('John Schember') author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime # Be sure these have an entry in calibre.devices.mime
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt'] FORMATS = ['mobi', 'prc', 'html', 'pdf', 'rtf', 'txt']
@ -31,19 +33,21 @@ class CYBOOKG3(USBMS):
WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD' WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD'
WINDOWS_CARD_A_MEM = 'CYBOOK_GEN3__-SD' WINDOWS_CARD_A_MEM = 'CYBOOK_GEN3__-SD'
OSX_MAIN_MEM = ['Bookeen Cybook Gen3 -FD Media', 'Bookeen Cybook Opus -FD Media'] OSX_MAIN_MEM = 'Bookeen Cybook Gen3 -FD Media'
OSX_CARD_A_MEM = 'Bookeen Cybook Gen3 -SD Media' OSX_CARD_A_MEM = 'Bookeen Cybook Gen3 -SD Media'
MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory' MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Cybook Gen 3 Storage Card' STORAGE_CARD_VOLUME_LABEL = 'Cybook Gen 3 Storage Card'
EBOOK_DIR_MAIN = "eBooks" EBOOK_DIR_MAIN = 'eBooks'
EBOOK_DIR_CARD_A = "eBooks" EBOOK_DIR_CARD_A = 'eBooks'
THUMBNAIL_HEIGHT = 144 THUMBNAIL_HEIGHT = 144
DELETE_EXTS = ['.mbp', '.dat', '_6090.t2b']
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
def upload_books(self, files, names, on_card=None, end_session=True, def upload_books(self, files, names, on_card=None, end_session=True,
metadata=None): metadata=None):
path = self._sanity_check(on_card, files) path = self._sanity_check(on_card, files)
paths = [] paths = []
@ -51,45 +55,16 @@ class CYBOOKG3(USBMS):
metadata = iter(metadata) metadata = iter(metadata)
for i, infile in enumerate(files): for i, infile in enumerate(files):
newpath = path mdata, fname = metadata.next(), names.next()
mdata = metadata.next() filepath = self.create_upload_path(path, mdata, fname)
if 'tags' in mdata.keys():
for tag in mdata['tags']:
if tag.startswith(_('News')):
newpath = os.path.join(newpath, 'news')
newpath = os.path.join(newpath, sanitize(mdata.get('title', '')))
newpath = os.path.join(newpath, sanitize(mdata.get('timestamp', '')))
elif tag.startswith('/'):
newpath += tag
newpath = os.path.normpath(newpath)
break
if newpath == path:
newpath = os.path.join(newpath, sanitize(mdata.get('authors', _('Unknown'))))
newpath = os.path.join(newpath, sanitize(mdata.get('title', _('Unknown'))))
if not os.path.exists(newpath):
os.makedirs(newpath)
filepath = os.path.join(newpath, sanitize(names.next()))
paths.append(filepath) paths.append(filepath)
if hasattr(infile, 'read'): self.put_file(infile, filepath, replace_file=True)
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
coverdata = None coverdata = None
if 'cover' in mdata.keys(): cover = mdata.get('cover', None)
if mdata['cover'] != None: if cover:
coverdata = mdata['cover'][2] coverdata = cover[2]
t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb') t2bfile = open('%s_6090.t2b' % (os.path.splitext(filepath)[0]), 'wb')
t2b.write_t2b(t2bfile, coverdata) t2b.write_t2b(t2bfile, coverdata)
@ -101,31 +76,13 @@ class CYBOOKG3(USBMS):
return zip(paths, cycle([on_card])) return zip(paths, cycle([on_card]))
def delete_books(self, paths, end_session=True):
for i, path in enumerate(paths):
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
if os.path.exists(path):
os.unlink(path)
filepath, ext = os.path.splitext(path) class CYBOOK_OPUS(USBMS):
# Delete the ebook auxiliary file name = 'Cybook Opus Device Interface'
if os.path.exists(filepath + '.mbp'): description = _('Communicate with the Cybook Opus eBook reader.')
os.unlink(filepath + '.mbp') author = _('John Schember')
if os.path.exists(filepath + '.dat'): supported_platforms = ['windows', 'osx', 'linux']
os.unlink(filepath + '.dat')
# Delete the thumbnails file auto generated for the ebook
if os.path.exists(filepath + '_6090.t2b'):
os.unlink(filepath + '_6090.t2b')
try:
os.removedirs(os.path.dirname(path))
except:
pass
self.report_progress(1.0, _('Removing books from device...'))
class CYBOOK_OPUS(CYBOOKG3):
FORMATS = ['epub', 'pdf', 'txt'] FORMATS = ['epub', 'pdf', 'txt']
@ -133,14 +90,13 @@ class CYBOOK_OPUS(CYBOOKG3):
PRODUCT_ID = [0x0703] PRODUCT_ID = [0x0703]
BCD = [0x110] BCD = [0x110]
VENDOR_NAME = 'BOOKEEN'
WINDOWS_MAIN_MEM = 'CYBOOK_OPUS__-FD' WINDOWS_MAIN_MEM = 'CYBOOK_OPUS__-FD'
WINDOWS_CARD_A_MEM = 'CYBOOK_OPUS__-SD' WINDOWS_CARD_A_MEM = 'CYBOOK_OPUS__-SD'
OSX_MAIN_MEM = 'Bookeen Cybook Opus -FD Media' OSX_MAIN_MEM = 'Bookeen Cybook Opus -FD Media'
OSX_CARD_A_MEM = 'Bookeen Cybook Opus -SD Media' OSX_CARD_A_MEM = 'Bookeen Cybook Opus -SD Media'
def upload_books(self, *args, **kwargs): EBOOK_DIR_MAIN = 'eBooks'
USBMS.upload_books(self, *args, **kwargs) EBOOK_DIR_CARD_A = 'eBooks'
SUPPORTS_SUB_DIRS = True
def delete_books(self, *args, **kwargs):
USBMS.delete_books(self, *args, **kwargs)

View File

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for the Netronix EB600 Device driver for the Netronix EB600
@ -14,13 +18,15 @@ Windows PNP strings:
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class EB600(USBMS): class EB600(USBMS):
name = 'Netronix EB600 Device Interface' name = 'Netronix EB600 Device Interface'
description = _('Communicate with the EB600 eBook reader.') description = _('Communicate with the EB600 eBook reader.')
author = _('Kovid Goyal') author = _('Kovid Goyal')
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
FORMATS = ['epub', 'mobi', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt', 'pdf'] FORMATS = ['epub', 'mobi', 'prc', 'chm', 'djvu', 'html', 'rtf', 'txt',
'pdf']
DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt'] DRM_FORMATS = ['prc', 'mobi', 'html', 'pdf', 'txt']
VENDOR_ID = [0x1f85] VENDOR_ID = [0x1f85]
@ -59,4 +65,3 @@ class COOL_ER(EB600):
WINDOWS_MAIN_MEM = 'EREADER' WINDOWS_MAIN_MEM = 'EREADER'
EBOOK_DIR_MAIN = 'my docs' EBOOK_DIR_MAIN = 'my docs'

View File

@ -8,17 +8,15 @@ __docformat__ = 'restructuredtext en'
Device driver for IRex Iliad Device driver for IRex Iliad
''' '''
import os
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class ILIAD(USBMS): class ILIAD(USBMS):
name = 'IRex Iliad Device Interface' name = 'IRex Iliad Device Interface'
description = _('Communicate with the IRex Iliad eBook reader.') description = _('Communicate with the IRex Iliad eBook reader.')
author = _('John Schember') author = _('John Schember')
supported_platforms = ['windows', 'linux'] supported_platforms = ['windows', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime # Be sure these have an entry in calibre.devices.mime
FORMATS = ['mobi', 'prc', 'html', 'pdf', 'txt'] FORMATS = ['mobi', 'prc', 'html', 'pdf', 'txt']
@ -35,23 +33,5 @@ class ILIAD(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'IRex Iliad Main Memory' MAIN_MEMORY_VOLUME_LABEL = 'IRex Iliad Main Memory'
EBOOK_DIR_MAIN = 'books' EBOOK_DIR_MAIN = 'books'
DELETE_EXTS = ['.mbp']
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
def delete_books(self, paths, end_session=True):
for i, path in enumerate(paths):
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
if os.path.exists(path):
os.unlink(path)
filepath, ext = os.path.splitext(path)
# Delete the ebook auxiliary file
if os.path.exists(filepath + '.mbp'):
os.unlink(filepath + '.mbp')
try:
os.removedirs(os.path.dirname(path))
except:
pass
self.report_progress(1.0, _('Removing books from device...'))

View File

@ -8,17 +8,16 @@ __docformat__ = 'restructuredtext en'
Device driver for IRex Digiatal Reader Device driver for IRex Digiatal Reader
''' '''
import os
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class IREXDR1000(USBMS): class IREXDR1000(USBMS):
name = 'IRex Digital Reader 1000 Device Interface' name = 'IRex Digital Reader 1000 Device Interface'
description = _('Communicate with the IRex Digital Reader 1000 eBook reader.') description = _('Communicate with the IRex Digital Reader 1000 eBook ' \
'reader.')
author = _('John Schember') author = _('John Schember')
supported_platforms = ['windows', 'osx', 'linux'] supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats # Ordered list of supported formats
# Be sure these have an entry in calibre.devices.mime # Be sure these have an entry in calibre.devices.mime
FORMATS = ['epub', 'mobi', 'prc', 'html', 'pdf', 'txt'] FORMATS = ['epub', 'mobi', 'prc', 'html', 'pdf', 'txt']
@ -35,23 +34,5 @@ class IREXDR1000(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'IRex Digital Reader 1000 Main Memory' MAIN_MEMORY_VOLUME_LABEL = 'IRex Digital Reader 1000 Main Memory'
EBOOK_DIR_MAIN = 'ebooks' EBOOK_DIR_MAIN = 'ebooks'
DELETE_EXTS = ['.mbp']
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
def delete_books(self, paths, end_session=True):
for i, path in enumerate(paths):
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
if os.path.exists(path):
os.unlink(path)
filepath, ext = os.path.splitext(path)
# Delete the ebook auxiliary file
if os.path.exists(filepath + '.mbp'):
os.unlink(filepath + '.mbp')
try:
os.removedirs(os.path.dirname(path))
except:
pass
self.report_progress(1.0, _('Removing books from device...'))

View File

@ -1,10 +1,16 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, James Ralston <jralston at mindspring.com>' __copyright__ = '2009, James Ralston <jralston at mindspring.com>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for Ectaco Jetbook firmware >= JL04_v030e Device driver for Ectaco Jetbook firmware >= JL04_v030e
''' '''
import os, re, sys, shutil import os
import re
import sys
from itertools import cycle from itertools import cycle
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
@ -54,46 +60,18 @@ class JETBOOK(USBMS):
metadata = iter(metadata) metadata = iter(metadata)
for i, infile in enumerate(files): for i, infile in enumerate(files):
newpath = path mdata, fname = metadata.next(), names.next()
path = os.path.dirname(self.create_upload_path(path, mdata, fname))
mdata = metadata.next()
if 'tags' in mdata.keys():
for tag in mdata['tags']:
if tag.startswith(_('News')):
newpath = os.path.join(newpath, 'news')
newpath = os.path.join(newpath, mdata.get('title', ''))
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
break
elif tag.startswith('/'):
newpath += tag
newpath = os.path.normpath(newpath)
break
author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_') author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_')
title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_') title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_')
fileext = os.path.splitext(os.path.basename(names.next()))[1] fileext = os.path.splitext(os.path.basename(fname))[1]
fname = '%s#%s%s' % (author, title, fileext) fname = '%s#%s%s' % (author, title, fileext)
if newpath == path: filepath = os.path.join(path, fname)
newpath = os.path.join(newpath, author, title)
if not os.path.exists(newpath):
os.makedirs(newpath)
filepath = os.path.join(newpath, fname)
paths.append(filepath) paths.append(filepath)
if hasattr(infile, 'read'): self.put_file(infile, filepath, replace_file=True)
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...')) self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
@ -132,6 +110,3 @@ class JETBOOK(USBMS):
drives['carda'] = main drives['carda'] = main
return drives return drives

View File

@ -1,14 +1,21 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>' __copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for Amazon's Kindle Device driver for Amazon's Kindle
''' '''
import os, re, sys import os
import re
import sys
from calibre.devices.usbms.driver import USBMS from calibre.devices.usbms.driver import USBMS
class KINDLE(USBMS): class KINDLE(USBMS):
name = 'Kindle Device Interface' name = 'Kindle Device Interface'
description = _('Communicate with the Kindle eBook reader.') description = _('Communicate with the Kindle eBook reader.')
author = _('John Schember') author = _('John Schember')
@ -31,26 +38,14 @@ class KINDLE(USBMS):
MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory' MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card' STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card'
EBOOK_DIR_MAIN = "documents" EBOOK_DIR_MAIN = 'documents'
EBOOK_DIR_CARD_A = "documents" EBOOK_DIR_CARD_A = 'documents'
DELETE_EXTS = ['.mbp']
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
WIRELESS_FILE_NAME_PATTERN = re.compile( WIRELESS_FILE_NAME_PATTERN = re.compile(
r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*') r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*')
def delete_books(self, paths, end_session=True):
for i, path in enumerate(paths):
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
if os.path.exists(path):
os.unlink(path)
filepath = os.path.splitext(path)[0]
# Delete the ebook auxiliary file
if os.path.exists(filepath + '.mbp'):
os.unlink(filepath + '.mbp')
self.report_progress(1.0, _('Removing books from device...'))
@classmethod @classmethod
def metadata_from_path(cls, path): def metadata_from_path(cls, path):
mi = cls.metadata_from_formats([path]) mi = cls.metadata_from_formats([path])
@ -65,6 +60,7 @@ class KINDLE(USBMS):
class KINDLE2(KINDLE): class KINDLE2(KINDLE):
name = 'Kindle 2 Device Interface' name = 'Kindle 2 Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.') description = _('Communicate with the Kindle 2 eBook reader.')
author = _('John Schember') author = _('John Schember')
@ -73,7 +69,9 @@ class KINDLE2(KINDLE):
PRODUCT_ID = [0x0002] PRODUCT_ID = [0x0002]
BCD = [0x0100] BCD = [0x0100]
class KINDLE_DX(KINDLE): class KINDLE_DX(KINDLE):
name = 'Kindle DX Device Interface' name = 'Kindle DX Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.') description = _('Communicate with the Kindle 2 eBook reader.')
author = _('John Schember') author = _('John Schember')
@ -83,5 +81,3 @@ class KINDLE_DX(KINDLE):
PRODUCT_ID = [0x0003] PRODUCT_ID = [0x0003]
BCD = [0x0100] BCD = [0x0100]

View File

@ -1,15 +1,21 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __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>' '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for the SONY PRS-505 Device driver for the SONY PRS-505
''' '''
import os, re, time
import os
import re
import time
from itertools import cycle from itertools import cycle
from calibre.devices.usbms.cli import CLI from calibre.devices.usbms.cli import CLI
from calibre.devices.usbms.device import Device from calibre.devices.usbms.device import Device
from calibre.devices.errors import DeviceError, FreeSpaceError
from calibre.devices.prs505.books import BookList, fix_ids from calibre.devices.prs505.books import BookList, fix_ids
from calibre import __appname__ from calibre import __appname__
@ -80,7 +86,6 @@ class PRS505(CLI, Device):
self.report_progress(1.0, _('Get device information...')) self.report_progress(1.0, _('Get device information...'))
return (self.__class__.__name__, '', '', '') return (self.__class__.__name__, '', '', '')
def books(self, oncard=None, end_session=True): def books(self, oncard=None, end_session=True):
if oncard == 'carda' and not self._card_a_prefix: if oncard == 'carda' and not self._card_a_prefix:
self.report_progress(1.0, _('Getting list of books on device...')) self.report_progress(1.0, _('Getting list of books on device...'))
@ -105,48 +110,13 @@ class PRS505(CLI, Device):
def upload_books(self, files, names, on_card=None, end_session=True, def upload_books(self, files, names, on_card=None, end_session=True,
metadata=None): metadata=None):
if on_card == 'carda' and not self._card_a_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card == 'cardb' and not self._card_b_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card and on_card not in ('carda', 'cardb'):
raise DeviceError(_('The reader has no storage card in this slot.'))
if on_card == 'carda': path = self._sanity_check(on_card, files)
path = os.path.join(self._card_a_prefix, self.CARD_PATH_PREFIX)
elif on_card == 'cardb':
path = os.path.join(self._card_b_prefix, self.CARD_PATH_PREFIX)
else:
path = os.path.join(self._main_prefix, 'database', 'media', 'books')
def get_size(obj):
if hasattr(obj, 'seek'):
obj.seek(0, 2)
size = obj.tell()
obj.seek(0)
return size
return os.path.getsize(obj)
sizes = [get_size(f) for f in files]
size = sum(sizes)
if not on_card and size > self.free_space()[0] - 2*1024*1024:
raise FreeSpaceError(_("There is insufficient free space in main memory"))
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
paths, ctimes = [], [] paths, ctimes = [], []
names = iter(names) names = iter(names)
metadata = iter(metadata) metadata = iter(metadata)
for i, infile in enumerate(files): for i, infile in enumerate(files):
close = False
if not hasattr(infile, 'read'):
infile, close = open(infile, 'rb'), True
infile.seek(0)
mdata, fname = metadata.next(), names.next() mdata, fname = metadata.next(), names.next()
filepath = self.create_upload_path(path, mdata, fname) filepath = self.create_upload_path(path, mdata, fname)
@ -154,8 +124,6 @@ class PRS505(CLI, Device):
self.put_file(infile, paths[-1], replace_file=True) self.put_file(infile, paths[-1], replace_file=True)
if close:
infile.close()
ctimes.append(os.path.getctime(paths[-1])) ctimes.append(os.path.getctime(paths[-1]))
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...')) self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))

View File

@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
''' '''
Device driver for the SONY PRS-700 Device driver for the SONY PRS-700
@ -23,4 +26,3 @@ class PRS700(PRS505):
OSX_MAIN_MEM = 'Sony PRS-700/UC Media' OSX_MAIN_MEM = 'Sony PRS-700/UC Media'
OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media' OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media'
OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD' OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD'

View File

@ -1,13 +1,17 @@
__license__ = 'GPL v3' # -*- coding: utf-8 -*-
__copyright__ = '2009, John Schember <john at nachtimwald.com>'
'''
'''
import os, fnmatch, re, time __license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import os
import re
import time
from calibre.devices.interface import BookList as _BookList from calibre.devices.interface import BookList as _BookList
class Book(object): class Book(object):
def __init__(self, path, title, authors, mime): def __init__(self, path, title, authors, mime):
self.title = title self.title = title
self.authors = authors self.authors = authors
@ -33,14 +37,17 @@ class Book(object):
return None return None
def __str__(self): def __str__(self):
""" Return a utf-8 encoded string with title author and path information """ '''
Return a utf-8 encoded string with title author and path information
'''
return self.title.encode('utf-8') + " by " + \ return self.title.encode('utf-8') + " by " + \
self.authors.encode('utf-8') + " at " + self.path.encode('utf-8') self.authors.encode('utf-8') + " at " + self.path.encode('utf-8')
class BookList(_BookList): class BookList(_BookList):
def supports_tags(self): def supports_tags(self):
return False return False
def set_tags(self, book, tags): def set_tags(self, book, tags):
pass pass

View File

@ -1,11 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import with_statement
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>' __copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, shutil import os
import shutil
from calibre.devices.errors import PathError from calibre.devices.errors import PathError
@ -33,6 +33,10 @@ class CLI(object):
def put_file(self, infile, path, replace_file=False, end_session=True): def put_file(self, infile, path, replace_file=False, end_session=True):
path = self.munge_path(path) path = self.munge_path(path)
close = False
if not hasattr(infile, 'read'):
infile, close = open(infile, 'rb'), True
infile.seek(0)
if os.path.isdir(path): if os.path.isdir(path):
path = os.path.join(path, infile.name) path = os.path.join(path, infile.name)
if not replace_file and os.path.exists(path): if not replace_file and os.path.exists(path):
@ -44,6 +48,8 @@ class CLI(object):
shutil.copyfileobj(infile, dest, 10*1024*1024) shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush() dest.flush()
dest.close() dest.close()
if close:
infile.close()
def munge_path(self, path): def munge_path(self, path):
if path.startswith('/') and not (path.startswith(self._main_prefix) or \ if path.startswith('/') and not (path.startswith(self._main_prefix) or \

View File

@ -1,13 +1,23 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '''2009, John Schember <john at nachtimwald.com> __copyright__ = '2009, John Schember <john at nachtimwald.com> ' \
and Kovid Goyal <kovid@kovidgoyal.net>''' '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
''' '''
Generic device driver. This is not a complete stand alone driver. It is Generic device driver. This is not a complete stand alone driver. It is
intended to be subclassed with the relevant parts implemented for a particular intended to be subclassed with the relevant parts implemented for a particular
device. This class handles device detection. device. This class handles device detection.
''' '''
import os, subprocess, time, re, sys, glob, shutil import os
import subprocess
import time
import re
import sys
import glob
import shutil
from itertools import repeat from itertools import repeat
from math import ceil from math import ceil
@ -18,6 +28,7 @@ from calibre import iswindows, islinux, isosx, __appname__
from calibre.utils.filenames import ascii_filename as sanitize from calibre.utils.filenames import ascii_filename as sanitize
class Device(DeviceConfig, DevicePlugin): class Device(DeviceConfig, DevicePlugin):
''' '''
This class provides logic common to all drivers for devices that export themselves 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 as USB Mass Storage devices. If you are writing such a driver, inherit from this
@ -240,7 +251,6 @@ class Device(DeviceConfig, DevicePlugin):
return True return True
return False return False
time.sleep(6) time.sleep(6)
drives = {} drives = {}
wmi = __import__('wmi', globals(), locals(), [], -1) wmi = __import__('wmi', globals(), locals(), [], -1)
@ -294,7 +304,6 @@ class Device(DeviceConfig, DevicePlugin):
return True return True
return False return False
def get_osx_mountpoints(self, raw=None): def get_osx_mountpoints(self, raw=None):
raw = self.run_ioreg(raw) raw = self.run_ioreg(raw)
lines = raw.splitlines() lines = raw.splitlines()
@ -458,7 +467,6 @@ class Device(DeviceConfig, DevicePlugin):
return node return node
return nodes[-1][0] return nodes[-1][0]
def open_linux(self): def open_linux(self):
def mount(node, type): def mount(node, type):
@ -497,7 +505,6 @@ class Device(DeviceConfig, DevicePlugin):
return None, ret return None, ret
return self.node_mountpoint(node)+'/', 0 return self.node_mountpoint(node)+'/', 0
main, carda, cardb = self.find_device_nodes() main, carda, cardb = self.find_device_nodes()
if main is None: if main is None:
raise DeviceError(_('Unable to detect the %s disk drive.') raise DeviceError(_('Unable to detect the %s disk drive.')
@ -600,7 +607,6 @@ class Device(DeviceConfig, DevicePlugin):
except: except:
pass pass
def eject(self): def eject(self):
if islinux: if islinux:
try: try:
@ -619,6 +625,40 @@ class Device(DeviceConfig, DevicePlugin):
pass pass
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
def _sanity_check(self, on_card, files):
if on_card == 'carda' and not self._card_a_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card == 'cardb' and not self._card_b_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card and on_card not in ('carda', 'cardb'):
raise DeviceError(_('Selected slot: %s is not supported.') % on_card)
if on_card == 'carda':
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
elif on_card == 'cardb':
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
else:
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
def get_size(obj):
if hasattr(obj, 'seek'):
obj.seek(0, os.SEEK_END)
size = obj.tell()
obj.seek(0)
return size
return os.path.getsize(obj)
sizes = [get_size(f) for f in files]
size = sum(sizes)
if not on_card and size > self.free_space()[0] - 2*1024*1024:
raise FreeSpaceError(_("There is insufficient free space in main memory"))
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
return path
def create_upload_path(self, path, mdata, fname): def create_upload_path(self, path, mdata, fname):
resizable = [] resizable = []
newpath = path newpath = path
@ -681,10 +721,7 @@ class Device(DeviceConfig, DevicePlugin):
filepath = filepath.replace(os.sep+os.sep, os.sep) filepath = filepath.replace(os.sep+os.sep, os.sep)
newpath = os.path.dirname(filepath) newpath = os.path.dirname(filepath)
if not os.path.exists(newpath): if not os.path.exists(newpath):
os.makedirs(newpath) os.makedirs(newpath)
return filepath return filepath

View File

@ -1,5 +1,9 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, John Schember <john at nachtimwald.com>' __copyright__ = '2009, John Schember <john at nachtimwald.com>'
__docformat__ = 'restructuredtext en'
''' '''
Generic USB Mass storage device driver. This is not a complete stand alone Generic USB Mass storage device driver. This is not a complete stand alone
driver. It is intended to be subclassed with the relevant parts implemented driver. It is intended to be subclassed with the relevant parts implemented
@ -9,14 +13,12 @@ for a particular device.
import os import os
import fnmatch import fnmatch
import re import re
import shutil
from itertools import cycle from itertools import cycle
from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata import authors_to_string
from calibre.devices.usbms.cli import CLI from calibre.devices.usbms.cli import CLI
from calibre.devices.usbms.device import Device from calibre.devices.usbms.device import Device
from calibre.devices.usbms.books import BookList, Book from calibre.devices.usbms.books import BookList, Book
from calibre.devices.errors import DeviceError, FreeSpaceError
from calibre.devices.mime import mime_type_ext from calibre.devices.mime import mime_type_ext
# CLI must come before Device as it implments the CLI functions that # CLI must come before Device as it implments the CLI functions that
@ -32,6 +34,7 @@ class USBMS(CLI, Device):
EBOOK_DIR_MAIN = '' EBOOK_DIR_MAIN = ''
EBOOK_DIR_CARD_A = '' EBOOK_DIR_CARD_A = ''
EBOOK_DIR_CARD_B = '' EBOOK_DIR_CARD_B = ''
DELETE_EXTS = []
CAN_SET_METADATA = False CAN_SET_METADATA = False
def reset(self, key='-1', log_packets=False, report_progress=None): def reset(self, key='-1', log_packets=False, report_progress=None):
@ -80,40 +83,6 @@ class USBMS(CLI, Device):
return bl return bl
def _sanity_check(self, on_card, files):
if on_card == 'carda' and not self._card_a_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card == 'cardb' and not self._card_b_prefix:
raise ValueError(_('The reader has no storage card in this slot.'))
elif on_card and on_card not in ('carda', 'cardb'):
raise DeviceError(_('Selected slot: %s is not supported.') % on_card)
if on_card == 'carda':
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
elif on_card == 'cardb':
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
else:
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
def get_size(obj):
if hasattr(obj, 'seek'):
obj.seek(0, os.SEEK_END)
size = obj.tell()
obj.seek(0)
return size
return os.path.getsize(obj)
sizes = [get_size(f) for f in files]
size = sum(sizes)
if not on_card and size > self.free_space()[0] - 2*1024*1024:
raise FreeSpaceError(_("There is insufficient free space in main memory"))
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
return path
def upload_books(self, files, names, on_card=None, end_session=True, def upload_books(self, files, names, on_card=None, end_session=True,
metadata=None): metadata=None):
@ -129,16 +98,7 @@ class USBMS(CLI, Device):
paths.append(filepath) paths.append(filepath)
if hasattr(infile, 'read'): self.put_file(infile, filepath, replace_file=True)
infile.seek(0)
dest = open(filepath, 'wb')
shutil.copyfileobj(infile, dest, 10*1024*1024)
dest.flush()
dest.close()
else:
shutil.copy2(infile, filepath)
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...')) self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
@ -146,7 +106,6 @@ class USBMS(CLI, Device):
return zip(paths, cycle([on_card])) return zip(paths, cycle([on_card]))
def add_books_to_metadata(self, locations, metadata, booklists): def add_books_to_metadata(self, locations, metadata, booklists):
for i, location in enumerate(locations): for i, location in enumerate(locations):
self.report_progress((i+1) / float(len(locations)), _('Adding books to device metadata listing...')) self.report_progress((i+1) / float(len(locations)), _('Adding books to device metadata listing...'))
@ -159,13 +118,18 @@ class USBMS(CLI, Device):
booklists[blist].append(book) booklists[blist].append(book)
self.report_progress(1.0, _('Adding books to device metadata listing...')) self.report_progress(1.0, _('Adding books to device metadata listing...'))
def delete_books(self, paths, end_session=True): def delete_books(self, paths, end_session=True):
for i, path in enumerate(paths): for i, path in enumerate(paths):
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...')) self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
if os.path.exists(path): if os.path.exists(path):
# Delete the ebook # Delete the ebook
os.unlink(path) os.unlink(path)
filepath = os.path.splitext(path)[0]
for ext in self.DELETE_EXTS:
if os.path.exists(filepath + ext):
os.unlink(filepath + ext)
if self.SUPPORTS_SUB_DIRS: if self.SUPPORTS_SUB_DIRS:
try: try:
os.removedirs(os.path.dirname(path)) os.removedirs(os.path.dirname(path))
@ -199,7 +163,6 @@ class USBMS(CLI, Device):
with quick_metadata: with quick_metadata:
return metadata_from_formats(fmts) return metadata_from_formats(fmts)
@classmethod @classmethod
def book_from_path(cls, path): def book_from_path(cls, path):
from calibre.ebooks.metadata.meta import path_to_ext from calibre.ebooks.metadata.meta import path_to_ext