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_to_viewer_instance(args, open_at): if len(args) > 1: msg = json.dumps((os.path.abspath(args[1]), open_at)) try: send_message_in_process(msg, address=viewer_socket_address()) except Exception as err: error_dialog(None, _('Connecting to E-book viewer failed'), _( 'Unable to connect to existing E-book viewer window, try restarting the viewer.'), det_msg=str(err), show=True) raise SystemExit(1) print('Opened book in existing viewer instance')
def main(args=sys.argv): # Ensure viewer can continue to function if GUI is closed os.environ.pop('CALIBRE_WORKER_TEMP_DIR', None) reset_base_dir() scheme = QWebEngineUrlScheme(FAKE_PROTOCOL.encode('ascii')) scheme.setSyntax(QWebEngineUrlScheme.Syntax.Host) scheme.setFlags(QWebEngineUrlScheme.Flag.SecureScheme) QWebEngineUrlScheme.registerScheme(scheme) override = 'calibre-ebook-viewer' if islinux else None processed_args = [] internal_book_data = internal_book_data_path = None for arg in args: if arg.startswith('--internal-book-data='): internal_book_data_path = arg.split('=', 1)[1] continue processed_args.append(arg) if internal_book_data_path: try: with lopen(internal_book_data_path, 'rb') as f: internal_book_data = json.load(f) finally: try: os.remove(internal_book_data_path) except OSError: pass args = processed_args app = Application(args, override_program_name=override, windows_app_uid=VIEWER_APP_UID) parser = option_parser() opts, args = parser.parse_args(args) oat = opts.open_at if oat and not ( oat.startswith('toc:') or oat.startswith('toc-href:') or oat.startswith('toc-href-contains:') or oat.startswith('epubcfi(/') or is_float(oat) or oat.startswith('ref:')): raise SystemExit('Not a valid --open-at value: {}'.format(opts.open_at)) if get_session_pref('singleinstance', False): from calibre.utils.lock import SingleInstance from calibre.gui2.listener import Listener with SingleInstance(singleinstance_name) as si: if si: try: listener = Listener(address=viewer_socket_address(), parent=app) listener.start_listening() except Exception as err: error_dialog(None, _('Failed to start listener'), _( 'Could not start the listener used for single instance viewers. Try rebooting your computer.'), det_msg=str(err), show=True) else: with closing(listener): run_gui(app, opts, args, internal_book_data, listener=listener) else: send_message_to_viewer_instance(args, opts.open_at) else: run_gui(app, opts, args, internal_book_data)
def create_listener(): addr = viewer_socket_address() if islinux: from calibre.utils.ipc.server import LinuxListener as Listener else: from multiprocessing.connection import Listener if not iswindows: # On macOS (and BSDs, I am guessing), following a crash, the # listener socket file sticks around and needs to be explicitly # removed. It is safe to do this since we are already guaranteed to # be the owner of the socket by singleinstance() try: os.remove(addr) except Exception: pass return Listener(address=addr)
def create_listener(): if islinux: from calibre.utils.ipc.server import LinuxListener as Listener else: from multiprocessing.connection import Listener return Listener(address=viewer_socket_address())