From 7571cbf7acc5f3fe2afe82bcedb97565bb97bfc2 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Sep 2012 08:30:10 +0200 Subject: [PATCH 1/5] Make approximate_formats work when there are no formats --- src/calibre/utils/formatter_functions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index fae2d50f80..393ef876c9 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -608,6 +608,8 @@ class BuiltinApproximateFormats(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals): fmt_data = mi.get('db_approx_formats', []) + if not fmt_data: + return '' data = sorted(fmt_data) return ','.join(v.upper() for v in data) From 17e56c57b4956dd459224ad39031872e9415859b Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Sep 2012 09:04:53 +0200 Subject: [PATCH 2/5] Put the device kind when the wireless driver connects --- .../devices/smart_device_app/driver.py | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index 47bc4b3185..24323a5923 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -163,7 +163,9 @@ class SDBook(Book): class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): name = 'SmartDevice App Interface' - gui_name = _('SmartDevice') + gui_name = _('Wireless Device') + gui_name_template = '%s: %s' + icon = I('devices/galaxy_s3.png') description = _('Communicate with Smart Device apps') supported_platforms = ['windows', 'osx', 'linux'] @@ -321,28 +323,30 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): self.client_can_stream_metadata = False def _debug(self, *args): - if not DEBUG: - return - total_elapsed = time.time() - self.debug_start_time - elapsed = time.time() - self.debug_time - print('SMART_DEV (%7.2f:%7.3f) %s'%(total_elapsed, elapsed, - inspect.stack()[1][3]), end='') - for a in args: - try: - if isinstance(a, dict): - printable = {} - for k,v in a.iteritems(): - if isinstance(v, (str, unicode)) and len(v) > 50: - printable[k] = 'too long' - else: - printable[k] = v - prints('', printable, end='') - else: - prints('', a, end='') - except: - prints('', 'value too long', end='') - print() - self.debug_time = time.time() + # manual synchronization so we don't lose the calling method name + with self.sync_lock: + if not DEBUG: + return + total_elapsed = time.time() - self.debug_start_time + elapsed = time.time() - self.debug_time + print('SMART_DEV (%7.2f:%7.3f) %s'%(total_elapsed, elapsed, + inspect.stack()[1][3]), end='') + for a in args: + try: + if isinstance(a, dict): + printable = {} + for k,v in a.iteritems(): + if isinstance(v, (str, unicode)) and len(v) > 50: + printable[k] = 'too long' + else: + printable[k] = v + prints('', printable, end='') + else: + prints('', a, end='') + except: + prints('', 'value too long', end='') + print() + self.debug_time = time.time() # local utilities @@ -825,6 +829,9 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): self.client_can_receive_book_binary = result.get('canReceiveBookBinary', False) self._debug('Device can receive book binary', self.client_can_stream_metadata) + self.client_device_kind = result.get('deviceKind', '') + self._debug('Client device kind', self.client_device_kind) + self.max_book_packet_len = result.get('maxBookContentPacketLen', self.BASE_PACKET_LEN) self._debug('max_book_packet_len', self.max_book_packet_len) @@ -886,6 +893,13 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): raise return False + @synchronous('sync_lock') + def get_gui_name(self): + if self.client_device_kind: + return self.gui_name_template%(self.gui_name, self.client_device_kind) + return self.gui_name + + @synchronous('sync_lock') def get_device_information(self, end_session=True): self._debug() @@ -1039,6 +1053,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): @synchronous('sync_lock') def post_yank_cleanup(self): self._debug() + self.gui_name = self.gui_name_base @synchronous('sync_lock') def upload_books(self, files, names, on_card=None, end_session=True, From 482d360024e2b06bdcbe4cb5a185f0bfc29a4bea Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Sep 2012 11:22:45 +0200 Subject: [PATCH 3/5] Add the content server port to the broadcast reply. --- src/calibre/devices/smart_device_app/driver.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index 24323a5923..cd37c2b075 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -31,9 +31,10 @@ from calibre.ebooks.metadata import title_sort from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.book.json_codec import JsonCodec from calibre.library import current_library_name +from calibre.library.server import server_config as content_server_config from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.ipc import eintr_retry_call -from calibre.utils.config import from_json, tweaks +from calibre.utils.config import from_json, tweaks, ConfigProxy from calibre.utils.date import isoformat, now from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to from calibre.utils.mdns import (publish as publish_zeroconf, unpublish as @@ -98,9 +99,11 @@ class ConnectionListener (Thread): try: packet = self.driver.broadcast_socket.recvfrom(100) remote = packet[1] + content_server_port = ConfigProxy(content_server_config())['port'] message = str(self.driver.ZEROCONF_CLIENT_STRING + b' (on ' + str(socket.gethostname().partition('.')[0]) + - b'),' + str(self.driver.port)) + b');' + str(content_server_port) + + b',' + str(self.driver.port)) self.driver._debug('received broadcast', packet, message) self.driver.broadcast_socket.sendto(message, remote) except: From c9e4eb68cd541ac414f767a9b47dfbbf1a8b991b Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Sep 2012 11:36:44 +0200 Subject: [PATCH 4/5] Defensive programming around fetching the CS port --- src/calibre/devices/smart_device_app/driver.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index cd37c2b075..d2e72ebc1e 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -99,10 +99,15 @@ class ConnectionListener (Thread): try: packet = self.driver.broadcast_socket.recvfrom(100) remote = packet[1] - content_server_port = ConfigProxy(content_server_config())['port'] + content_server_port = b''; + try : + content_server_port = \ + str(ConfigProxy(content_server_config())['port']) + except: + pass message = str(self.driver.ZEROCONF_CLIENT_STRING + b' (on ' + str(socket.gethostname().partition('.')[0]) + - b');' + str(content_server_port) + + b');' + content_server_port + b',' + str(self.driver.port)) self.driver._debug('received broadcast', packet, message) self.driver.broadcast_socket.sendto(message, remote) From 6dd1312693f3dc5c160f3d6bf4bccadad085b375 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Thu, 20 Sep 2012 14:46:10 +0200 Subject: [PATCH 5/5] Remove "synchronous" from get_gui_name. Use suggested code to get the port. --- src/calibre/devices/smart_device_app/driver.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index d2e72ebc1e..f655e2bc4b 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -102,7 +102,7 @@ class ConnectionListener (Thread): content_server_port = b''; try : content_server_port = \ - str(ConfigProxy(content_server_config())['port']) + str(content_server_config().parse().port) except: pass message = str(self.driver.ZEROCONF_CLIENT_STRING + b' (on ' + @@ -901,7 +901,6 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): raise return False - @synchronous('sync_lock') def get_gui_name(self): if self.client_device_kind: return self.gui_name_template%(self.gui_name, self.client_device_kind)