def ensure_single_instance(args, open_at): try: from calibre.utils.lock import singleinstance si = singleinstance(singleinstance_name) except Exception: import traceback error_dialog(None, _('Cannot start viewer'), _( 'Failed to start viewer, could not insure only a single instance of the viewer is running. Click "Show Details" for more information'), det_msg=traceback.format_exc(), show=True) raise SystemExit(1) if not si: if len(args) > 1: t = RC(print_error=True, socket_address=viewer_socket_address()) t.start() t.join(3.0) if t.is_alive() or t.conn is None: error_dialog(None, _('Connect to viewer failed'), _( 'Unable to connect to existing viewer window, try restarting the viewer.'), show=True) raise SystemExit(1) t.conn.send((os.path.abspath(args[1]), open_at)) t.conn.close() prints('Opened book in existing viewer instance') raise SystemExit(0) listener = create_listener() return listener
def send_message(msg=''): if msg: t = RC(print_error=False) t.start() t.join(3) if t.done: t.conn.send('bookedited:' + msg) t.conn.close()
def build_pipe(print_error=True): t = RC(print_error=print_error) t.start() t.join(3.0) if t.is_alive(): cant_start() raise SystemExit(1) return t
def send_message(msg=''): prints('Notifying calibre of the change') from calibre.utils.ipc import RC t = RC(print_error=False) t.start() t.join(3) if t.done: t.conn.send('refreshdb:' + msg) t.conn.close()
def send_rc_message(msg): from calibre.utils.ipc import RC t = RC(print_error=False) t.start() t.join(3) if t.done: t.conn.send('refreshdb:' + msg) t.conn.close() if DEBUG: print('Calibre has been notified of the change...')
def build_pipe(print_error=True): t = RC(print_error=print_error) t.start() t.join(3.0) if t.is_alive(): if iswindows: cant_start() else: f = os.path.expanduser('~/.calibre_calibre GUI.lock') cant_start(what=_('try deleting the file') + ': ' + f) raise SystemExit(1) return t
def updateCalibreGUIView(): ''' Refresh the GUI view ''' t = RC(print_error=False) t.start() sleep(0.5) while True: if t.done: t.conn.send('refreshdb:') t.conn.close() break sleep(0.5)
def download_finished(self, download_id): self.central.download_progress.remove_item(download_id) download_item = self.download_data.pop(download_id) path = download_item.path() fname = os.path.basename(path) if download_item.state() == download_item.DownloadInterrupted: error_dialog(self, _('Download failed'), _( 'Download of {0} failed with error: {1}').format(fname, download_item.interruptReasonString()), show=True) return ext = fname.rpartition('.')[-1].lower() if ext not in BOOK_EXTENSIONS: if ext == 'acsm': if not confirm('<p>' + _( 'This e-book is a DRMed EPUB file. ' 'You will be prompted to save this file to your ' 'computer. Once it is saved, open it with ' '<a href="https://www.adobe.com/solutions/ebook/digital-editions.html">' 'Adobe Digital Editions</a> (ADE).<p>ADE, in turn ' 'will download the actual e-book, which will be a ' '.epub file. You can add this book to calibre ' 'using "Add Books" and selecting the file from ' 'the ADE library folder.'), 'acsm_download', self): return name = choose_save_file(self, 'web-store-download-unknown', _( 'File is not a supported e-book type. Save to disk?'), initial_filename=fname) if name: shutil.copyfile(path, name) os.remove(path) return t = RC(print_error=False) t.start() t.join(3.0) if t.conn is None: error_dialog(self, _('No running calibre'), _( 'No running calibre instance found. Please start calibre before trying to' ' download books.'), show=True) return tags = self.data['tags'] if isinstance(tags, string_or_bytes): tags = list(filter(None, [x.strip() for x in tags.split(',')])) data = json.dumps({'path': path, 'tags': tags}) if not isinstance(data, bytes): data = data.encode('utf-8') t.conn.send(b'web-store:' + data) t.conn.close() info_dialog(self, _('Download completed'), _( 'Download of {0} has been completed, the book was added to' ' your calibre library').format(fname), show=True)
def _postimport(self, book_id, book_format=None, db=None, log=None, fork_job=True, abort=None, notifications=None): #NODOC IMPORTANT # TODO: make general overhaul of starting conversion logic if log: # divert our printing to the caller's logger prints = log # Log object has __call__ dunder method with INFO level prints = partial(prints, '{}:'.format(PLUGINNAME)) else: log = self.prints.func try: prints except NameError: prints = self.prints if sys.__stdin__.isatty(): # if run by cli, i.e.: # calibredb add # calibredebug -r djvumaker -- convert -i #id # runs also for GUI if run trough `calibredebug -g` fork_job = False # DEBUG UNCOMMENT rpc_refresh = True # use the calibre RPC to signal a GUI refresh if db is None: from calibre.library import db # TODO: probably legacy db import, change for new_api db = db() # initialize calibre library database if book_format == None: if not db.has_format(book_id, 'PDF', index_is_id=True): raise Exception( 'Book with id #{} has not a PDF format.'.format(book_id)) else: book_format = 'pdf' if db.has_format(book_id, 'DJVU', index_is_id=True): prints( "already have 'DJVU' format document for book ID #{}".format( book_id)) return None # don't auto convert, we already have a DJVU for this document path_to_ebook = db.format_abspath(book_id, book_format, index_is_id=True) if book_format == 'pdf': is_rasterbook_val, pages, images = is_rasterbook( path_to_ebook, basic_return=False) if is_rasterbook_val: pass # TODO: should add a 'scanned' or 'djvumaker' tag else: # this is a marked-up/vector-based pdf, # no advantages to having another copy in DJVU format prints(( "{} document from book ID #{} determined to be a markup-based ebook," " not converting to DJVU").format(book_format, book_id)) return None #no-error in job panel # TODO: test the DPI to determine if a document is from a broad-sheeted book. # if so, queue up k2pdfopt to try and chunk the content appropriately to letter size prints(( "scheduling new {} document from book ID #{} for post-import DJVU" " conversion: {}").format(book_format, book_id, path_to_ebook)) if fork_job: #useful for not blocking calibre GUI when large PDFs # are dropped into the automatic-import-folder try: # https://github.com/kovidgoyal/calibre/blob/master/src/calibre/utils/ipc/simple_worker.py # dispatch API for Worker() # src/calibre/utils/ipc/launch.py # Worker() uses sbp.Popen to # run a second Python to a logfile # note that Calibre bungs the python loader to check the plugin directory when # modules with calibre_plugin. prefixed are passed # https://github.com/kovidgoyal/calibre/blob/master/src/calibre/customize/zipplugin.py#L192 func_name = self.plugin_prefs['use_backend'] args = [ path_to_ebook, log, abort, notifications, pages, images ] jobret = worker_fork_job( 'calibre_plugins.{}'.format(PLUGINNAME), func_name, args=args, kwargs={'preferences': self.plugin_prefs}, env={'PATH': os.environ['PATH'] + ':/usr/local/bin'}, # djvu and poppler-utils on osx timeout=600) # TODO: determine a resonable timeout= based on filesize or # make a heartbeat= check # TODO: doesn't work for pdf2djvu, why? except WorkerError as e: prints('djvudigital background conversion failed: \n{}'.format( force_unicode(e.orig_tb))) raise # ConversionError except: prints(traceback.format_exc()) raise # dump djvudigital output logged in file by the Worker to # calibre proc's (gui or console) log/stdout with open(jobret['stdout_stderr'], 'rb') as f: raw = f.read().strip() prints(raw) if jobret['result']: djvu = jobret['result'] else: WorkerError("djvu conversion error: %s" % jobret['result']) # elif hasattr(self, gui): #if we have the calibre gui running, # we can give it a threadedjob and not use fork_job else: #!fork_job & !gui prints("Starts backend") djvu = self.run_backend(path_to_ebook, log, abort, notifications, pages, images) if djvu: db.new_api.add_format(book_id, 'DJVU', djvu, run_hooks=True) prints("added new 'DJVU' document to book ID #{}".format(book_id)) if sys.__stdin__.isatty(): # update calibre gui Out-Of-Band. Like if we were run as a command-line scripted import # this resets current gui views/selections, no cleaner way to do it :-( from calibre.utils.ipc import RC t = RC(print_error=False) t.start() t.join(3) if t.done: # GUI is running t.conn.send('refreshdb:') t.conn.close() prints("signalled Calibre GUI refresh") else: # TODO: normal Exception propagation instead of passing errors as return values raise Exception('ConversionError, djvu: {}'.format(djvu))