Skip to content

Commit

Permalink
#598: support polling for platforms where we cannot rely on dbus to g…
Browse files Browse the repository at this point in the history
…et notified of printer changes (ie: osx, or with env var to test) - don't even try the dbus approach on OSX by default, make the polling delay configurable, add some debug

git-svn-id: https://xpra.org/svn/Xpra/trunk@8871 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Mar 30, 2015
1 parent 11439e7 commit 57ce84a
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 28 deletions.
26 changes: 23 additions & 3 deletions src/xpra/client/client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
from xpra.os_util import get_hex_uuid, get_machine_id, get_user_uuid, load_binary_file, SIGNAMES, strtobytes, bytestostr
from xpra.util import typedict, updict, xor, repr_ellipsized, nonl, disconnect_is_an_error

try:
import xpra.platform.printing
assert xpra.platform.printing
HAS_PRINTING = True
except:
HAS_PRINTING = False

EXIT_OK = 0
EXIT_CONNECTION_LOST = 1
EXIT_TIMEOUT = 2
Expand Down Expand Up @@ -350,6 +357,7 @@ def cleanup(self):
if self._protocol:
self._protocol.close()
self._protocol = None
self.cleanup_printing()

def glib_init(self):
try:
Expand Down Expand Up @@ -538,14 +546,26 @@ def parse_printing_capabilities(self):
self.timeout_add(1000, self.init_printing)

def init_printing(self):
if not HAS_PRINTING:
return
try:
from xpra.platform.printing import on_printers_modified
printlog("on_printers_modified=%s", on_printers_modified)
on_printers_modified(self.send_printers)
from xpra.platform.printing import init_printing
printlog("init_printing=%s", init_printing)
init_printing(self.send_printers)
self.do_send_printers()
except Exception:
log.warn("failed to send printers", exc_info=True)

def cleanup_printing(self):
if not HAS_PRINTING:
return
try:
from xpra.platform.printing import cleanup_printing
printlog("cleanup_printing=%s", cleanup_printing)
cleanup_printing()
except Exception:
log.warn("failed to cleanup printing subsystem", exc_info=True)

def send_printers(self, *args):
#dbus can fire dozens of times for a single printer change
#so we wait a bit and fire via a timer to try to batch things together:
Expand Down
11 changes: 7 additions & 4 deletions src/xpra/platform/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,25 @@ def print_files(printer, filenames, title, options):
def printing_finished(printpid):
return True

def on_printers_modified(callback):
def init_printing(printers_modified_callback=None):
pass

def cleanup_printing():
pass

#default implementation uses pycups:
from xpra.platform import platform_import
try:
from xpra.platform.pycups_printing import get_printers, print_files, printing_finished, on_printers_modified
assert get_printers and print_files and printing_finished and on_printers_modified
from xpra.platform.pycups_printing import get_printers, print_files, printing_finished, init_printing, cleanup_printing
assert get_printers and print_files and printing_finished and init_printing, cleanup_printing
except Exception as e:
#ignore the error on win32:
if not sys.platform.startswith("win"):
err("cannot use pycups for printing: %s", e)

platform_import(globals(), "printing", False,
"on_printers_modified",
"init_printing",
"cleanup_printing",
"get_printers",
"print_files",
"printing_finished")
Expand Down
76 changes: 57 additions & 19 deletions src/xpra/platform/pycups_printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
PRINTER_PREFIX = "Xpra:"
PRINTER_PREFIX = os.environ.get("XPRA_PRINTER_PREFIX", PRINTER_PREFIX)

DEFAULT_CUPS_DBUS = str(int(not sys.platform.startswith("darwin")))
CUPS_DBUS = os.environ.get("XPRA_CUPS_DBUS", DEFAULT_CUPS_DBUS)=="1"
POLLING_DELAY = int(os.environ.get("XPRA_CUPS_POLLING_DELAY", "60"))
log("pycups settings: DEFAULT_CUPS_DBUS=%s, CUPS_DBUS=%s, POLLING_DELAY=%s", DEFAULT_CUPS_DBUS, CUPS_DBUS, POLLING_DELAY)
log("pycups settings: PRINTER_PREFIX=%s, ADD_LOCAL_PRINTERS=%s", PRINTER_PREFIX, ADD_LOCAL_PRINTERS)
log("pycups settings: PPD_FILE=%s, ALLOW=%s", PPD_FILE, ALLOW)
log("pycups settings: FORWARDER_TMPDIR=%s", FORWARDER_TMPDIR)


#allows us to inject the lpadmin command
def set_lpadmin_command(lpadmin):
Expand Down Expand Up @@ -82,7 +90,7 @@ def remove_printer(name):
exec_lpadmin(["-x", PRINTER_PREFIX+sanitize_name(name)])


dbus_init = False
dbus_init = None
printers_modified_callback = None
DBUS_PATH="/com/redhat/PrinterSpooler"
DBUS_IFACE="com.redhat.PrinterSpooler"
Expand All @@ -92,28 +100,58 @@ def handle_dbus_signal(*args):
printers_modified_callback()

def init_dbus_listener():
if not CUPS_DBUS:
return False
global dbus_init
log("init_dbus_listener() dbus_init=%s", dbus_init)
if dbus_init:
return
dbus_init = True
try:
from xpra.x11.dbus_common import init_system_bus
system_bus = init_system_bus()
log("system bus: %s", system_bus)
sig_match = system_bus.add_signal_receiver(handle_dbus_signal, path=DBUS_PATH, dbus_interface=DBUS_IFACE)
log("system_bus.add_signal_receiver(..)=%s", sig_match)
except Exception:
if sys.platform.startswith("darwin"):
log("no dbus on osx")
else:
log.error("failed to initialize dbus cups event listener", exc_info=True)

def on_printers_modified(callback):
if dbus_init is None:
try:
from xpra.x11.dbus_common import init_system_bus
system_bus = init_system_bus()
log("system bus: %s", system_bus)
sig_match = system_bus.add_signal_receiver(handle_dbus_signal, path=DBUS_PATH, dbus_interface=DBUS_IFACE)
log("system_bus.add_signal_receiver(..)=%s", sig_match)
dbus_init = True
except Exception:
if sys.platform.startswith("darwin"):
log("no dbus on osx")
else:
log.error("failed to initialize dbus cups event listener", exc_info=True)
dbus_init = False
return dbus_init

def check_printers():
global printers_modified_callback
#we don't actually check anything here and just
#fire the callback every time, relying in client_base
#to notice that nothing has changed and avoid sending the same printers to the server
log("check_printers() printers_modified_callback=%s", printers_modified_callback)
printers_modified_callback()
schedule_polling_timer()

_polling_timer = None
def schedule_polling_timer():
#fallback to polling:
import threading
global _polling_timer
_polling_timer = threading.Timer(POLLING_DELAY, check_printers)
_polling_timer.start()

def init_printing(callback):
global printers_modified_callback
log("on_printers_modified(%s) printers_modified_callback=%s", callback, printers_modified_callback)
log("init_printing(%s) printers_modified_callback=%s", callback, printers_modified_callback)
printers_modified_callback = callback
init_dbus_listener()
if not init_dbus_listener():
log("init_printing(%s) will use polling", callback)
schedule_polling_timer()

def cleanup_printing():
global _polling_timer
try:
_polling_timer.cancel()
_polling_timer = None
except:
pass


def get_printers():
Expand Down
4 changes: 2 additions & 2 deletions src/xpra/platform/win32/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
PROCESSES = {}

printers_modified_callback = None
def on_printers_modified(callback):
def init_printing(callback):
global printers_modified_callback
log("on_printers_modified(%s) printers_modified_callback=%s", callback, printers_modified_callback)
log("init_printing(%s) printers_modified_callback=%s", callback, printers_modified_callback)
printers_modified_callback = callback
try:
init_winspool_listener()
Expand Down

0 comments on commit 57ce84a

Please sign in to comment.