Sync to trunk.

This commit is contained in:
John Schember 2009-12-27 21:22:28 -05:00
commit b61f5fcd3b
28 changed files with 9545 additions and 1022 deletions

View File

@ -4,6 +4,41 @@
# for important features/bug fixes.
# 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
date: 2009-12-26

View 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

View 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')]

View File

@ -72,7 +72,7 @@ class Translations(POT):
if os.path.exists(pycountry):
iso639 = self.j(pycountry, 'iso639.mo')
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')
shutil.copy2(iso639, dest)
else:

View File

@ -2,7 +2,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = 'calibre'
__version__ = '0.6.30'
__version__ = '0.6.31'
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
import re
@ -24,6 +24,7 @@ isosx = 'darwin' in sys.platform.lower()
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
islinux = not(iswindows or isosx)
isfrozen = hasattr(sys, 'frozen')
isunix = isosx or islinux
try:
preferred_encoding = locale.getpreferredencoding()

View File

@ -257,6 +257,7 @@ class SonyReader900Output(SonyReaderOutput):
description = _('This profile is intended for the SONY PRS-900.')
screen_size = (600, 999)
comic_screen_size = screen_size
class JetBook5Output(OutputProfile):

View File

@ -62,7 +62,7 @@ def migrate(old, new):
def debug_device_driver():
from calibre.devices import debug
print debug()
debug(ioreg_to_tmp=True, buf=sys.stdout)
if iswindows:
raw_input('Press Enter to continue...')

View File

@ -27,13 +27,14 @@ def strftime(epoch, zone=time.gmtime):
src[2] = INVERSE_MONTH_MAP[int(src[2])]
return ' '.join(src)
def debug():
def debug(ioreg_to_tmp=False, buf=None):
from calibre.customize.ui import device_plugins
from calibre.devices.scanner import DeviceScanner
from calibre.constants import iswindows, isosx, __version__
from calibre import prints
oldo, olde = sys.stdout, sys.stderr
if buf is None:
buf = StringIO()
sys.stdout = sys.stderr = buf
try:
@ -82,16 +83,17 @@ def debug():
connected_devices = []
for dev in device_plugins():
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:
connected_devices.append(dev)
connected_devices.append((dev, det))
errors = {}
success = False
for dev in connected_devices:
for dev, det in connected_devices:
out('Device possibly connected:', dev.__class__.name)
out('Trying to open device...', end=' ')
try:
dev.reset(detected_device=det)
dev.open()
out('OK')
except:
@ -112,10 +114,16 @@ def debug():
out(' ')
if ioreg is not None:
ioreg = 'IOREG Output\n'+ioreg
out(' ')
out('IOREG Output')
if ioreg_to_tmp:
open('/tmp/ioreg.txt', 'wb').write(ioreg)
out('Dont forget to send the contents of /tmp/ioreg.txt')
out('You can open it with the command: open /tmp/ioreg.txt')
else:
out(ioreg)
if hasattr(buf, 'getvalue'):
return buf.getvalue().decode('utf-8')
finally:
sys.stdout = oldo

View File

@ -10,7 +10,7 @@ Device driver for Bookeen's Cybook Gen 3
import os
from calibre import islinux
from calibre.constants import isunix
from calibre.devices.usbms.driver import USBMS
import calibre.devices.cybookg3.t2b as t2b
@ -55,7 +55,7 @@ class CYBOOKG3(USBMS):
@classmethod
def can_handle(cls, device_info, debug=False):
if islinux:
if isunix:
return device_info[3] == 'Bookeen' and device_info[4] == 'Cybook Gen3'
return True
@ -87,6 +87,6 @@ class CYBOOK_OPUS(CYBOOKG3):
@classmethod
def can_handle(cls, device_info, debug=False):
if islinux:
if isunix:
return device_info[3] == 'Bookeen'
return True

View File

@ -104,12 +104,12 @@ class DevicePlugin(Plugin):
@classmethod
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
'''
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 = cls.VENDOR_ID if hasattr(cls.VENDOR_ID, '__len__') else [cls.VENDOR_ID]
@ -134,18 +134,20 @@ class DevicePlugin(Plugin):
if debug:
cls.print_usb_device_info(dev)
if cls.can_handle(dev, debug=debug):
return True
return False
return True, dev
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
@param log_packets: If true the packet stream to/from the device is logged
@param report_progress: Function that is called with a % progress
:key: The key to unlock the device
:log_packets: If true the packet stream to/from the device is logged
:report_progress: Function that is called with a % progress
(number between 0 and 100) for various tasks
If it is called with -1 that means that the
task does not have any progress information
:detected_device: Device information from the device scanner
"""
raise NotImplementedError()

View File

@ -206,9 +206,10 @@ def main():
scanner.scan()
connected_devices = []
for d in device_plugins():
if scanner.is_device_connected(d):
ok, det = scanner.is_device_connected(d)
if ok:
dev = d
dev.reset(log_packets=options.log_packets)
dev.reset(log_packets=options.log_packets, detected_device=det)
connected_devices.append(dev)
if dev is None:

View File

@ -39,6 +39,7 @@ from tempfile import TemporaryFile
from array import array
from functools import wraps
from StringIO import StringIO
from threading import RLock
from calibre.devices.interface import DevicePlugin
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
KNOWN_USB_PROTOCOL_VERSIONS = [0x3030303030303130L]
lock = RLock()
class File(object):
"""
@ -161,9 +163,12 @@ class PRS500(DeviceConfig, DevicePlugin):
"""
@wraps(func)
def run_session(*args, **kwargs):
with lock:
dev = args[0]
res = None
try:
if not hasattr(dev, 'in_session'):
dev.reset()
if not dev.handle:
dev.open()
if not getattr(dev, 'in_session', False):
@ -194,7 +199,8 @@ class PRS500(DeviceConfig, DevicePlugin):
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 log_packets: If true the packet stream to/from the device is logged
@ -203,6 +209,7 @@ class PRS500(DeviceConfig, DevicePlugin):
If it is called with -1 that means that the
task does not have any progress information
"""
with lock:
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
# Handle that is used to communicate with device. Setup in L{open}
self.handle = None
@ -243,8 +250,9 @@ class PRS500(DeviceConfig, DevicePlugin):
Also initialize the device.
See the source code for the sequence of initialization commands.
"""
with lock:
if not hasattr(self, 'key'):
self.key = '-1\0\0\0\0\0\0'
self.reset()
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
if not self.device:
raise DeviceError()
@ -294,6 +302,7 @@ class PRS500(DeviceConfig, DevicePlugin):
def close(self):
""" Release device interface """
with lock:
try:
self.handle.reset()
self.handle.release_interface(self.INTERFACE_ID)
@ -312,6 +321,7 @@ class PRS500(DeviceConfig, DevicePlugin):
@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.
"""
with lock:
if self.log_packets:
self.log_packet(command, "Command")
bytes_sent = self.handle.control_msg(0x40, 0x80, command)
@ -346,6 +356,7 @@ class PRS500(DeviceConfig, DevicePlugin):
@param packet_size: Size of packets to be sent to device.
C{data} is broken up into packets to be sent to device.
"""
with lock:
def bulk_write_packet(packet):
self.handle.bulk_write(self.BULK_OUT_EP, packet)
if self.log_packets:
@ -394,6 +405,7 @@ class PRS500(DeviceConfig, DevicePlugin):
@return: A list of packets read from the device.
Each packet is of type data_type
"""
with lock:
msize = self.bulk_read_max_packet_size
def bulk_read_packet(data_type=Answer, size=0x1000):
rsize = size

View File

@ -22,9 +22,32 @@ from itertools import repeat
from calibre.devices.interface import DevicePlugin
from calibre.devices.errors import DeviceError, FreeSpaceError
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
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):
'''
@ -108,8 +131,13 @@ class Device(DeviceConfig, DevicePlugin):
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">'
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
try:
self.detected_device = USBDevice(detected_device)
except: # On windows detected_device is None
self.detected_device = None
@classmethod
def get_gui_name(cls):
@ -391,29 +419,82 @@ class Device(DeviceConfig, DevicePlugin):
raise
time.sleep(2)
def open_osx(self):
mount = self.osx_run_mount()
names = self.get_osx_mountpoints()
dev_pat = r'/dev/%s(\w*)\s+on\s+([^\(]+)\s+'
if 'main' not in names.keys():
raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%self.__class__.__name__)
main_pat = dev_pat % names['main']
main_match = re.search(main_pat, mount)
if main_match is None:
raise DeviceError(_('Unable to detect the %s mount point. Try rebooting.')%self.__class__.__name__)
self._main_prefix = main_match.group(2) + os.sep
card_a_pat = names['carda'] if 'carda' in names.keys() else None
card_b_pat = names['cardb'] if 'cardb' in names.keys() else None
def get_card_prefix(pat):
if pat is not None:
pat = dev_pat % pat
return re.search(pat, mount).group(2) + os.sep
def _osx_bsd_names(self):
if usbobserver_err:
raise RuntimeError('Failed to load usbobserver: '+usbobserver_err)
drives = usbobserver.get_usb_drives()
matches = []
d = self.detected_device
if d.serial:
for path, vid, pid, bcd, ven, prod, serial in drives:
if d.match_serial(serial):
matches.append(path)
if not matches:
if d.manufacturer and d.product:
for path, vid, pid, bcd, man, prod, serial in drives:
if d.match_strings(vid, pid, bcd, man, prod):
matches.append(path)
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)
self._card_b_prefix = get_card_prefix(card_b_pat)
pat = re.compile(r'(?P<m>\d+)([a-z]+(?P<p>\d+)){0,1}')
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):

View File

@ -33,10 +33,6 @@ class USBMS(CLI, Device):
FORMATS = []
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):
self.report_progress(1.0, _('Get device information...'))
return (self.__class__.__name__, '', '', '')

View File

@ -24,31 +24,74 @@
#include <stdio.h>
#include <CoreFoundation/CFNumber.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.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*
get_iokit_string_property(io_service_t dev, int prop) {
usbobserver_get_iokit_string_property(io_service_t dev, CFStringRef prop) {
CFTypeRef PropRef;
char buf[500];
PropRef = IORegistryEntryCreateCFProperty(dev, USB_PROPS[prop], kCFAllocatorDefault, 0);
PropRef = IORegistryEntryCreateCFProperty(dev, prop, kCFAllocatorDefault, 0);
if (PropRef) {
if(!CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8)) buf[0] = '\0';
CFRelease(PropRef);
} else buf[0] = '\0';
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 *
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
CFMutableDictionaryRef matchingDict;
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);
@ -58,78 +101,206 @@ usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
}
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;
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;
}
PyObject *devices, *device;
devices = PyList_New(0);
if (devices == NULL) {
PyErr_NoMemory();
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;
}
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);
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->GetDeviceReleaseNumber(dev, &bcd);
if (vendor != NULL && product != NULL && bcd != NULL) {
manufacturer = get_iokit_string_property(usbDevice, 0);
if (manufacturer == NULL) manufacturer = Py_None;
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;
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("(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);
(*plugInInterface)->Release(plugInInterface);
(*dev)->Release(dev);
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);
}
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[] = {
{"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}
};

View File

@ -12,6 +12,7 @@ import subprocess
from functools import partial
from calibre.ebooks import ConversionError, DRMError
from calibre.ptempfile import PersistentTemporaryFile
from calibre import isosx, iswindows, islinux
from calibre import CurrentDir
@ -45,8 +46,10 @@ def pdftohtml(output_dir, pdf_path, no_images):
if no_images:
cmd.append('-i')
logf = PersistentTemporaryFile('pdftohtml_log')
try:
p = popen(cmd, stderr=subprocess.PIPE)
p = popen(cmd, stderr=logf._fd, stdout=logf._fd,
stdin=subprocess.PIPE)
except OSError, err:
if err.errno == 2:
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
else:
raise
logf.flush()
logf.close()
out = open(logf.name, 'rb').read()
if ret != 0:
err = p.stderr.read()
raise ConversionError(err)
raise ConversionError(out)
print "pdftohtml log:"
print out
if not os.path.exists(index) or os.stat(index).st_size < 100:
raise DRMError()

View File

@ -94,8 +94,8 @@ class DeviceManager(Thread):
import pythoncom
pythoncom.CoInitialize()
try:
for dev in connected_devices:
dev.reset()
for dev, detected_device in connected_devices:
dev.reset(detected_device=detected_device)
try:
dev.open()
except:
@ -116,10 +116,10 @@ class DeviceManager(Thread):
self.scanner.scan()
connected_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 showing in GUI and not ejected
connected_devices.append(device[0])
connected_devices.append((device[0], detected_device))
device[1] = True
elif not connected and device[1]:
# Disconnected but showing in GUI

View File

@ -92,6 +92,12 @@ class Sony505(Sony500):
name = 'SONY Reader Pocket/Touch Edition'
id = 'prs505'
class Sony900(Sony505):
name = 'SONY Reader Daily Edition'
id = 'prs900'
output_profile = 'sony900'
class Nook(Sony505):
id = 'nook'
name = 'Nook'

View File

@ -81,7 +81,7 @@ Device Integration
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|?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
"PO-Revision-Date: 2009-12-25 19:11+0000\n"
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
"PO-Revision-Date: 2009-12-26 16:45+0000\n"
"Last-Translator: Kovid Goyal <Unknown>\n"
"Language-Team: Arabic <ar@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\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"
#: /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:121
#: /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:783
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
#: /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:51
#: /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:717
#: /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:63
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
@ -7361,10 +7361,18 @@ msgid "English (TH)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
msgid "Dutch (NL)"
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)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
msgid "Dutch (BE)"
msgstr ""

View File

@ -4,9 +4,9 @@
#
msgid ""
msgstr ""
"Project-Id-Version: calibre 0.6.30\n"
"POT-Creation-Date: 2009-12-26 08:40+MST\n"
"PO-Revision-Date: 2009-12-26 08:40+MST\n"
"Project-Id-Version: calibre 0.6.31\n"
"POT-Creation-Date: 2009-12-27 16:02+MST\n"
"PO-Revision-Date: 2009-12-27 16:02+MST\n"
"Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\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/devices/jetbook/driver.py:94
#: /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:199
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:789
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:792
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:206
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:870
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:873
#: /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/fb2/input.py:67
#: /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 ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:56
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:208
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc."
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:235
msgid "This profile is intended for the SONY PRS line. The 500/505/600/700 etc."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:69
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:243
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:68
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."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:80
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:254
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:96
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:298
msgid "This profile is intended for the Mobipocket books."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:93
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:267
msgid "This profile is intended for the Hanlin V3/V5 and its clones."
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:109
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:311
msgid "This profile is intended for the Hanlin V3 and its clones."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:105
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:279
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:121
#: /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."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:118
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:292
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:144
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:344
msgid "This profile is intended for the Cybook Opus."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:130
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:303
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:156
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:355
msgid "This profile is intended for the Amazon Kindle."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:142
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:336
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:168
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:388
msgid "This profile is intended for the Irex Illiad."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:154
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:349
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:180
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:401
msgid "This profile is intended for the IRex Digital Reader 1000."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:168
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:363
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:194
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:415
msgid "This profile is intended for the B&N Nook."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:186
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:213
msgid "Output profile"
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."
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."
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."
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."
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"
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
msgid "Communicate with the Blackberry smart phone."
msgstr ""
#: /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/prs500/driver.py:88
#: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:90
msgid "Kovid Goyal"
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
msgid "Communicate with the Cybook Gen 3 eBook reader."
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."
msgstr ""
@ -407,6 +415,18 @@ msgstr ""
msgid "Communicate with the ESlick eBook reader."
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
msgid "Communicate with the IRex Iliad eBook reader."
msgstr ""
@ -437,8 +457,8 @@ msgstr ""
#: /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:136
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:120
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:122
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:116
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:118
msgid "Transferring books to device..."
msgstr ""
@ -474,7 +494,7 @@ msgstr ""
msgid "Communicate with the Nuut2 eBook reader."
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."
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:103
#: /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:52
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:55
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:75
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:85
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:94
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:45
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:48
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:51
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:71
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:81
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:90
msgid "Getting list of books on device..."
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:174
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:148
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:163
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:159
msgid "Removing books from device..."
msgstr ""
#: /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..."
msgstr ""
#: /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 ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:308
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:399
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:336
msgid "Unable to detect the %s disk drive. Try rebooting."
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."
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."
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."
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."
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)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:720
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:722
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:801
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:803
msgid "The reader has no storage card in this slot."
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."
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"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:759
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:761
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:840
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:842
msgid "There is insufficient free space on the storage card"
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/tag_view.py:125
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1065
@ -594,17 +613,17 @@ msgstr ""
msgid "Communicate with an eBook reader."
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..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:136
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:144
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:132
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:140
msgid "Adding books to device metadata listing..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:167
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:172
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:163
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:168
msgid "Removing books from device metadata listing..."
msgstr ""
@ -1902,7 +1921,7 @@ msgstr ""
msgid "The orientation of the page. Default is portrait. Choices are %s"
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"
msgstr ""
@ -2048,7 +2067,7 @@ msgid "Limit max simultaneous jobs to number of CPUs"
msgstr ""
#: /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"
msgstr ""
@ -3459,7 +3478,7 @@ msgid "Failed to start content server"
msgstr ""
#: /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"
msgstr ""
@ -5354,7 +5373,7 @@ msgid "Bad database location"
msgstr ""
#: /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"
msgstr ""
@ -6119,40 +6138,40 @@ msgstr ""
msgid "Title Case"
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."
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."
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."
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..."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:394
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:395
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:400
#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:401
msgid "Failed to move library"
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"
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"
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"
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"
msgstr ""
@ -6970,50 +6989,50 @@ msgstr ""
msgid "Custom"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:455
#: /home/kovid/work/calibre/src/calibre/web/fetch/simple.py:459
msgid ""
"%prog URL\n"
"\n"
"Where URL is for example http://google.com"
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"
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"
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"
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"
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"
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."
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."
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."
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."
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"
msgstr ""

View File

@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: de\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
"PO-Revision-Date: 2009-12-25 21:08+0000\n"
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
"PO-Revision-Date: 2009-12-26 20:24+0000\n"
"Last-Translator: S. Dorscht <Unknown>\n"
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\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"
"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:121
#: /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:783
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
#: /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:51
#: /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:717
#: /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:63
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
@ -8227,10 +8227,18 @@ msgid "English (TH)"
msgstr "Englisch (TH)"
#: /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)"
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)"
msgstr "Holländisch (BE)"

View File

@ -10,14 +10,14 @@ msgid ""
msgstr ""
"Project-Id-Version: es\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
"PO-Revision-Date: 2009-12-26 01:25+0000\n"
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
"PO-Revision-Date: 2009-12-26 16:48+0000\n"
"Last-Translator: mosteo <alejandro@mosteo.com>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\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"
#: /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:121
#: /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:783
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
#: /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:51
#: /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:717
#: /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:63
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
@ -8181,10 +8181,18 @@ msgid "English (TH)"
msgstr "Inglés (TH)"
#: /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)"
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)"
msgstr "Neerlandés (BE)"

File diff suppressed because it is too large Load Diff

View File

@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
"PO-Revision-Date: 2009-12-25 19:14+0000\n"
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
"PO-Revision-Date: 2009-12-26 16:50+0000\n"
"Last-Translator: Kovid Goyal <Unknown>\n"
"Language-Team: Latvian <ivars_a@inbox.lv>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\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-Poedit-Country: LATVIA\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:121
#: /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:783
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
#: /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:51
#: /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:717
#: /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:63
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
@ -7354,10 +7354,18 @@ msgid "English (TH)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
msgid "Dutch (NL)"
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)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
msgid "Dutch (BE)"
msgstr ""

View File

@ -6,14 +6,14 @@ msgid ""
msgstr ""
"Project-Id-Version: calibre 0.4.55\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-12-25 04:54+0000\n"
"PO-Revision-Date: 2009-12-25 19:27+0000\n"
"POT-Creation-Date: 2009-12-26 16:57+0000\n"
"PO-Revision-Date: 2009-12-26 16:54+0000\n"
"Last-Translator: Kovid Goyal <Unknown>\n"
"Language-Team: American English <kde-i18n-doc@lists.kde.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\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-Poedit-Country: RUSSIAN FEDERATION\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:121
#: /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:783
#: /home/kovid/work/calibre/src/calibre/ebooks/mobi/reader.py:594
#: /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:51
#: /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:717
#: /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:63
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
@ -7760,10 +7760,18 @@ msgid "English (TH)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:103
msgid "Dutch (NL)"
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)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:106
msgid "Dutch (BE)"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -190,6 +190,10 @@ class RecursiveFetcher(object):
time.sleep(delta)
if isinstance(url, unicode):
url = url.encode('utf-8')
# Not sure is this is really needed as I think mechanize
# handles quoting automatically, but leaving it in
# in case it breaks something
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])