mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Sync to trunk.
This commit is contained in:
commit
b61f5fcd3b
@ -4,6 +4,41 @@
|
|||||||
# for important features/bug fixes.
|
# for important features/bug fixes.
|
||||||
# Also, each release can have new and improved recipes.
|
# Also, each release can have new and improved recipes.
|
||||||
|
|
||||||
|
- version: 0.6.31
|
||||||
|
date: 2009-12-27
|
||||||
|
|
||||||
|
new features:
|
||||||
|
- title: "Support for the SONY PRS 900 and the Airis dBook"
|
||||||
|
type: major
|
||||||
|
|
||||||
|
- title: "Device detection on OS X now directly queries the IOKit registry instead of parsing the output of the ioreg command."
|
||||||
|
description: >
|
||||||
|
"The logic for device detection in OS X is very similar to that in linux. This means that if a windows driver
|
||||||
|
for a device is written, it should work with no modification on both OS X and Linux."
|
||||||
|
|
||||||
|
bug fixes:
|
||||||
|
- title: "Fix a major regression in the 0.6.30 news download system that caused a lot of recipes to fail"
|
||||||
|
|
||||||
|
- title: "Make PRS 500 driver thread safe."
|
||||||
|
tickets: [4307]
|
||||||
|
|
||||||
|
- title: "Fix ebook viewer not working when launched as standalone program to view PDF files on windows"
|
||||||
|
|
||||||
|
- title: "PDB Output: Fix italics"
|
||||||
|
|
||||||
|
|
||||||
|
new recipes:
|
||||||
|
|
||||||
|
- title: The Hartford Courant
|
||||||
|
author: Being
|
||||||
|
|
||||||
|
- title: National Post
|
||||||
|
author: Nick Redding
|
||||||
|
|
||||||
|
- title: The Columbus Dispatch
|
||||||
|
author: kwetal
|
||||||
|
|
||||||
|
|
||||||
- version: 0.6.30
|
- version: 0.6.30
|
||||||
date: 2009-12-26
|
date: 2009-12-26
|
||||||
|
|
||||||
|
90
resources/recipes/hartford_courant.recipe
Normal file
90
resources/recipes/hartford_courant.recipe
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
from __future__ import with_statement
|
||||||
|
__license__ = 'GPL 3'
|
||||||
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class ChicagoTribune(BasicNewsRecipe):
|
||||||
|
|
||||||
|
title = 'The Hartford Courant'
|
||||||
|
__author__ = 'Being and Sujata Raman'
|
||||||
|
description = 'Politics, local and business news from Hartford'
|
||||||
|
language = 'en'
|
||||||
|
|
||||||
|
use_embedded_content = False
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':["story","entry-asset asset hentry"]}),
|
||||||
|
dict(name='div', attrs={'id':["pagebody","story","maincontentcontainer"]}),
|
||||||
|
]
|
||||||
|
remove_tags_after = [ {'class':['photo_article',]} ]
|
||||||
|
|
||||||
|
remove_tags = [{'id':["moduleArticleTools","content-bottom","rail","articleRelates module","toolSet","relatedrailcontent","div-wrapper","beta","atp-comments","footer"]},
|
||||||
|
{'class':["clearfix","relatedTitle","articleRelates module","asset-footer","tools","comments","featurePromo","featurePromo fp-topjobs brownBackground","clearfix fullSpan brownBackground","curvedContent"]},
|
||||||
|
dict(name='font',attrs={'id':["cr-other-headlines"]})]
|
||||||
|
extra_css = '''
|
||||||
|
h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;}
|
||||||
|
h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;}
|
||||||
|
.byline {font-family:Arial,Helvetica,sans-serif; font-size:xx-small;}
|
||||||
|
.date {font-family:Arial,Helvetica,sans-serif; font-size:xx-small;}
|
||||||
|
p{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
.copyright {font-family:Arial,Helvetica,sans-serif;font-size:xx-small;text-align:center}
|
||||||
|
.story{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
.entry-asset asset hentry{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
.pagebody{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
.maincontentcontainer{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
.story-body{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
body{font-family:Helvetica,Arial,sans-serif;font-size:small;}
|
||||||
|
'''
|
||||||
|
feeds = [
|
||||||
|
('Breaking News', 'http://feeds.feedburner.com/courant-breaking-news/'),
|
||||||
|
('Nation/World News', 'http://feeds.feedburner.com/courant-nation-world/'),
|
||||||
|
('Connecticut News', 'http://feeds.feedburner.com/courant-connecticut-news/'),
|
||||||
|
('Hartford News', 'http://feeds.feedburner.com/courant-hartford/'),
|
||||||
|
('West Hartford News', 'http://feeds.feedburner.com/courant-west-hartford/'),
|
||||||
|
('Bristol', 'http://feeds.feedburner.com/courant-bristol/'),
|
||||||
|
('Politics', 'http://feeds.feedburner.com/courant-politics/'),
|
||||||
|
('Opinion', 'http://feeds.feedburner.com/courant-opinion/'),
|
||||||
|
('Editorials', 'http://feeds.feedburner.com/courant-editorials/'),
|
||||||
|
('Letters', 'http://feeds.feedburner.com/courant-letters/'),
|
||||||
|
('Bob Englehart', 'http://feeds2.feedburner.com/BobEnglehartEnglehartsView'),
|
||||||
|
('Business', 'http://feeds.feedburner.com/courant-business/'),
|
||||||
|
('Sports', 'http://feeds.feedburner.com/courant-sports/'),
|
||||||
|
('Features', 'http://feeds.feedburner.com/courant-features/'),
|
||||||
|
('Consumer', 'http://feeds.feedburner.com/courant-consumer/'),
|
||||||
|
('Shopping', 'http://feeds.feedburner.com/courant-shopping/'),
|
||||||
|
('Arts & Theater', 'http://feeds.feedburner.com/courant-entertainment/'),
|
||||||
|
('Entertainment', 'http://feeds.feedburner.com/courant-stage/'),
|
||||||
|
('Music', 'http://feeds.feedburner.com/courant-music/'),
|
||||||
|
('TV', 'http://feeds.feedburner.com/courant-tv/'),
|
||||||
|
('Movies', 'http://feeds.feedburner.com/courant-movies/'),
|
||||||
|
#('Metromix headlines', 'http://feeds.feedburner.com/metromix/topheadlines/'),
|
||||||
|
#('Metromix events', 'http://feeds.feedburner.com/metromix/events/'),
|
||||||
|
#('Metromix restaurants', 'http://feeds.feedburner.com/metromix/restaurants/'),
|
||||||
|
('Outdoors', 'http://feeds.feedburner.com/courant-outdoors/'),
|
||||||
|
('Peter Marteka', 'http://feeds.feedburner.com/courant-marteka-column/'),
|
||||||
|
('Susan Campbell', 'http://feeds.feedburner.com/courant-campbell-column/'),
|
||||||
|
('Helen Ubinas', 'http://feeds.feedburner.com/courant-helen-ubinas-column/'),
|
||||||
|
('Jim Shea', 'http://feeds.feedburner.com/courant-jim-shea-column/'),
|
||||||
|
('Tom Condon', 'http://feeds.feedburner.com/courant-tom-condon-column/'),
|
||||||
|
('Colin McEnroe', 'http://feeds.feedburner.com/courant-colin-mcenroe-column/'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
print article.get('feedburner_origlink', article.get('guid', article.get('link')))
|
||||||
|
return article.get('feedburner_origlink', article.get('guid', article.get('link')))
|
||||||
|
|
||||||
|
|
||||||
|
def postprocess_html(self, soup, first_fetch):
|
||||||
|
for t in soup.findAll(['table', 'tr', 'td']):
|
||||||
|
t.name = 'div'
|
||||||
|
|
||||||
|
for tag in soup.findAll('form', dict(attrs={'name':["comments_form"]})):
|
||||||
|
tag.extract()
|
||||||
|
for tag in soup.findAll('font', dict(attrs={'id':["cr-other-headlines"]})):
|
||||||
|
tag.extract()
|
||||||
|
|
||||||
|
return soup
|
20
resources/recipes/national_post.recipe
Normal file
20
resources/recipes/national_post.recipe
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1261379503(BasicNewsRecipe):
|
||||||
|
title = u'National Post'
|
||||||
|
language = 'en_CA'
|
||||||
|
__author__ = 'Nick Redding'
|
||||||
|
description = u"News from Canada"
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 25
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':'content'})]
|
||||||
|
remove_tags = [dict(name='div', attrs={'class':'story-tools'}),dict(name='div', attrs={'class':'newsblock'}),dict(name='p', attrs={'class':'border-top'}),dict(name='div', attrs={'id':'footer'})]
|
||||||
|
|
||||||
|
feeds = [(u'News Headlines', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=section| news'),
|
||||||
|
(u'FP Headlines', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=section| financial%20post|storytype|business'),
|
||||||
|
(u'Arts & Life Headlines', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=section| arts%20%26%20life|storytype|news'),
|
||||||
|
(u'Canada News', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=storytyp e|webcanada&feed=rss'),
|
||||||
|
(u'World News', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=storytyp e|webworld&feed=rss'),(u'Editorial', u'http://www.nationalpost.com/scripts/sp6query.aspx?catalog=ntnp&type=stry&tags=section| editorial'),
|
||||||
|
(u'FP Opinion', u'http://www.nationalpost.com/scripts/columnists.aspx?publication=national+post&columnty pe=fp')]
|
||||||
|
|
@ -72,7 +72,7 @@ class Translations(POT):
|
|||||||
if os.path.exists(pycountry):
|
if os.path.exists(pycountry):
|
||||||
iso639 = self.j(pycountry, 'iso639.mo')
|
iso639 = self.j(pycountry, 'iso639.mo')
|
||||||
dest = self.j(self.d(dest), self.b(iso639))
|
dest = self.j(self.d(dest), self.b(iso639))
|
||||||
if self.newer(dest, iso639):
|
if self.newer(dest, iso639) and os.path.exists(iso639):
|
||||||
self.info('\tCopying ISO 639 translations')
|
self.info('\tCopying ISO 639 translations')
|
||||||
shutil.copy2(iso639, dest)
|
shutil.copy2(iso639, dest)
|
||||||
else:
|
else:
|
||||||
|
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.6.30'
|
__version__ = '0.6.31'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@ -24,6 +24,7 @@ isosx = 'darwin' in sys.platform.lower()
|
|||||||
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
|
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
|
||||||
islinux = not(iswindows or isosx)
|
islinux = not(iswindows or isosx)
|
||||||
isfrozen = hasattr(sys, 'frozen')
|
isfrozen = hasattr(sys, 'frozen')
|
||||||
|
isunix = isosx or islinux
|
||||||
|
|
||||||
try:
|
try:
|
||||||
preferred_encoding = locale.getpreferredencoding()
|
preferred_encoding = locale.getpreferredencoding()
|
||||||
|
@ -257,6 +257,7 @@ class SonyReader900Output(SonyReaderOutput):
|
|||||||
description = _('This profile is intended for the SONY PRS-900.')
|
description = _('This profile is intended for the SONY PRS-900.')
|
||||||
|
|
||||||
screen_size = (600, 999)
|
screen_size = (600, 999)
|
||||||
|
comic_screen_size = screen_size
|
||||||
|
|
||||||
class JetBook5Output(OutputProfile):
|
class JetBook5Output(OutputProfile):
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ def migrate(old, new):
|
|||||||
|
|
||||||
def debug_device_driver():
|
def debug_device_driver():
|
||||||
from calibre.devices import debug
|
from calibre.devices import debug
|
||||||
print debug()
|
debug(ioreg_to_tmp=True, buf=sys.stdout)
|
||||||
if iswindows:
|
if iswindows:
|
||||||
raw_input('Press Enter to continue...')
|
raw_input('Press Enter to continue...')
|
||||||
|
|
||||||
|
@ -27,14 +27,15 @@ def strftime(epoch, zone=time.gmtime):
|
|||||||
src[2] = INVERSE_MONTH_MAP[int(src[2])]
|
src[2] = INVERSE_MONTH_MAP[int(src[2])]
|
||||||
return ' '.join(src)
|
return ' '.join(src)
|
||||||
|
|
||||||
def debug():
|
def debug(ioreg_to_tmp=False, buf=None):
|
||||||
from calibre.customize.ui import device_plugins
|
from calibre.customize.ui import device_plugins
|
||||||
from calibre.devices.scanner import DeviceScanner
|
from calibre.devices.scanner import DeviceScanner
|
||||||
from calibre.constants import iswindows, isosx, __version__
|
from calibre.constants import iswindows, isosx, __version__
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
oldo, olde = sys.stdout, sys.stderr
|
oldo, olde = sys.stdout, sys.stderr
|
||||||
|
|
||||||
buf = StringIO()
|
if buf is None:
|
||||||
|
buf = StringIO()
|
||||||
sys.stdout = sys.stderr = buf
|
sys.stdout = sys.stderr = buf
|
||||||
try:
|
try:
|
||||||
out = partial(prints, file=buf)
|
out = partial(prints, file=buf)
|
||||||
@ -82,16 +83,17 @@ def debug():
|
|||||||
connected_devices = []
|
connected_devices = []
|
||||||
for dev in device_plugins():
|
for dev in device_plugins():
|
||||||
out('Looking for', dev.__class__.__name__)
|
out('Looking for', dev.__class__.__name__)
|
||||||
connected = s.is_device_connected(dev, debug=True)
|
connected, det = s.is_device_connected(dev, debug=True)
|
||||||
if connected:
|
if connected:
|
||||||
connected_devices.append(dev)
|
connected_devices.append((dev, det))
|
||||||
|
|
||||||
errors = {}
|
errors = {}
|
||||||
success = False
|
success = False
|
||||||
for dev in connected_devices:
|
for dev, det in connected_devices:
|
||||||
out('Device possibly connected:', dev.__class__.name)
|
out('Device possibly connected:', dev.__class__.name)
|
||||||
out('Trying to open device...', end=' ')
|
out('Trying to open device...', end=' ')
|
||||||
try:
|
try:
|
||||||
|
dev.reset(detected_device=det)
|
||||||
dev.open()
|
dev.open()
|
||||||
out('OK')
|
out('OK')
|
||||||
except:
|
except:
|
||||||
@ -112,11 +114,17 @@ def debug():
|
|||||||
out(' ')
|
out(' ')
|
||||||
|
|
||||||
if ioreg is not None:
|
if ioreg is not None:
|
||||||
|
ioreg = 'IOREG Output\n'+ioreg
|
||||||
out(' ')
|
out(' ')
|
||||||
out('IOREG Output')
|
if ioreg_to_tmp:
|
||||||
out(ioreg)
|
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)
|
||||||
|
|
||||||
return buf.getvalue().decode('utf-8')
|
if hasattr(buf, 'getvalue'):
|
||||||
|
return buf.getvalue().decode('utf-8')
|
||||||
finally:
|
finally:
|
||||||
sys.stdout = oldo
|
sys.stdout = oldo
|
||||||
sys.stderr = olde
|
sys.stderr = olde
|
||||||
|
@ -10,7 +10,7 @@ Device driver for Bookeen's Cybook Gen 3
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from calibre import islinux
|
from calibre.constants import isunix
|
||||||
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
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class CYBOOKG3(USBMS):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_handle(cls, device_info, debug=False):
|
def can_handle(cls, device_info, debug=False):
|
||||||
if islinux:
|
if isunix:
|
||||||
return device_info[3] == 'Bookeen' and device_info[4] == 'Cybook Gen3'
|
return device_info[3] == 'Bookeen' and device_info[4] == 'Cybook Gen3'
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -87,6 +87,6 @@ class CYBOOK_OPUS(CYBOOKG3):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_handle(cls, device_info, debug=False):
|
def can_handle(cls, device_info, debug=False):
|
||||||
if islinux:
|
if isunix:
|
||||||
return device_info[3] == 'Bookeen'
|
return device_info[3] == 'Bookeen'
|
||||||
return True
|
return True
|
||||||
|
@ -104,12 +104,12 @@ class DevicePlugin(Plugin):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def is_usb_connected(cls, devices_on_system, debug=False):
|
def is_usb_connected(cls, devices_on_system, debug=False):
|
||||||
'''
|
'''
|
||||||
Return True if a device handled by this plugin is currently connected.
|
Return True, device_info if a device handled by this plugin is currently connected.
|
||||||
|
|
||||||
:param devices_on_system: List of devices currently connected
|
:param devices_on_system: List of devices currently connected
|
||||||
'''
|
'''
|
||||||
if iswindows:
|
if iswindows:
|
||||||
return cls.is_usb_connected_windows(devices_on_system, debug=debug)
|
return cls.is_usb_connected_windows(devices_on_system, debug=debug), None
|
||||||
|
|
||||||
vendors_on_system = set([x[0] for x in devices_on_system])
|
vendors_on_system = set([x[0] for x in devices_on_system])
|
||||||
vendors = cls.VENDOR_ID if hasattr(cls.VENDOR_ID, '__len__') else [cls.VENDOR_ID]
|
vendors = cls.VENDOR_ID if hasattr(cls.VENDOR_ID, '__len__') else [cls.VENDOR_ID]
|
||||||
@ -134,18 +134,20 @@ class DevicePlugin(Plugin):
|
|||||||
if debug:
|
if debug:
|
||||||
cls.print_usb_device_info(dev)
|
cls.print_usb_device_info(dev)
|
||||||
if cls.can_handle(dev, debug=debug):
|
if cls.can_handle(dev, debug=debug):
|
||||||
return True
|
return True, dev
|
||||||
return False
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||||
|
detected_device=None) :
|
||||||
"""
|
"""
|
||||||
@param key: The key to unlock the device
|
:key: The key to unlock the device
|
||||||
@param log_packets: If true the packet stream to/from the device is logged
|
:log_packets: If true the packet stream to/from the device is logged
|
||||||
@param report_progress: Function that is called with a % progress
|
:report_progress: Function that is called with a % progress
|
||||||
(number between 0 and 100) for various tasks
|
(number between 0 and 100) for various tasks
|
||||||
If it is called with -1 that means that the
|
If it is called with -1 that means that the
|
||||||
task does not have any progress information
|
task does not have any progress information
|
||||||
|
:detected_device: Device information from the device scanner
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -206,9 +206,10 @@ def main():
|
|||||||
scanner.scan()
|
scanner.scan()
|
||||||
connected_devices = []
|
connected_devices = []
|
||||||
for d in device_plugins():
|
for d in device_plugins():
|
||||||
if scanner.is_device_connected(d):
|
ok, det = scanner.is_device_connected(d)
|
||||||
|
if ok:
|
||||||
dev = d
|
dev = d
|
||||||
dev.reset(log_packets=options.log_packets)
|
dev.reset(log_packets=options.log_packets, detected_device=det)
|
||||||
connected_devices.append(dev)
|
connected_devices.append(dev)
|
||||||
|
|
||||||
if dev is None:
|
if dev is None:
|
||||||
|
@ -39,6 +39,7 @@ from tempfile import TemporaryFile
|
|||||||
from array import array
|
from array import array
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
from threading import RLock
|
||||||
|
|
||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
from calibre.devices.libusb import Error as USBError
|
from calibre.devices.libusb import Error as USBError
|
||||||
@ -52,6 +53,7 @@ from calibre.devices.usbms.deviceconfig import DeviceConfig
|
|||||||
# Protocol versions this driver has been tested with
|
# Protocol versions this driver has been tested with
|
||||||
KNOWN_USB_PROTOCOL_VERSIONS = [0x3030303030303130L]
|
KNOWN_USB_PROTOCOL_VERSIONS = [0x3030303030303130L]
|
||||||
|
|
||||||
|
lock = RLock()
|
||||||
|
|
||||||
class File(object):
|
class File(object):
|
||||||
"""
|
"""
|
||||||
@ -161,40 +163,44 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
"""
|
"""
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def run_session(*args, **kwargs):
|
def run_session(*args, **kwargs):
|
||||||
dev = args[0]
|
with lock:
|
||||||
res = None
|
dev = args[0]
|
||||||
try:
|
res = None
|
||||||
if not dev.handle:
|
try:
|
||||||
dev.open()
|
if not hasattr(dev, 'in_session'):
|
||||||
if not getattr(dev, 'in_session', False):
|
dev.reset()
|
||||||
dev.send_validated_command(BeginEndSession(end=False))
|
if not dev.handle:
|
||||||
dev.in_session = True
|
dev.open()
|
||||||
res = func(*args, **kwargs)
|
if not getattr(dev, 'in_session', False):
|
||||||
except ArgumentError:
|
dev.send_validated_command(BeginEndSession(end=False))
|
||||||
|
dev.in_session = True
|
||||||
|
res = func(*args, **kwargs)
|
||||||
|
except ArgumentError:
|
||||||
|
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
||||||
|
dev.send_validated_command(BeginEndSession(end=True))
|
||||||
|
dev.in_session = False
|
||||||
|
raise
|
||||||
|
except USBError, err:
|
||||||
|
if "No such device" in str(err):
|
||||||
|
raise DeviceError()
|
||||||
|
elif "Connection timed out" in str(err):
|
||||||
|
dev.close()
|
||||||
|
raise TimeoutError(func.__name__)
|
||||||
|
elif "Protocol error" in str(err):
|
||||||
|
dev.close()
|
||||||
|
raise ProtocolError("There was an unknown error in the"+\
|
||||||
|
" protocol. Contact " + __author__)
|
||||||
|
dev.close()
|
||||||
|
raise
|
||||||
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
||||||
dev.send_validated_command(BeginEndSession(end=True))
|
dev.send_validated_command(BeginEndSession(end=True))
|
||||||
dev.in_session = False
|
dev.in_session = False
|
||||||
raise
|
return res
|
||||||
except USBError, err:
|
|
||||||
if "No such device" in str(err):
|
|
||||||
raise DeviceError()
|
|
||||||
elif "Connection timed out" in str(err):
|
|
||||||
dev.close()
|
|
||||||
raise TimeoutError(func.__name__)
|
|
||||||
elif "Protocol error" in str(err):
|
|
||||||
dev.close()
|
|
||||||
raise ProtocolError("There was an unknown error in the"+\
|
|
||||||
" protocol. Contact " + __author__)
|
|
||||||
dev.close()
|
|
||||||
raise
|
|
||||||
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
|
||||||
dev.send_validated_command(BeginEndSession(end=True))
|
|
||||||
dev.in_session = False
|
|
||||||
return res
|
|
||||||
|
|
||||||
return run_session
|
return run_session
|
||||||
|
|
||||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||||
|
detected_device=None) :
|
||||||
"""
|
"""
|
||||||
@param key: The key to unlock the device
|
@param key: The key to unlock the device
|
||||||
@param log_packets: If true the packet stream to/from the device is logged
|
@param log_packets: If true the packet stream to/from the device is logged
|
||||||
@ -203,17 +209,18 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
If it is called with -1 that means that the
|
If it is called with -1 that means that the
|
||||||
task does not have any progress information
|
task does not have any progress information
|
||||||
"""
|
"""
|
||||||
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
with lock:
|
||||||
# Handle that is used to communicate with device. Setup in L{open}
|
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
||||||
self.handle = None
|
# Handle that is used to communicate with device. Setup in L{open}
|
||||||
self.in_session = False
|
self.handle = None
|
||||||
self.log_packets = log_packets
|
self.in_session = False
|
||||||
self.report_progress = report_progress
|
self.log_packets = log_packets
|
||||||
if len(key) > 8:
|
self.report_progress = report_progress
|
||||||
key = key[:8]
|
if len(key) > 8:
|
||||||
elif len(key) < 8:
|
key = key[:8]
|
||||||
key += ''.join(['\0' for i in xrange(8 - len(key))])
|
elif len(key) < 8:
|
||||||
self.key = key
|
key += ''.join(['\0' for i in xrange(8 - len(key))])
|
||||||
|
self.key = key
|
||||||
|
|
||||||
def reconnect(self):
|
def reconnect(self):
|
||||||
""" Only recreates the device node and deleted the connection handle """
|
""" Only recreates the device node and deleted the connection handle """
|
||||||
@ -243,64 +250,66 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
Also initialize the device.
|
Also initialize the device.
|
||||||
See the source code for the sequence of initialization commands.
|
See the source code for the sequence of initialization commands.
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, 'key'):
|
with lock:
|
||||||
self.key = '-1\0\0\0\0\0\0'
|
if not hasattr(self, 'key'):
|
||||||
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
self.reset()
|
||||||
if not self.device:
|
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
||||||
raise DeviceError()
|
if not self.device:
|
||||||
configs = self.device.configurations
|
raise DeviceError()
|
||||||
try:
|
configs = self.device.configurations
|
||||||
self.handle = self.device.open()
|
|
||||||
config = configs[0]
|
|
||||||
try:
|
try:
|
||||||
self.handle.set_configuration(configs[0])
|
self.handle = self.device.open()
|
||||||
except USBError:
|
config = configs[0]
|
||||||
self.handle.set_configuration(configs[1])
|
try:
|
||||||
config = configs[1]
|
self.handle.set_configuration(configs[0])
|
||||||
_id = config.interface.contents.altsetting.contents
|
except USBError:
|
||||||
ed1 = _id.endpoint[0]
|
self.handle.set_configuration(configs[1])
|
||||||
ed2 = _id.endpoint[1]
|
config = configs[1]
|
||||||
if ed1.EndpointAddress == self.BULK_IN_EP:
|
_id = config.interface.contents.altsetting.contents
|
||||||
red, wed = ed1, ed2
|
ed1 = _id.endpoint[0]
|
||||||
else:
|
ed2 = _id.endpoint[1]
|
||||||
red, wed = ed2, ed1
|
if ed1.EndpointAddress == self.BULK_IN_EP:
|
||||||
self.bulk_read_max_packet_size = red.MaxPacketSize
|
red, wed = ed1, ed2
|
||||||
self.bulk_write_max_packet_size = wed.MaxPacketSize
|
else:
|
||||||
self.handle.claim_interface(self.INTERFACE_ID)
|
red, wed = ed2, ed1
|
||||||
except USBError, err:
|
self.bulk_read_max_packet_size = red.MaxPacketSize
|
||||||
raise DeviceBusy(str(err))
|
self.bulk_write_max_packet_size = wed.MaxPacketSize
|
||||||
# Large timeout as device may still be initializing
|
self.handle.claim_interface(self.INTERFACE_ID)
|
||||||
res = self.send_validated_command(GetUSBProtocolVersion(), timeout=20000)
|
except USBError, err:
|
||||||
if res.code != 0:
|
raise DeviceBusy(str(err))
|
||||||
raise ProtocolError("Unable to get USB Protocol version.")
|
# Large timeout as device may still be initializing
|
||||||
version = self._bulk_read(24, data_type=USBProtocolVersion)[0].version
|
res = self.send_validated_command(GetUSBProtocolVersion(), timeout=20000)
|
||||||
if version not in KNOWN_USB_PROTOCOL_VERSIONS:
|
if res.code != 0:
|
||||||
print >> sys.stderr, "WARNING: Usb protocol version " + \
|
raise ProtocolError("Unable to get USB Protocol version.")
|
||||||
hex(version) + " is unknown"
|
version = self._bulk_read(24, data_type=USBProtocolVersion)[0].version
|
||||||
res = self.send_validated_command(SetBulkSize(\
|
if version not in KNOWN_USB_PROTOCOL_VERSIONS:
|
||||||
chunk_size = 512*self.bulk_read_max_packet_size, \
|
print >> sys.stderr, "WARNING: Usb protocol version " + \
|
||||||
unknown = 2))
|
hex(version) + " is unknown"
|
||||||
if res.code != 0:
|
res = self.send_validated_command(SetBulkSize(\
|
||||||
raise ProtocolError("Unable to set bulk size.")
|
chunk_size = 512*self.bulk_read_max_packet_size, \
|
||||||
res = self.send_validated_command(UnlockDevice(key=self.key))#0x312d))
|
unknown = 2))
|
||||||
if res.code != 0:
|
if res.code != 0:
|
||||||
raise DeviceLocked()
|
raise ProtocolError("Unable to set bulk size.")
|
||||||
res = self.send_validated_command(SetTime())
|
res = self.send_validated_command(UnlockDevice(key=self.key))#0x312d))
|
||||||
if res.code != 0:
|
if res.code != 0:
|
||||||
raise ProtocolError("Could not set time on device")
|
raise DeviceLocked()
|
||||||
|
res = self.send_validated_command(SetTime())
|
||||||
|
if res.code != 0:
|
||||||
|
raise ProtocolError("Could not set time on device")
|
||||||
|
|
||||||
def eject(self):
|
def eject(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
""" Release device interface """
|
""" Release device interface """
|
||||||
try:
|
with lock:
|
||||||
self.handle.reset()
|
try:
|
||||||
self.handle.release_interface(self.INTERFACE_ID)
|
self.handle.reset()
|
||||||
except Exception, err:
|
self.handle.release_interface(self.INTERFACE_ID)
|
||||||
print >> sys.stderr, err
|
except Exception, err:
|
||||||
self.handle, self.device = None, None
|
print >> sys.stderr, err
|
||||||
self.in_session = False
|
self.handle, self.device = None, None
|
||||||
|
self.in_session = False
|
||||||
|
|
||||||
def _send_command(self, command, response_type=Response, timeout=1000):
|
def _send_command(self, command, response_type=Response, timeout=1000):
|
||||||
"""
|
"""
|
||||||
@ -312,17 +321,18 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
@param timeout: The time to wait for a response from the
|
@param timeout: The time to wait for a response from the
|
||||||
device, in milliseconds. If there is no response, a L{usb.USBError} is raised.
|
device, in milliseconds. If there is no response, a L{usb.USBError} is raised.
|
||||||
"""
|
"""
|
||||||
if self.log_packets:
|
with lock:
|
||||||
self.log_packet(command, "Command")
|
if self.log_packets:
|
||||||
bytes_sent = self.handle.control_msg(0x40, 0x80, command)
|
self.log_packet(command, "Command")
|
||||||
if bytes_sent != len(command):
|
bytes_sent = self.handle.control_msg(0x40, 0x80, command)
|
||||||
raise ControlError(desc="Could not send control request to device\n"\
|
if bytes_sent != len(command):
|
||||||
+ str(command))
|
raise ControlError(desc="Could not send control request to device\n"\
|
||||||
response = response_type(self.handle.control_msg(0xc0, 0x81, \
|
+ str(command))
|
||||||
Response.SIZE, timeout=timeout))
|
response = response_type(self.handle.control_msg(0xc0, 0x81, \
|
||||||
if self.log_packets:
|
Response.SIZE, timeout=timeout))
|
||||||
self.log_packet(response, "Response")
|
if self.log_packets:
|
||||||
return response
|
self.log_packet(response, "Response")
|
||||||
|
return response
|
||||||
|
|
||||||
def send_validated_command(self, command, cnumber=None, \
|
def send_validated_command(self, command, cnumber=None, \
|
||||||
response_type=Response, timeout=1000):
|
response_type=Response, timeout=1000):
|
||||||
@ -346,42 +356,43 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
@param packet_size: Size of packets to be sent to device.
|
@param packet_size: Size of packets to be sent to device.
|
||||||
C{data} is broken up into packets to be sent to device.
|
C{data} is broken up into packets to be sent to device.
|
||||||
"""
|
"""
|
||||||
def bulk_write_packet(packet):
|
with lock:
|
||||||
self.handle.bulk_write(self.BULK_OUT_EP, packet)
|
def bulk_write_packet(packet):
|
||||||
if self.log_packets:
|
self.handle.bulk_write(self.BULK_OUT_EP, packet)
|
||||||
self.log_packet(Answer(packet), "Answer h->d")
|
if self.log_packets:
|
||||||
|
self.log_packet(Answer(packet), "Answer h->d")
|
||||||
|
|
||||||
bytes_left = len(data)
|
bytes_left = len(data)
|
||||||
if bytes_left + 16 <= packet_size:
|
if bytes_left + 16 <= packet_size:
|
||||||
packet_size = bytes_left +16
|
packet_size = bytes_left +16
|
||||||
first_packet = Answer(bytes_left+16)
|
first_packet = Answer(bytes_left+16)
|
||||||
first_packet[16:] = data
|
first_packet[16:] = data
|
||||||
first_packet.length = len(data)
|
first_packet.length = len(data)
|
||||||
else:
|
else:
|
||||||
first_packet = Answer(packet_size)
|
first_packet = Answer(packet_size)
|
||||||
first_packet[16:] = data[0:packet_size-16]
|
first_packet[16:] = data[0:packet_size-16]
|
||||||
first_packet.length = packet_size-16
|
first_packet.length = packet_size-16
|
||||||
first_packet.number = 0x10005
|
first_packet.number = 0x10005
|
||||||
bulk_write_packet(first_packet)
|
bulk_write_packet(first_packet)
|
||||||
pos = first_packet.length
|
pos = first_packet.length
|
||||||
bytes_left -= first_packet.length
|
bytes_left -= first_packet.length
|
||||||
while bytes_left > 0:
|
while bytes_left > 0:
|
||||||
endpos = pos + packet_size if pos + packet_size <= len(data) \
|
endpos = pos + packet_size if pos + packet_size <= len(data) \
|
||||||
else len(data)
|
else len(data)
|
||||||
bulk_write_packet(data[pos:endpos])
|
bulk_write_packet(data[pos:endpos])
|
||||||
bytes_left -= endpos - pos
|
bytes_left -= endpos - pos
|
||||||
pos = endpos
|
pos = endpos
|
||||||
res = Response(self.handle.control_msg(0xc0, 0x81, Response.SIZE, \
|
res = Response(self.handle.control_msg(0xc0, 0x81, Response.SIZE, \
|
||||||
timeout=5000))
|
timeout=5000))
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(res, "Response")
|
self.log_packet(res, "Response")
|
||||||
if res.rnumber != 0x10005 or res.code != 0:
|
if res.rnumber != 0x10005 or res.code != 0:
|
||||||
raise ProtocolError("Sending via Bulk Transfer failed with response:\n"\
|
raise ProtocolError("Sending via Bulk Transfer failed with response:\n"\
|
||||||
+str(res))
|
+str(res))
|
||||||
if res.data_size != len(data):
|
if res.data_size != len(data):
|
||||||
raise ProtocolError("Unable to transfer all data to device. "+\
|
raise ProtocolError("Unable to transfer all data to device. "+\
|
||||||
"Response packet:\n"\
|
"Response packet:\n"\
|
||||||
+str(res))
|
+str(res))
|
||||||
|
|
||||||
|
|
||||||
def _bulk_read(self, bytes, command_number=0x00, packet_size=0x1000, \
|
def _bulk_read(self, bytes, command_number=0x00, packet_size=0x1000, \
|
||||||
@ -394,31 +405,32 @@ class PRS500(DeviceConfig, DevicePlugin):
|
|||||||
@return: A list of packets read from the device.
|
@return: A list of packets read from the device.
|
||||||
Each packet is of type data_type
|
Each packet is of type data_type
|
||||||
"""
|
"""
|
||||||
msize = self.bulk_read_max_packet_size
|
with lock:
|
||||||
def bulk_read_packet(data_type=Answer, size=0x1000):
|
msize = self.bulk_read_max_packet_size
|
||||||
rsize = size
|
def bulk_read_packet(data_type=Answer, size=0x1000):
|
||||||
if size % msize:
|
rsize = size
|
||||||
rsize = size - size % msize + msize
|
if size % msize:
|
||||||
data = data_type(self.handle.bulk_read(self.BULK_IN_EP, rsize))
|
rsize = size - size % msize + msize
|
||||||
if self.log_packets:
|
data = data_type(self.handle.bulk_read(self.BULK_IN_EP, rsize))
|
||||||
self.log_packet(data, "Answer d->h")
|
if self.log_packets:
|
||||||
if len(data) != size:
|
self.log_packet(data, "Answer d->h")
|
||||||
raise ProtocolError("Unable to read " + str(size) + " bytes from "\
|
if len(data) != size:
|
||||||
"device. Read: " + str(len(data)) + " bytes")
|
raise ProtocolError("Unable to read " + str(size) + " bytes from "\
|
||||||
return data
|
"device. Read: " + str(len(data)) + " bytes")
|
||||||
|
return data
|
||||||
|
|
||||||
bytes_left = bytes
|
bytes_left = bytes
|
||||||
packets = []
|
packets = []
|
||||||
while bytes_left > 0:
|
while bytes_left > 0:
|
||||||
if packet_size > bytes_left:
|
if packet_size > bytes_left:
|
||||||
packet_size = bytes_left
|
packet_size = bytes_left
|
||||||
packet = bulk_read_packet(data_type=data_type, size=packet_size)
|
packet = bulk_read_packet(data_type=data_type, size=packet_size)
|
||||||
bytes_left -= len(packet)
|
bytes_left -= len(packet)
|
||||||
packets.append(packet)
|
packets.append(packet)
|
||||||
self.send_validated_command(\
|
self.send_validated_command(\
|
||||||
AcknowledgeBulkRead(packets[0].number), \
|
AcknowledgeBulkRead(packets[0].number), \
|
||||||
cnumber=command_number)
|
cnumber=command_number)
|
||||||
return packets
|
return packets
|
||||||
|
|
||||||
@safe
|
@safe
|
||||||
def get_device_information(self, end_session=True):
|
def get_device_information(self, end_session=True):
|
||||||
|
@ -22,9 +22,32 @@ from itertools import repeat
|
|||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
from calibre.devices.errors import DeviceError, FreeSpaceError
|
from calibre.devices.errors import DeviceError, FreeSpaceError
|
||||||
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
from calibre.devices.usbms.deviceconfig import DeviceConfig
|
||||||
from calibre import iswindows, islinux, isosx, __appname__
|
from calibre.constants import iswindows, islinux, isosx, __appname__, plugins
|
||||||
from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
|
from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
|
||||||
|
|
||||||
|
if isosx:
|
||||||
|
usbobserver, usbobserver_err = plugins['usbobserver']
|
||||||
|
|
||||||
|
class USBDevice:
|
||||||
|
|
||||||
|
def __init__(self, dev):
|
||||||
|
self.idVendor = dev[0]
|
||||||
|
self.idProduct = dev[1]
|
||||||
|
self.bcdDevice = dev[2]
|
||||||
|
self.manufacturer = dev[3]
|
||||||
|
self.product = dev[4]
|
||||||
|
self.serial = dev[5]
|
||||||
|
|
||||||
|
def match_serial(self, serial):
|
||||||
|
return self.serial and self.serial == serial
|
||||||
|
|
||||||
|
def match_numbers(self, vid, pid, bcd):
|
||||||
|
return self.idVendor == vid and self.idProduct == pid and self.bcdDevice == bcd
|
||||||
|
|
||||||
|
def match_strings(self, vid, pid, bcd, man, prod):
|
||||||
|
return self.match_numbers(vid, pid, bcd) and \
|
||||||
|
self.manufacturer == man and self.product == prod
|
||||||
|
|
||||||
class Device(DeviceConfig, DevicePlugin):
|
class Device(DeviceConfig, DevicePlugin):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -108,8 +131,13 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
FDI_LUNS = {'lun0':0, 'lun1':1, 'lun2':2}
|
FDI_LUNS = {'lun0':0, 'lun1':1, 'lun2':2}
|
||||||
FDI_BCD_TEMPLATE = '<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.device_revision_bcd" int="%(bcd)s">'
|
FDI_BCD_TEMPLATE = '<match key="@info.parent:@info.parent:@info.parent:@info.parent:usb.device_revision_bcd" int="%(bcd)s">'
|
||||||
|
|
||||||
def reset(self, key='-1', log_packets=False, report_progress=None) :
|
def reset(self, key='-1', log_packets=False, report_progress=None,
|
||||||
|
detected_device=None):
|
||||||
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
self._main_prefix = self._card_a_prefix = self._card_b_prefix = None
|
||||||
|
try:
|
||||||
|
self.detected_device = USBDevice(detected_device)
|
||||||
|
except: # On windows detected_device is None
|
||||||
|
self.detected_device = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_gui_name(cls):
|
def get_gui_name(cls):
|
||||||
@ -391,29 +419,82 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
raise
|
raise
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
def open_osx(self):
|
def _osx_bsd_names(self):
|
||||||
mount = self.osx_run_mount()
|
if usbobserver_err:
|
||||||
names = self.get_osx_mountpoints()
|
raise RuntimeError('Failed to load usbobserver: '+usbobserver_err)
|
||||||
dev_pat = r'/dev/%s(\w*)\s+on\s+([^\(]+)\s+'
|
drives = usbobserver.get_usb_drives()
|
||||||
if 'main' not in names.keys():
|
matches = []
|
||||||
raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%self.__class__.__name__)
|
d = self.detected_device
|
||||||
main_pat = dev_pat % names['main']
|
if d.serial:
|
||||||
main_match = re.search(main_pat, mount)
|
for path, vid, pid, bcd, ven, prod, serial in drives:
|
||||||
if main_match is None:
|
if d.match_serial(serial):
|
||||||
raise DeviceError(_('Unable to detect the %s mount point. Try rebooting.')%self.__class__.__name__)
|
matches.append(path)
|
||||||
self._main_prefix = main_match.group(2) + os.sep
|
if not matches:
|
||||||
card_a_pat = names['carda'] if 'carda' in names.keys() else None
|
if d.manufacturer and d.product:
|
||||||
card_b_pat = names['cardb'] if 'cardb' in names.keys() else None
|
for path, vid, pid, bcd, man, prod, serial in drives:
|
||||||
|
if d.match_strings(vid, pid, bcd, man, prod):
|
||||||
def get_card_prefix(pat):
|
matches.append(path)
|
||||||
if pat is not None:
|
|
||||||
pat = dev_pat % pat
|
|
||||||
return re.search(pat, mount).group(2) + os.sep
|
|
||||||
else:
|
else:
|
||||||
return None
|
for path, vid, pid, bcd, man, prod, serial in drives:
|
||||||
|
if d.match_numbers(vid, pid, bcd):
|
||||||
|
matches.append(path)
|
||||||
|
if not matches:
|
||||||
|
raise DeviceError(
|
||||||
|
'Could not detect BSD names for %s. Try rebooting.' % self.name)
|
||||||
|
|
||||||
self._card_a_prefix = get_card_prefix(card_a_pat)
|
pat = re.compile(r'(?P<m>\d+)([a-z]+(?P<p>\d+)){0,1}')
|
||||||
self._card_b_prefix = get_card_prefix(card_b_pat)
|
def nums(x):
|
||||||
|
m = pat.search(x)
|
||||||
|
if m is None:
|
||||||
|
return (10000, 0)
|
||||||
|
g = m.groupdict()
|
||||||
|
if g['p'] is None:
|
||||||
|
g['p'] = 0
|
||||||
|
return map(int, (g.get('m'), g.get('p')))
|
||||||
|
|
||||||
|
def dcmp(x, y):
|
||||||
|
x = x.rpartition('/')[-1]
|
||||||
|
y = y.rpartition('/')[-1]
|
||||||
|
x, y = nums(x), nums(y)
|
||||||
|
ans = cmp(x[0], y[0])
|
||||||
|
if ans == 0:
|
||||||
|
ans = cmp(x[1], y[1])
|
||||||
|
return ans
|
||||||
|
|
||||||
|
matches.sort(cmp=dcmp)
|
||||||
|
drives = {'main':matches[0]}
|
||||||
|
if len(matches) > 1:
|
||||||
|
drives['carda'] = matches[1]
|
||||||
|
if len(matches) > 2:
|
||||||
|
drives['cardb'] = matches[2]
|
||||||
|
|
||||||
|
return drives
|
||||||
|
|
||||||
|
def osx_bsd_names(self):
|
||||||
|
try:
|
||||||
|
return self._osx_bsd_names()
|
||||||
|
except:
|
||||||
|
time.sleep(2)
|
||||||
|
return self._osx_bsd_names()
|
||||||
|
|
||||||
|
def open_osx(self):
|
||||||
|
drives = self.osx_bsd_names()
|
||||||
|
bsd_drives = dict(**drives)
|
||||||
|
drives = self.osx_sort_names(drives)
|
||||||
|
mount_map = usbobserver.get_mounted_filesystems()
|
||||||
|
for k, v in drives.items():
|
||||||
|
drives[k] = mount_map.get(v, None)
|
||||||
|
if drives['main'] is None:
|
||||||
|
print bsd_drives, mount_map, drives
|
||||||
|
raise DeviceError(_('Unable to detect the %s mount point. Try rebooting.')%self.__class__.__name__)
|
||||||
|
self._main_prefix = drives['main']+os.sep
|
||||||
|
def get_card_prefix(c):
|
||||||
|
ans = drives.get(c, None)
|
||||||
|
if ans is not None:
|
||||||
|
ans += os.sep
|
||||||
|
return ans
|
||||||
|
self._card_a_prefix = get_card_prefix('carda')
|
||||||
|
self._card_b_prefix = get_card_prefix('cardb')
|
||||||
|
|
||||||
def find_device_nodes(self):
|
def find_device_nodes(self):
|
||||||
|
|
||||||
|
@ -33,10 +33,6 @@ class USBMS(CLI, Device):
|
|||||||
FORMATS = []
|
FORMATS = []
|
||||||
CAN_SET_METADATA = False
|
CAN_SET_METADATA = False
|
||||||
|
|
||||||
def reset(self, key='-1', log_packets=False, report_progress=None):
|
|
||||||
Device.reset(self, key=key, log_packets=log_packets,
|
|
||||||
report_progress=report_progress)
|
|
||||||
|
|
||||||
def get_device_information(self, end_session=True):
|
def get_device_information(self, end_session=True):
|
||||||
self.report_progress(1.0, _('Get device information...'))
|
self.report_progress(1.0, _('Get device information...'))
|
||||||
return (self.__class__.__name__, '', '', '')
|
return (self.__class__.__name__, '', '', '')
|
||||||
|
@ -24,112 +24,283 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <CoreFoundation/CFNumber.h>
|
||||||
#include <IOKit/usb/IOUSBLib.h>
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <mach/mach.h>
|
#include <IOKit/storage/IOMedia.h>
|
||||||
|
#include <IOKit/IOBSD.h>
|
||||||
|
#include <IOKit/usb/USBSpec.h>
|
||||||
|
|
||||||
CFStringRef USB_PROPS[3] = { CFSTR("USB Vendor Name"), CFSTR("USB Product Name"), CFSTR("USB Serial Number") };
|
#include <mach/mach.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <sys/ucred.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
#ifndef kUSBVendorString
|
||||||
|
#define kUSBVendorString "USB Vendor Name"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef kUSBProductString
|
||||||
|
#define kUSBProductString "USB Product Name"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef kUSBSerialNumberString
|
||||||
|
#define kUSBSerialNumberString "USB Serial Number"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUKE(x) Py_XDECREF(x); x = NULL;
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
get_iokit_string_property(io_service_t dev, int prop) {
|
usbobserver_get_iokit_string_property(io_service_t dev, CFStringRef prop) {
|
||||||
CFTypeRef PropRef;
|
CFTypeRef PropRef;
|
||||||
char buf[500];
|
char buf[500];
|
||||||
|
|
||||||
PropRef = IORegistryEntryCreateCFProperty(dev, USB_PROPS[prop], kCFAllocatorDefault, 0);
|
PropRef = IORegistryEntryCreateCFProperty(dev, prop, kCFAllocatorDefault, 0);
|
||||||
if (PropRef) {
|
if (PropRef) {
|
||||||
if(!CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8)) buf[0] = '\0';
|
if(!CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8)) buf[0] = '\0';
|
||||||
} else buf[0] = '\0';
|
CFRelease(PropRef);
|
||||||
|
} else buf[0] = '\0';
|
||||||
|
|
||||||
return PyUnicode_DecodeUTF8(buf, strlen(buf), "replace");
|
return PyUnicode_DecodeUTF8(buf, strlen(buf), "replace");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
usbobserver_get_iokit_number_property(io_service_t dev, CFStringRef prop) {
|
||||||
|
CFTypeRef PropRef;
|
||||||
|
long val = 0;
|
||||||
|
|
||||||
|
PropRef = IORegistryEntryCreateCFProperty(dev, prop, kCFAllocatorDefault, 0);
|
||||||
|
if (PropRef) {
|
||||||
|
CFNumberGetValue((CFNumberRef)PropRef, kCFNumberLongType, &val);
|
||||||
|
CFRelease(PropRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyLong_FromLong(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
|
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
|
||||||
|
|
||||||
CFMutableDictionaryRef matchingDict;
|
CFMutableDictionaryRef matchingDict;
|
||||||
kern_return_t kr;
|
kern_return_t kr;
|
||||||
|
PyObject *devices, *device;
|
||||||
|
io_service_t usbDevice;
|
||||||
|
PyObject *vendor, *product, *bcd;
|
||||||
|
PyObject *manufacturer, *productn, *serial;
|
||||||
|
|
||||||
//Set up matching dictionary for class IOUSBDevice and its subclasses
|
|
||||||
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
|
||||||
if (!matchingDict) {
|
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Couldn't create a USB matching dictionary");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_iterator_t iter;
|
|
||||||
IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
|
|
||||||
io_service_t usbDevice;
|
|
||||||
IOCFPlugInInterface **plugInInterface = NULL;
|
|
||||||
SInt32 score;
|
|
||||||
IOUSBDeviceInterface182 **dev = NULL;
|
|
||||||
UInt16 vendor, product, bcd;
|
|
||||||
PyObject *manufacturer, *productn, *serial;
|
|
||||||
|
|
||||||
PyObject *devices, *device;
|
//Set up matching dictionary for class IOUSBDevice and its subclasses
|
||||||
devices = PyList_New(0);
|
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
||||||
if (devices == NULL) {
|
if (!matchingDict) {
|
||||||
PyErr_NoMemory();
|
PyErr_SetString(PyExc_RuntimeError, "Couldn't create a USB matching dictionary");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
while ((usbDevice = IOIteratorNext(iter))) {
|
|
||||||
plugInInterface = NULL; dev = NULL;
|
|
||||||
//Create an intermediate plugin
|
|
||||||
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
|
|
||||||
if ((kIOReturnSuccess != kr) || !plugInInterface) {
|
|
||||||
printf("Unable to create a plug-in (%08x)\n", kr); continue;
|
|
||||||
}
|
|
||||||
//Now create the device interface
|
|
||||||
HRESULT result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&dev);
|
|
||||||
|
|
||||||
if (result || !dev) {
|
|
||||||
printf("Couldn't create a device interface (%08x)\n", (int) result);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kr = (*dev)->GetDeviceVendor(dev, &vendor);
|
io_iterator_t iter;
|
||||||
kr = (*dev)->GetDeviceProduct(dev, &product);
|
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
|
||||||
kr = (*dev)->GetDeviceReleaseNumber(dev, &bcd);
|
if (KERN_SUCCESS != kr) {
|
||||||
|
printf("IOServiceGetMatchingServices returned 0x%08x\n", kr);
|
||||||
manufacturer = get_iokit_string_property(usbDevice, 0);
|
PyErr_SetString(PyExc_RuntimeError, "Could not run IO Matching");
|
||||||
if (manufacturer == NULL) manufacturer = Py_None;
|
return NULL;
|
||||||
productn = get_iokit_string_property(usbDevice, 1);
|
|
||||||
if (productn == NULL) productn = Py_None;
|
|
||||||
serial = get_iokit_string_property(usbDevice, 2);
|
|
||||||
if (serial == NULL) serial = Py_None;
|
|
||||||
|
|
||||||
device = Py_BuildValue("(iiiNNN)", vendor, product, bcd, manufacturer, productn, serial);
|
|
||||||
if (device == NULL) {
|
|
||||||
IOObjectRelease(usbDevice);
|
|
||||||
(*plugInInterface)->Release(plugInInterface);
|
|
||||||
(*dev)->Release(dev);
|
|
||||||
Py_DECREF(devices);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (PyList_Append(devices, device) == -1) {
|
|
||||||
IOObjectRelease(usbDevice);
|
|
||||||
(*plugInInterface)->Release(plugInInterface);
|
|
||||||
(*dev)->Release(dev);
|
|
||||||
Py_DECREF(devices);
|
|
||||||
Py_DECREF(device);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IOObjectRelease(usbDevice);
|
devices = PyList_New(0);
|
||||||
(*plugInInterface)->Release(plugInInterface);
|
if (devices == NULL) {
|
||||||
(*dev)->Release(dev);
|
PyErr_NoMemory();
|
||||||
Py_DECREF(device);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while ((usbDevice = IOIteratorNext(iter))) {
|
||||||
|
|
||||||
|
vendor = usbobserver_get_iokit_number_property(usbDevice, CFSTR(kUSBVendorID));
|
||||||
|
product = usbobserver_get_iokit_number_property(usbDevice, CFSTR(kUSBProductID));
|
||||||
|
bcd = usbobserver_get_iokit_number_property(usbDevice, CFSTR(kUSBDeviceReleaseNumber));
|
||||||
|
manufacturer = usbobserver_get_iokit_string_property(usbDevice, CFSTR(kUSBVendorString));
|
||||||
|
productn = usbobserver_get_iokit_string_property(usbDevice, CFSTR(kUSBProductString));
|
||||||
|
serial = usbobserver_get_iokit_string_property(usbDevice, CFSTR(kUSBSerialNumberString));
|
||||||
|
if (usbDevice) IOObjectRelease(usbDevice);
|
||||||
|
|
||||||
|
if (vendor != NULL && product != NULL && bcd != NULL) {
|
||||||
|
|
||||||
|
if (manufacturer == NULL) { manufacturer = Py_None; Py_INCREF(Py_None); }
|
||||||
|
if (productn == NULL) { productn = Py_None; Py_INCREF(Py_None); }
|
||||||
|
if (serial == NULL) { serial = Py_None; Py_INCREF(Py_None); }
|
||||||
|
|
||||||
|
device = Py_BuildValue("(OOOOOO)", vendor, product, bcd, manufacturer, productn, serial);
|
||||||
|
if (device != NULL) {
|
||||||
|
PyList_Append(devices, device);
|
||||||
|
Py_DECREF(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NUKE(vendor); NUKE(product); NUKE(bcd); NUKE(manufacturer);
|
||||||
|
NUKE(productn); NUKE(serial);
|
||||||
|
}
|
||||||
|
|
||||||
return devices;
|
if (iter) IOObjectRelease(iter);
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
usbobserver_get_bsd_path(io_object_t dev) {
|
||||||
|
char cpath[ MAXPATHLEN ];
|
||||||
|
CFTypeRef PropRef;
|
||||||
|
size_t dev_path_length;
|
||||||
|
|
||||||
|
cpath[0] = '\0';
|
||||||
|
PropRef = IORegistryEntryCreateCFProperty(dev, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0);
|
||||||
|
if (!PropRef) return NULL;
|
||||||
|
strcpy(cpath, _PATH_DEV);
|
||||||
|
dev_path_length = strlen(cpath);
|
||||||
|
|
||||||
|
if (!CFStringGetCString(PropRef,
|
||||||
|
cpath + dev_path_length,
|
||||||
|
MAXPATHLEN - dev_path_length,
|
||||||
|
kCFStringEncodingUTF8)) return NULL;
|
||||||
|
|
||||||
|
return PyUnicode_DecodeUTF8(cpath, strlen(cpath), "replace");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
usbobserver_find_prop(io_registry_entry_t e, CFStringRef key, int is_string )
|
||||||
|
{
|
||||||
|
char buf[500]; long val = 0;
|
||||||
|
PyObject *ans;
|
||||||
|
IOOptionBits bits = kIORegistryIterateRecursively | kIORegistryIterateParents;
|
||||||
|
CFTypeRef PropRef = IORegistryEntrySearchCFProperty( e, kIOServicePlane, key, NULL, bits );
|
||||||
|
|
||||||
|
if (!PropRef) return NULL;
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
if(is_string) {
|
||||||
|
CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8);
|
||||||
|
ans = PyUnicode_DecodeUTF8(buf, strlen(buf), "replace");
|
||||||
|
} else {
|
||||||
|
CFNumberGetValue((CFNumberRef)PropRef, kCFNumberLongType, &val);
|
||||||
|
ans = PyLong_FromLong(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(PropRef);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
usbobserver_get_usb_drives(PyObject *self, PyObject *args) {
|
||||||
|
CFMutableDictionaryRef matchingDict;
|
||||||
|
kern_return_t kr = KERN_FAILURE;
|
||||||
|
io_iterator_t iter;
|
||||||
|
io_object_t next;
|
||||||
|
PyObject *ans = NULL, *bsd_path = NULL, *t = NULL, *vid, *pid, *bcd, *manufacturer, *product, *serial;
|
||||||
|
|
||||||
|
//Set up matching dictionary for class IOMedia and its subclasses
|
||||||
|
matchingDict = IOServiceMatching(kIOMediaClass);
|
||||||
|
if (!matchingDict) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Couldn't create a Media matching dictionary");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Only want writable and ejectable leaf nodes
|
||||||
|
CFDictionarySetValue(matchingDict, CFSTR(kIOMediaWritableKey), kCFBooleanTrue);
|
||||||
|
CFDictionarySetValue(matchingDict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue);
|
||||||
|
CFDictionarySetValue(matchingDict, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
|
||||||
|
|
||||||
|
ans = PyList_New(0);
|
||||||
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
|
|
||||||
|
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
|
||||||
|
if (KERN_SUCCESS != kr) {
|
||||||
|
printf("IOServiceGetMatchingServices returned 0x%08x\n", kr);
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Could not run IO Matching");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((next = IOIteratorNext(iter))) {
|
||||||
|
bsd_path = usbobserver_get_bsd_path(next);
|
||||||
|
vid = usbobserver_find_prop(next, CFSTR(kUSBVendorID), 0);
|
||||||
|
pid = usbobserver_find_prop(next, CFSTR(kUSBProductID), 0);
|
||||||
|
bcd = usbobserver_find_prop(next, CFSTR(kUSBDeviceReleaseNumber), 0);
|
||||||
|
manufacturer = usbobserver_find_prop(next, CFSTR(kUSBVendorString), 1);
|
||||||
|
product = usbobserver_find_prop(next, CFSTR(kUSBProductString), 1);
|
||||||
|
serial = usbobserver_find_prop(next, CFSTR(kUSBSerialNumberString), 1);
|
||||||
|
|
||||||
|
IOObjectRelease(next);
|
||||||
|
|
||||||
|
if (bsd_path != NULL && vid != NULL && pid != NULL && bcd != NULL) {
|
||||||
|
if (manufacturer == NULL) { manufacturer = Py_None; Py_INCREF(Py_None); }
|
||||||
|
if (product == NULL) { product = Py_None; Py_INCREF(Py_None); }
|
||||||
|
if (serial == NULL) { serial = Py_None; Py_INCREF(Py_None); }
|
||||||
|
|
||||||
|
t = Py_BuildValue("(OOOOOOO)", bsd_path, vid, pid, bcd, manufacturer, product, serial);
|
||||||
|
if (t != NULL) {
|
||||||
|
PyList_Append(ans, t);
|
||||||
|
Py_DECREF(t); t = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NUKE(bsd_path); NUKE(vid); NUKE(pid); NUKE(bcd);
|
||||||
|
NUKE(manufacturer); NUKE(product); NUKE(serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter) IOObjectRelease(iter);
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
usbobserver_get_mounted_filesystems(PyObject *self, PyObject *args) {
|
||||||
|
struct statfs *buf, t;
|
||||||
|
int num, i;
|
||||||
|
PyObject *ans, *key, *val;
|
||||||
|
|
||||||
|
num = getfsstat(NULL, 0, MNT_NOWAIT);
|
||||||
|
if (num == -1) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Initial call to getfsstat failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ans = PyDict_New();
|
||||||
|
if (ans == NULL) return PyErr_NoMemory();
|
||||||
|
|
||||||
|
buf = (struct statfs*)calloc(num, sizeof(struct statfs));
|
||||||
|
if (buf == NULL) return PyErr_NoMemory();
|
||||||
|
|
||||||
|
num = getfsstat(buf, num*sizeof(struct statfs), MNT_NOWAIT);
|
||||||
|
if (num == -1) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Call to getfsstat failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < num; i++) {
|
||||||
|
t = buf[i];
|
||||||
|
key = PyBytes_FromString(t.f_mntfromname);
|
||||||
|
val = PyBytes_FromString(t.f_mntonname);
|
||||||
|
if (key != NULL && val != NULL) {
|
||||||
|
PyDict_SetItem(ans, key, val);
|
||||||
|
}
|
||||||
|
NUKE(key); NUKE(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef usbobserver_methods[] = {
|
static PyMethodDef usbobserver_methods[] = {
|
||||||
{"get_usb_devices", usbobserver_get_usb_devices, METH_VARARGS,
|
{"get_usb_devices", usbobserver_get_usb_devices, METH_VARARGS,
|
||||||
"Get list of connected USB devices. Returns a list of tuples. Each tuple is of the form (vendor_id, product_id)."
|
"Get list of connected USB devices. Returns a list of tuples. Each tuple is of the form (vendor_id, product_id, bcd, manufacturer, product, serial number)."
|
||||||
},
|
},
|
||||||
|
{"get_usb_drives", usbobserver_get_usb_drives, METH_VARARGS,
|
||||||
|
"Get list of mounted drives. Returns a list of tuples, each of the form (name, bsd_path)."
|
||||||
|
},
|
||||||
|
{"get_mounted_filesystems", usbobserver_get_mounted_filesystems, METH_VARARGS,
|
||||||
|
"Get mapping of mounted filesystems. Mapping is from BSD name to mount point."
|
||||||
|
},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import subprocess
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from calibre.ebooks import ConversionError, DRMError
|
from calibre.ebooks import ConversionError, DRMError
|
||||||
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
from calibre import isosx, iswindows, islinux
|
from calibre import isosx, iswindows, islinux
|
||||||
from calibre import CurrentDir
|
from calibre import CurrentDir
|
||||||
|
|
||||||
@ -45,8 +46,10 @@ def pdftohtml(output_dir, pdf_path, no_images):
|
|||||||
if no_images:
|
if no_images:
|
||||||
cmd.append('-i')
|
cmd.append('-i')
|
||||||
|
|
||||||
|
logf = PersistentTemporaryFile('pdftohtml_log')
|
||||||
try:
|
try:
|
||||||
p = popen(cmd, stderr=subprocess.PIPE)
|
p = popen(cmd, stderr=logf._fd, stdout=logf._fd,
|
||||||
|
stdin=subprocess.PIPE)
|
||||||
except OSError, err:
|
except OSError, err:
|
||||||
if err.errno == 2:
|
if err.errno == 2:
|
||||||
raise ConversionError(_('Could not find pdftohtml, check it is in your PATH'))
|
raise ConversionError(_('Could not find pdftohtml, check it is in your PATH'))
|
||||||
@ -62,10 +65,13 @@ def pdftohtml(output_dir, pdf_path, no_images):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
logf.flush()
|
||||||
|
logf.close()
|
||||||
|
out = open(logf.name, 'rb').read()
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
err = p.stderr.read()
|
raise ConversionError(out)
|
||||||
raise ConversionError(err)
|
print "pdftohtml log:"
|
||||||
|
print out
|
||||||
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
if not os.path.exists(index) or os.stat(index).st_size < 100:
|
||||||
raise DRMError()
|
raise DRMError()
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ class DeviceManager(Thread):
|
|||||||
import pythoncom
|
import pythoncom
|
||||||
pythoncom.CoInitialize()
|
pythoncom.CoInitialize()
|
||||||
try:
|
try:
|
||||||
for dev in connected_devices:
|
for dev, detected_device in connected_devices:
|
||||||
dev.reset()
|
dev.reset(detected_device=detected_device)
|
||||||
try:
|
try:
|
||||||
dev.open()
|
dev.open()
|
||||||
except:
|
except:
|
||||||
@ -116,10 +116,10 @@ class DeviceManager(Thread):
|
|||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
connected_devices = []
|
connected_devices = []
|
||||||
for device in self.devices:
|
for device in self.devices:
|
||||||
connected = self.scanner.is_device_connected(device[0])
|
connected, detected_device = self.scanner.is_device_connected(device[0])
|
||||||
if connected and not device[1] and not device[2]:
|
if connected and not device[1] and not device[2]:
|
||||||
# If connected and not showing in GUI and not ejected
|
# If connected and not showing in GUI and not ejected
|
||||||
connected_devices.append(device[0])
|
connected_devices.append((device[0], detected_device))
|
||||||
device[1] = True
|
device[1] = True
|
||||||
elif not connected and device[1]:
|
elif not connected and device[1]:
|
||||||
# Disconnected but showing in GUI
|
# Disconnected but showing in GUI
|
||||||
|
@ -92,6 +92,12 @@ class Sony505(Sony500):
|
|||||||
name = 'SONY Reader Pocket/Touch Edition'
|
name = 'SONY Reader Pocket/Touch Edition'
|
||||||
id = 'prs505'
|
id = 'prs505'
|
||||||
|
|
||||||
|
class Sony900(Sony505):
|
||||||
|
|
||||||
|
name = 'SONY Reader Daily Edition'
|
||||||
|
id = 'prs900'
|
||||||
|
output_profile = 'sony900'
|
||||||
|
|
||||||
class Nook(Sony505):
|
class Nook(Sony505):
|
||||||
id = 'nook'
|
id = 'nook'
|
||||||
name = 'Nook'
|
name = 'Nook'
|
||||||
|
@ -81,7 +81,7 @@ Device Integration
|
|||||||
|
|
||||||
What devices does |app| support?
|
What devices does |app| support?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
At the moment |app| has full support for the SONY PRS 300/500/505/600/700, Barnes & Noble Nook, Cybook Gen 3/Opus, Amazon Kindle 1/2/DX, Netronix EB600, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Foxit eSlick, PocketBook 360, Italica, various Android phones and the iPhone. In addition, using the :guilabel:`Save to disk` function you can use it with any ebook reader that exports itself as a USB disk.
|
At the moment |app| has full support for the SONY PRS 300/500/505/600/700/900, Barnes & Noble Nook, Cybook Gen 3/Opus, Amazon Kindle 1/2/DX, Netronix EB600, Ectaco Jetbook, BeBook/BeBook Mini, Irex Illiad/DR1000, Foxit eSlick, PocketBook 360, Italica, eClicto, Iriver Story, Airis dBook, various Android phones and the iPhone. In addition, using the :guilabel:`Save to disk` function you can use it with any ebook reader that exports itself as a USB disk.
|
||||||
|
|
||||||
How can I help get my device supported in |app|?
|
How can I help get my device supported in |app|?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -7,14 +7,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre\n"
|
"Project-Id-Version: calibre\n"
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
|
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
|
||||||
"PO-Revision-Date: 2009-12-25 19:11+0000\n"
|
"PO-Revision-Date: 2009-12-26 16:45+0000\n"
|
||||||
"Last-Translator: Kovid Goyal <Unknown>\n"
|
"Last-Translator: Kovid Goyal <Unknown>\n"
|
||||||
"Language-Team: Arabic <ar@li.org>\n"
|
"Language-Team: Arabic <ar@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2009-12-26 04:31+0000\n"
|
"X-Launchpad-Export-Date: 2009-12-27 04:31+0000\n"
|
||||||
"X-Generator: Launchpad (build Unknown)\n"
|
"X-Generator: Launchpad (build Unknown)\n"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:41
|
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:41
|
||||||
@ -64,8 +64,8 @@ msgstr "لا يفعل شيءً"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:593
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:783
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:784
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
||||||
@ -132,7 +132,7 @@ msgstr "لا يفعل شيءً"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:107
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -7361,10 +7361,18 @@ msgid "English (TH)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
||||||
msgid "Dutch (NL)"
|
msgid "English (CY)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
||||||
|
msgid "German (AT)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
||||||
|
msgid "Dutch (NL)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.6.30\n"
|
"Project-Id-Version: calibre 0.6.31\n"
|
||||||
"POT-Creation-Date: 2009-12-26 08:40+MST\n"
|
"POT-Creation-Date: 2009-12-27 16:02+MST\n"
|
||||||
"PO-Revision-Date: 2009-12-26 08:40+MST\n"
|
"PO-Revision-Date: 2009-12-27 16:02+MST\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: LANGUAGE\n"
|
"Language-Team: LANGUAGE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -22,11 +22,13 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:44
|
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:44
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:94
|
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:94
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:54
|
#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:54
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:70
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:71
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:58
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:58
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:199
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:199
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:789
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:870
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:792
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:873
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:206
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:202
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:414
|
#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:414
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:67
|
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:67
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:69
|
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:69
|
||||||
@ -236,72 +238,90 @@ msgid "This profile tries to provide sane defaults and is useful if you know not
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:56
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:56
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:208
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:235
|
||||||
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc."
|
msgid "This profile is intended for the SONY PRS line. The 500/505/600/700 etc."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:69
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:68
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:243
|
msgid "This profile is intended for the SONY PRS 300."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:77
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:257
|
||||||
|
msgid "This profile is intended for the SONY PRS-900."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:85
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:287
|
||||||
msgid "This profile is intended for the Microsoft Reader."
|
msgid "This profile is intended for the Microsoft Reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:80
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:96
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:254
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:298
|
||||||
msgid "This profile is intended for the Mobipocket books."
|
msgid "This profile is intended for the Mobipocket books."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:93
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:109
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:267
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:311
|
||||||
msgid "This profile is intended for the Hanlin V3/V5 and its clones."
|
msgid "This profile is intended for the Hanlin V3 and its clones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:105
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:279
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:323
|
||||||
|
msgid "This profile is intended for the Hanlin V5 and its clones."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:131
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:331
|
||||||
msgid "This profile is intended for the Cybook G3."
|
msgid "This profile is intended for the Cybook G3."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:118
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:144
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:292
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:344
|
||||||
msgid "This profile is intended for the Cybook Opus."
|
msgid "This profile is intended for the Cybook Opus."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:130
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:156
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:303
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:355
|
||||||
msgid "This profile is intended for the Amazon Kindle."
|
msgid "This profile is intended for the Amazon Kindle."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:142
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:168
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:336
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:388
|
||||||
msgid "This profile is intended for the Irex Illiad."
|
msgid "This profile is intended for the Irex Illiad."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:154
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:180
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:349
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:401
|
||||||
msgid "This profile is intended for the IRex Digital Reader 1000."
|
msgid "This profile is intended for the IRex Digital Reader 1000."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:168
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:194
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:363
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:415
|
||||||
msgid "This profile is intended for the B&N Nook."
|
msgid "This profile is intended for the B&N Nook."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:186
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:213
|
||||||
msgid "Output profile"
|
msgid "Output profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:190
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:217
|
||||||
msgid "This profile tries to provide sane defaults and is useful if you want to produce a document intended to be read at a computer or on a range of devices."
|
msgid "This profile tries to provide sane defaults and is useful if you want to produce a document intended to be read at a computer or on a range of devices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:220
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:248
|
||||||
|
msgid "This profile is intended for the SONY PRS-300."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:266
|
||||||
msgid "This profile is intended for the 5-inch JetBook."
|
msgid "This profile is intended for the 5-inch JetBook."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:231
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:275
|
||||||
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics."
|
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:320
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:372
|
||||||
msgid "This profile is intended for the Amazon Kindle DX."
|
msgid "This profile is intended for the Amazon Kindle DX."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -369,33 +389,21 @@ msgstr ""
|
|||||||
msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used"
|
msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/bebook/driver.py:19
|
|
||||||
msgid "Communicate with the BeBook eBook reader."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/bebook/driver.py:95
|
|
||||||
msgid "Communicate with the BeBook Mini eBook reader."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:12
|
#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:12
|
||||||
msgid "Communicate with the Blackberry smart phone."
|
msgid "Communicate with the Blackberry smart phone."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:13
|
#: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:13
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/nuut2/driver.py:18
|
#: /home/kovid/work/calibre/src/calibre/devices/nuut2/driver.py:18
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:88
|
#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:90
|
||||||
msgid "Kovid Goyal"
|
msgid "Kovid Goyal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/boox/driver.py:17
|
|
||||||
msgid "Communicate with the BOOX eBook reader."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:21
|
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:21
|
||||||
msgid "Communicate with the Cybook Gen 3 eBook reader."
|
msgid "Communicate with the Cybook Gen 3 eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:68
|
#: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:67
|
||||||
msgid "Communicate with the Cybook Opus eBook reader."
|
msgid "Communicate with the Cybook Opus eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -407,6 +415,18 @@ msgstr ""
|
|||||||
msgid "Communicate with the ESlick eBook reader."
|
msgid "Communicate with the ESlick eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:19
|
||||||
|
msgid "Communicate with Hanlin V3 eBook readers."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:95
|
||||||
|
msgid "Communicate with Hanlin V5 eBook readers."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/hanlin/driver.py:113
|
||||||
|
msgid "Communicate with the BOOX eBook reader."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/iliad/driver.py:16
|
#: /home/kovid/work/calibre/src/calibre/devices/iliad/driver.py:16
|
||||||
msgid "Communicate with the IRex Iliad eBook reader."
|
msgid "Communicate with the IRex Iliad eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -437,8 +457,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:78
|
#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:78
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:134
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:134
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:136
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:136
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:120
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:116
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:122
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:118
|
||||||
msgid "Transferring books to device..."
|
msgid "Transferring books to device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -474,7 +494,7 @@ msgstr ""
|
|||||||
msgid "Communicate with the Nuut2 eBook reader."
|
msgid "Communicate with the Nuut2 eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:87
|
#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:89
|
||||||
msgid "Communicate with the Sony PRS-500 eBook reader."
|
msgid "Communicate with the Sony PRS-500 eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -483,12 +503,12 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:100
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:100
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:103
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:103
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:114
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:114
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:49
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:52
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:48
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:55
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:75
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:71
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:85
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:81
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:94
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:90
|
||||||
msgid "Getting list of books on device..."
|
msgid "Getting list of books on device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -498,64 +518,63 @@ msgstr ""
|
|||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:167
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:167
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:174
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:174
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:148
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:163
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:159
|
||||||
msgid "Removing books from device..."
|
msgid "Removing books from device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:202
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:202
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:178
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:174
|
||||||
msgid "Sending metadata to device..."
|
msgid "Sending metadata to device..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:208
|
#: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:208
|
||||||
msgid "Communicate with the Sony PRS-600/700 eBook reader."
|
msgid "Communicate with the Sony PRS-600/700/900 eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:308
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:336
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:399
|
|
||||||
msgid "Unable to detect the %s disk drive. Try rebooting."
|
msgid "Unable to detect the %s disk drive. Try rebooting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:403
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:489
|
||||||
msgid "Unable to detect the %s mount point. Try rebooting."
|
msgid "Unable to detect the %s mount point. Try rebooting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:470
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:551
|
||||||
msgid "Unable to detect the %s disk drive."
|
msgid "Unable to detect the %s disk drive."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:563
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:644
|
||||||
msgid "Could not find mount helper: %s."
|
msgid "Could not find mount helper: %s."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:575
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:656
|
||||||
msgid "Unable to detect the %s disk drive. Your kernel is probably exporting a deprecated version of SYSFS."
|
msgid "Unable to detect the %s disk drive. Your kernel is probably exporting a deprecated version of SYSFS."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:583
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:664
|
||||||
msgid "Unable to mount main memory (Error code: %d)"
|
msgid "Unable to mount main memory (Error code: %d)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:720
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:801
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:722
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:803
|
||||||
msgid "The reader has no storage card in this slot."
|
msgid "The reader has no storage card in this slot."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:724
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:805
|
||||||
msgid "Selected slot: %s is not supported."
|
msgid "Selected slot: %s is not supported."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:757
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:838
|
||||||
msgid "There is insufficient free space in main memory"
|
msgid "There is insufficient free space in main memory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:759
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:840
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:761
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:842
|
||||||
msgid "There is insufficient free space on the storage card"
|
msgid "There is insufficient free space on the storage card"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:772
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:853
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:232
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:232
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:125
|
#: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:125
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1065
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1065
|
||||||
@ -594,17 +613,17 @@ msgstr ""
|
|||||||
msgid "Communicate with an eBook reader."
|
msgid "Communicate with an eBook reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:41
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:37
|
||||||
msgid "Get device information..."
|
msgid "Get device information..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:136
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:132
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:140
|
||||||
msgid "Adding books to device metadata listing..."
|
msgid "Adding books to device metadata listing..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:167
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:163
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:172
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:168
|
||||||
msgid "Removing books from device metadata listing..."
|
msgid "Removing books from device metadata listing..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -1902,7 +1921,7 @@ msgstr ""
|
|||||||
msgid "The orientation of the page. Default is portrait. Choices are %s"
|
msgid "The orientation of the page. Default is portrait. Choices are %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/pdftohtml.py:52
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/pdftohtml.py:55
|
||||||
msgid "Could not find pdftohtml, check it is in your PATH"
|
msgid "Could not find pdftohtml, check it is in your PATH"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2048,7 +2067,7 @@ msgid "Limit max simultaneous jobs to number of CPUs"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:127
|
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:127
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:404
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:410
|
||||||
msgid "Copied"
|
msgid "Copied"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3459,7 +3478,7 @@ msgid "Failed to start content server"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:698
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:698
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:514
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:520
|
||||||
msgid "Select location for books"
|
msgid "Select location for books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5354,7 +5373,7 @@ msgid "Bad database location"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:471
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:471
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:522
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:528
|
||||||
msgid "Calibre Library"
|
msgid "Calibre Library"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -6119,40 +6138,40 @@ msgstr ""
|
|||||||
msgid "Title Case"
|
msgid "Title Case"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:295
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:301
|
||||||
msgid "If you use the WordPlayer e-book app on your Android phone, you can access your calibre book collection directly on the device. To do this you have to turn on the content server."
|
msgid "If you use the WordPlayer e-book app on your Android phone, you can access your calibre book collection directly on the device. To do this you have to turn on the content server."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:299
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:305
|
||||||
msgid "Remember to leave calibre running as the server only runs as long as calibre is running."
|
msgid "Remember to leave calibre running as the server only runs as long as calibre is running."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:301
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:307
|
||||||
msgid "You have to add the URL http://myhostname:8080 as your calibre library in WordPlayer. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on."
|
msgid "You have to add the URL http://myhostname:8080 as your calibre library in WordPlayer. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:378
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:384
|
||||||
msgid "Moving library..."
|
msgid "Moving library..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:394
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:400
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:395
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:401
|
||||||
msgid "Failed to move library"
|
msgid "Failed to move library"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:449
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:455
|
||||||
msgid "Invalid database"
|
msgid "Invalid database"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:450
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:456
|
||||||
msgid "<p>An invalid library already exists at %s, delete it before trying to move the existing library.<br>Error: %s"
|
msgid "<p>An invalid library already exists at %s, delete it before trying to move the existing library.<br>Error: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:461
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:467
|
||||||
msgid "Could not move library"
|
msgid "Could not move library"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:589
|
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:595
|
||||||
msgid "welcome wizard"
|
msgid "welcome wizard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -6970,50 +6989,50 @@ msgstr ""
|
|||||||
msgid "Custom"
|
msgid "Custom"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:455
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:459
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog URL\n"
|
"%prog URL\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Where URL is for example http://google.com"
|
"Where URL is for example http://google.com"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:458
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:462
|
||||||
msgid "Base directory into which URL is saved. Default is %default"
|
msgid "Base directory into which URL is saved. Default is %default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:461
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:465
|
||||||
msgid "Timeout in seconds to wait for a response from the server. Default: %default s"
|
msgid "Timeout in seconds to wait for a response from the server. Default: %default s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:464
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:468
|
||||||
msgid "Maximum number of levels to recurse i.e. depth of links to follow. Default %default"
|
msgid "Maximum number of levels to recurse i.e. depth of links to follow. Default %default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:467
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:471
|
||||||
msgid "The maximum number of files to download. This only applies to files from <a href> tags. Default is %default"
|
msgid "The maximum number of files to download. This only applies to files from <a href> tags. Default is %default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:469
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:473
|
||||||
msgid "Minimum interval in seconds between consecutive fetches. Default is %default s"
|
msgid "Minimum interval in seconds between consecutive fetches. Default is %default s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:471
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:475
|
||||||
msgid "The character encoding for the websites you are trying to download. The default is to try and guess the encoding."
|
msgid "The character encoding for the websites you are trying to download. The default is to try and guess the encoding."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:473
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:477
|
||||||
msgid "Only links that match this regular expression will be followed. This option can be specified multiple times, in which case as long as a link matches any one regexp, it will be followed. By default all links are followed."
|
msgid "Only links that match this regular expression will be followed. This option can be specified multiple times, in which case as long as a link matches any one regexp, it will be followed. By default all links are followed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:475
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:479
|
||||||
msgid "Any link that matches this regular expression will be ignored. This option can be specified multiple times, in which case as long as any regexp matches a link, it will be ignored.By default, no links are ignored. If both --filter-regexp and --match-regexp are specified, then --filter-regexp is applied first."
|
msgid "Any link that matches this regular expression will be ignored. This option can be specified multiple times, in which case as long as any regexp matches a link, it will be ignored.By default, no links are ignored. If both --filter-regexp and --match-regexp are specified, then --filter-regexp is applied first."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:477
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:481
|
||||||
msgid "Do not download CSS stylesheets."
|
msgid "Do not download CSS stylesheets."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:478
|
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:482
|
||||||
msgid "Show detailed output information. Useful for debugging"
|
msgid "Show detailed output information. Useful for debugging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -7,14 +7,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: de\n"
|
"Project-Id-Version: de\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
|
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
|
||||||
"PO-Revision-Date: 2009-12-25 21:08+0000\n"
|
"PO-Revision-Date: 2009-12-26 20:24+0000\n"
|
||||||
"Last-Translator: S. Dorscht <Unknown>\n"
|
"Last-Translator: S. Dorscht <Unknown>\n"
|
||||||
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
|
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2009-12-26 04:32+0000\n"
|
"X-Launchpad-Export-Date: 2009-12-27 04:31+0000\n"
|
||||||
"X-Generator: Launchpad (build Unknown)\n"
|
"X-Generator: Launchpad (build Unknown)\n"
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
|
||||||
@ -65,8 +65,8 @@ msgstr "Macht absolut gar nichts"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:593
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:783
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:784
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
||||||
@ -133,7 +133,7 @@ msgstr "Macht absolut gar nichts"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:107
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -8227,10 +8227,18 @@ msgid "English (TH)"
|
|||||||
msgstr "Englisch (TH)"
|
msgstr "Englisch (TH)"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
||||||
|
msgid "English (CY)"
|
||||||
|
msgstr "Englisch (CY)"
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
||||||
|
msgid "German (AT)"
|
||||||
|
msgstr "Deutsch (AT)"
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
||||||
msgid "Dutch (NL)"
|
msgid "Dutch (NL)"
|
||||||
msgstr "Holländisch (NL)"
|
msgstr "Holländisch (NL)"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr "Holländisch (BE)"
|
msgstr "Holländisch (BE)"
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: es\n"
|
"Project-Id-Version: es\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
|
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
|
||||||
"PO-Revision-Date: 2009-12-26 01:25+0000\n"
|
"PO-Revision-Date: 2009-12-26 16:48+0000\n"
|
||||||
"Last-Translator: mosteo <alejandro@mosteo.com>\n"
|
"Last-Translator: mosteo <alejandro@mosteo.com>\n"
|
||||||
"Language-Team: Spanish\n"
|
"Language-Team: Spanish\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2009-12-26 04:33+0000\n"
|
"X-Launchpad-Export-Date: 2009-12-27 04:32+0000\n"
|
||||||
"X-Generator: Launchpad (build Unknown)\n"
|
"X-Generator: Launchpad (build Unknown)\n"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:41
|
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:41
|
||||||
@ -67,8 +67,8 @@ msgstr "No hacer nada en absoluto"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:593
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:783
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:784
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
||||||
@ -135,7 +135,7 @@ msgstr "No hacer nada en absoluto"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:107
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -8181,10 +8181,18 @@ msgid "English (TH)"
|
|||||||
msgstr "Inglés (TH)"
|
msgstr "Inglés (TH)"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
||||||
|
msgid "English (CY)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
||||||
|
msgid "German (AT)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
||||||
msgid "Dutch (NL)"
|
msgid "Dutch (NL)"
|
||||||
msgstr "Neerlandés (NL)"
|
msgstr "Neerlandés (NL)"
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr "Neerlandés (BE)"
|
msgstr "Neerlandés (BE)"
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,14 +7,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre\n"
|
"Project-Id-Version: calibre\n"
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
|
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
|
||||||
"PO-Revision-Date: 2009-12-25 19:14+0000\n"
|
"PO-Revision-Date: 2009-12-26 16:50+0000\n"
|
||||||
"Last-Translator: Kovid Goyal <Unknown>\n"
|
"Last-Translator: Kovid Goyal <Unknown>\n"
|
||||||
"Language-Team: Latvian <ivars_a@inbox.lv>\n"
|
"Language-Team: Latvian <ivars_a@inbox.lv>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2009-12-26 04:32+0000\n"
|
"X-Launchpad-Export-Date: 2009-12-27 04:31+0000\n"
|
||||||
"X-Generator: Launchpad (build Unknown)\n"
|
"X-Generator: Launchpad (build Unknown)\n"
|
||||||
"X-Poedit-Country: LATVIA\n"
|
"X-Poedit-Country: LATVIA\n"
|
||||||
"X-Poedit-Language: Latvian\n"
|
"X-Poedit-Language: Latvian\n"
|
||||||
@ -66,8 +66,8 @@ msgstr "Pilnīgi neko nedara"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:593
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:783
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:784
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
||||||
@ -134,7 +134,7 @@ msgstr "Pilnīgi neko nedara"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:107
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -7354,10 +7354,18 @@ msgid "English (TH)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
||||||
msgid "Dutch (NL)"
|
msgid "English (CY)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
||||||
|
msgid "German (AT)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
||||||
|
msgid "Dutch (NL)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.4.55\n"
|
"Project-Id-Version: calibre 0.4.55\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
|
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
|
||||||
"PO-Revision-Date: 2009-12-25 19:27+0000\n"
|
"PO-Revision-Date: 2009-12-26 16:54+0000\n"
|
||||||
"Last-Translator: Kovid Goyal <Unknown>\n"
|
"Last-Translator: Kovid Goyal <Unknown>\n"
|
||||||
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
|
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2009-12-26 04:32+0000\n"
|
"X-Launchpad-Export-Date: 2009-12-27 04:31+0000\n"
|
||||||
"X-Generator: Launchpad (build Unknown)\n"
|
"X-Generator: Launchpad (build Unknown)\n"
|
||||||
"X-Poedit-Country: RUSSIAN FEDERATION\n"
|
"X-Poedit-Country: RUSSIAN FEDERATION\n"
|
||||||
"X-Poedit-Language: Russian\n"
|
"X-Poedit-Language: Russian\n"
|
||||||
@ -68,8 +68,8 @@ msgstr "Ничего не делает"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:79
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:121
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:155
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:593
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:783
|
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:784
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
#: /home/kovid/work/calibre/src/calibre/ebooks/odt/input.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:896
|
||||||
@ -136,7 +136,7 @@ msgstr "Ничего не делает"
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:645
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:717
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:764
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:107
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -7760,10 +7760,18 @@ msgid "English (TH)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
|
||||||
msgid "Dutch (NL)"
|
msgid "English (CY)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:104
|
||||||
|
msgid "German (AT)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:105
|
||||||
|
msgid "Dutch (NL)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
7541
src/calibre/translations/sq.po
Normal file
7541
src/calibre/translations/sq.po
Normal file
File diff suppressed because it is too large
Load Diff
@ -190,10 +190,14 @@ class RecursiveFetcher(object):
|
|||||||
time.sleep(delta)
|
time.sleep(delta)
|
||||||
if isinstance(url, unicode):
|
if isinstance(url, unicode):
|
||||||
url = url.encode('utf-8')
|
url = url.encode('utf-8')
|
||||||
purl = list(urlparse.urlparse(url))
|
# Not sure is this is really needed as I think mechanize
|
||||||
for i in range(2, 6):
|
# handles quoting automatically, but leaving it in
|
||||||
purl[i] = quote(purl[i])
|
# in case it breaks something
|
||||||
url = urlparse.urlunparse(purl)
|
if re.search(r'\s+|,', url) is not None:
|
||||||
|
purl = list(urlparse.urlparse(url))
|
||||||
|
for i in range(2, 6):
|
||||||
|
purl[i] = quote(purl[i])
|
||||||
|
url = urlparse.urlunparse(purl)
|
||||||
try:
|
try:
|
||||||
open_func = getattr(self.browser, 'open_novisit', self.browser.open)
|
open_func = getattr(self.browser, 'open_novisit', self.browser.open)
|
||||||
with closing(open_func(url, timeout=self.timeout)) as f:
|
with closing(open_func(url, timeout=self.timeout)) as f:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user