[gtk+] printing: Don't wake up Avahi printers unnecessarily
- From: Marek Kašík <mkasik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] printing: Don't wake up Avahi printers unnecessarily
- Date: Thu, 21 Nov 2013 14:45:03 +0000 (UTC)
commit 376e2c003d02405cb0a62b90f4e2a0cab88f9650
Author: Marek Kasik <mkasik redhat com>
Date: Thu Nov 21 15:27:33 2013 +0100
printing: Don't wake up Avahi printers unnecessarily
Use info available in Avahi TXT records for creation of gtk printer
and request details when needed (through gtk_printer_request_details()).
If there is a printer advertised on Avahi by a remote CUPS server
try to get its PPD file at first or get its capabilities through an IPP
request if it fails.
https://bugzilla.gnome.org/show_bug.cgi?id=712751
modules/printbackends/cups/gtkprintbackendcups.c | 317 +++++++++++++++-------
1 files changed, 220 insertions(+), 97 deletions(-)
---
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c
b/modules/printbackends/cups/gtkprintbackendcups.c
index 9090733..53c7de1 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -2365,28 +2365,6 @@ set_default_printer (GtkPrintBackendCups *cups_backend,
}
#ifdef HAVE_CUPS_API_1_6
-typedef struct
-{
- gchar *name;
- gchar *type;
- gchar *domain;
- gchar *host;
- gint port;
-} AvahiService;
-
-void
-avahi_service_free (AvahiService *service)
-{
- if (service)
- {
- g_free (service->name);
- g_free (service->type);
- g_free (service->domain);
- g_free (service->host);
- g_free (service);
- }
-}
-
static void
cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
GtkCupsResult *result,
@@ -2395,9 +2373,7 @@ cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend);
ipp_attribute_t *attr;
- AvahiService *service = (AvahiService *) user_data;
GtkPrinter *printer;
- gboolean list_has_changed = FALSE;
gboolean status_changed = FALSE;
ipp_t *response;
@@ -2432,42 +2408,28 @@ cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
if (info->printer_name && info->printer_uri)
{
- info->avahi_printer = TRUE;
-
- if (info->got_printer_type &&
- info->default_printer &&
- cups_backend->avahi_default_printer == NULL)
- cups_backend->avahi_default_printer = g_strdup (info->printer_name);
-
set_info_state_message (info);
printer = gtk_print_backend_find_printer (backend, info->printer_name);
- if (!printer)
+ if (printer != NULL &&
+ GTK_PRINTER_CUPS (printer)->avahi_browsed)
{
- printer = cups_create_printer (cups_backend, info);
- list_has_changed = TRUE;
+ g_object_ref (printer);
}
else
{
- g_object_ref (printer);
+ goto done;
}
+ if (info->got_printer_type &&
+ info->default_printer &&
+ cups_backend->avahi_default_printer == NULL)
+ cups_backend->avahi_default_printer = g_strdup (info->printer_name);
+
gtk_printer_set_is_paused (printer, info->is_paused);
gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
- if (!gtk_printer_is_active (printer))
- {
- gtk_printer_set_is_active (printer, TRUE);
- gtk_printer_set_is_new (printer, TRUE);
- list_has_changed = TRUE;
- }
-
GTK_PRINTER_CUPS (printer)->remote = info->remote_printer;
- GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (service->name);
- GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (service->type);
- GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (service->domain);
- GTK_PRINTER_CUPS (printer)->hostname = g_strdup (service->host);
- GTK_PRINTER_CUPS (printer)->port = service->port;
GTK_PRINTER_CUPS (printer)->state = info->state;
GTK_PRINTER_CUPS (printer)->ipp_version_major = info->ipp_version_major;
GTK_PRINTER_CUPS (printer)->ipp_version_minor = info->ipp_version_minor;
@@ -2482,11 +2444,8 @@ cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
set_printer_icon_name_from_info (printer, info);
- if (gtk_printer_is_new (printer))
- {
- g_signal_emit_by_name (backend, "printer-added", printer);
- gtk_printer_set_is_new (printer, FALSE);
- }
+ gtk_printer_set_has_details (printer, TRUE);
+ g_signal_emit_by_name (printer, "details-acquired", TRUE);
if (status_changed)
g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
@@ -2498,9 +2457,6 @@ cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
}
done:
- if (list_has_changed)
- g_signal_emit_by_name (backend, "printer-list-changed");
-
if (!cups_backend->got_default_printer &&
gtk_print_backend_printer_list_is_done (backend) &&
cups_backend->avahi_default_printer != NULL)
@@ -2508,6 +2464,7 @@ done:
set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
+ g_free (info->state_msg);
g_slice_free (PrinterSetupInfo, info);
gdk_threads_leave ();
@@ -2517,25 +2474,14 @@ static void
cups_request_avahi_printer_info (const gchar *printer_uri,
const gchar *host,
gint port,
- const gchar *name,
- const gchar *type,
- const gchar *domain,
GtkPrintBackendCups *backend)
{
GtkCupsRequest *request;
- AvahiService *service;
http_t *http;
http = httpConnect (host, port);
if (http)
{
- service = (AvahiService *) g_new0 (AvahiService, 1);
- service->name = g_strdup (name);
- service->type = g_strdup (type);
- service->domain = g_strdup (domain);
- service->host = g_strdup (host);
- service->port = port;
-
request = gtk_cups_request_new_with_username (http,
GTK_CUPS_POST,
IPP_GET_PRINTER_ATTRIBUTES,
@@ -2556,22 +2502,118 @@ cups_request_avahi_printer_info (const gchar *printer_uri,
cups_request_execute (backend,
request,
(GtkPrintCupsResponseCallbackFunc) cups_request_avahi_printer_info_cb,
- service,
- (GDestroyNotify) avahi_service_free);
+ NULL,
+ NULL);
}
}
typedef struct
{
gchar *printer_uri;
+ gchar *location;
gchar *host;
gint port;
+ gchar *printer_name;
gchar *name;
+ gboolean got_printer_type;
+ guint printer_type;
+ gboolean got_printer_state;
+ guint printer_state;
gchar *type;
gchar *domain;
GtkPrintBackendCups *backend;
} AvahiConnectionTestData;
+/*
+ * Create new GtkPrinter from informations included in TXT records.
+ */
+static void
+create_cups_printer_from_avahi_data (AvahiConnectionTestData *data)
+{
+ PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
+ GtkPrinter *printer;
+
+ info->avahi_printer = TRUE;
+ info->printer_name = data->printer_name;
+ info->printer_uri = data->printer_uri;
+
+ if (data->got_printer_state)
+ info->state = data->printer_state;
+
+ info->got_printer_type = data->got_printer_type;
+ if (data->got_printer_type)
+ {
+ if (data->printer_type & CUPS_PRINTER_DEFAULT)
+ info->default_printer = TRUE;
+ else
+ info->default_printer = FALSE;
+
+ if (data->printer_type & CUPS_PRINTER_REMOTE)
+ info->remote_printer = TRUE;
+ else
+ info->remote_printer = FALSE;
+
+ if (data->printer_type & CUPS_PRINTER_REJECTING)
+ info->is_accepting_jobs = FALSE;
+ else
+ info->is_accepting_jobs = TRUE;
+
+ if (info->default_printer &&
+ data->backend->avahi_default_printer == NULL)
+ data->backend->avahi_default_printer = g_strdup (info->printer_name);
+ }
+
+ set_info_state_message (info);
+
+ printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (data->backend), data->printer_name);
+ if (printer == NULL)
+ {
+ printer = cups_create_printer (data->backend, info);
+
+ if (data->got_printer_type)
+ {
+ gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
+ GTK_PRINTER_CUPS (printer)->remote = info->remote_printer;
+
+ if (info->default_printer &&
+ data->backend->avahi_default_printer == NULL)
+ data->backend->avahi_default_printer = g_strdup (info->printer_name);
+ }
+
+ if (data->got_printer_state)
+ GTK_PRINTER_CUPS (printer)->state = info->state;
+
+ GTK_PRINTER_CUPS (printer)->avahi_name = g_strdup (data->name);
+ GTK_PRINTER_CUPS (printer)->avahi_type = g_strdup (data->type);
+ GTK_PRINTER_CUPS (printer)->avahi_domain = g_strdup (data->domain);
+ g_free (GTK_PRINTER_CUPS (printer)->hostname);
+ GTK_PRINTER_CUPS (printer)->hostname = g_strdup (data->host);
+ GTK_PRINTER_CUPS (printer)->port = data->port;
+ gtk_printer_set_location (printer, data->location);
+ gtk_printer_set_state_message (printer, info->state_msg);
+
+ set_printer_icon_name_from_info (printer, info);
+
+ if (!gtk_printer_is_active (printer))
+ gtk_printer_set_is_active (printer, TRUE);
+
+ g_signal_emit_by_name (data->backend, "printer-added", printer);
+ gtk_printer_set_is_new (printer, FALSE);
+ g_signal_emit_by_name (data->backend, "printer-list-changed");
+
+ if (!data->backend->got_default_printer &&
+ gtk_print_backend_printer_list_is_done (GTK_PRINT_BACKEND (data->backend)) &&
+ data->backend->avahi_default_printer != NULL)
+ set_default_printer (data->backend, data->backend->avahi_default_printer);
+
+ /* The ref is held by GtkPrintBackend, in add_printer() */
+ g_object_unref (printer);
+ }
+
+ g_free (info->state_msg);
+ g_slice_free (PrinterSetupInfo, info);
+}
+
static void
avahi_connection_test_cb (GObject *source_object,
GAsyncResult *res,
@@ -2590,23 +2632,46 @@ avahi_connection_test_cb (GObject *source_object,
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
- cups_request_avahi_printer_info (data->printer_uri,
- data->host,
- data->port,
- data->name,
- data->type,
- data->domain,
- data->backend);
+ create_cups_printer_from_avahi_data (data);
}
g_free (data->printer_uri);
+ g_free (data->location);
g_free (data->host);
+ g_free (data->printer_name);
g_free (data->name);
g_free (data->type);
g_free (data->domain);
g_free (data);
}
+gboolean
+avahi_txt_get_key_value_pair (const gchar *entry,
+ gchar **key,
+ gchar **value)
+{
+ const gchar *equal_sign;
+
+ *key = NULL;
+ *value = NULL;
+
+ if (entry != NULL)
+ {
+ /* See RFC 6763 section 6.3 */
+ equal_sign = strstr (entry, "=");
+
+ if (equal_sign != NULL)
+ {
+ *key = g_strndup (entry, equal_sign - entry);
+ *value = g_strdup (equal_sign + 1);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
avahi_service_resolver_cb (GObject *source_object,
GAsyncResult *res,
@@ -2626,8 +2691,12 @@ avahi_service_resolver_cb (GObject *source_object,
guint32 flags;
guint16 port;
GError *error = NULL;
- gchar *suffix = NULL;
+ gchar *queue_name = NULL;
gchar *tmp;
+ gchar *printer_name;
+ gchar *endptr;
+ gchar *key;
+ gchar *value;
gint interface;
gint protocol;
gint aprotocol;
@@ -2653,6 +2722,8 @@ avahi_service_resolver_cb (GObject *source_object,
&txt,
&flags);
+ data = g_new0 (AvahiConnectionTestData, 1);
+
for (i = 0; i < g_variant_n_children (txt); i++)
{
child = g_variant_get_child_value (txt, i);
@@ -2663,32 +2734,61 @@ avahi_service_resolver_cb (GObject *source_object,
tmp[j] = g_variant_get_byte (g_variant_get_child_value (child, j));
}
- if (g_str_has_prefix (tmp, "rp="))
+ if (!avahi_txt_get_key_value_pair (tmp, &key, &value))
{
- suffix = g_strdup (tmp + 3);
g_free (tmp);
- break;
+ continue;
}
+ if (g_strcmp0 (key, "rp") == 0)
+ {
+ queue_name = g_strdup (value);
+
+ printer_name = g_strrstr (queue_name, "/");
+ if (printer_name != NULL)
+ data->printer_name = g_strdup (printer_name + 1);
+ else
+ data->printer_name = g_strdup (queue_name);
+ }
+ else if (g_strcmp0 (key, "note") == 0)
+ {
+ data->location = g_strdup (value);
+ }
+ else if (g_strcmp0 (key, "printer-type") == 0)
+ {
+ endptr = NULL;
+ data->printer_type = g_ascii_strtoull (value, &endptr, 16);
+ if (data->printer_type != 0 || endptr != value)
+ data->got_printer_type = TRUE;
+ }
+ else if (g_strcmp0 (key, "printer-state") == 0)
+ {
+ endptr = NULL;
+ data->printer_state = g_ascii_strtoull (value, &endptr, 10);
+ if (data->printer_state != 0 || endptr != value)
+ data->got_printer_state = TRUE;
+ }
+
+ g_clear_pointer (&key, g_free);
+ g_clear_pointer (&value, g_free);
g_free (tmp);
}
- if (suffix)
+ if (queue_name)
{
if (g_strcmp0 (type, "_ipp._tcp") == 0)
protocol_string = "ipp";
else
protocol_string = "ipps";
- data = g_new0 (AvahiConnectionTestData, 1);
-
if (aprotocol == AVAHI_PROTO_INET6)
- data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port, suffix);
+ data->printer_uri = g_strdup_printf ("%s://[%s]:%u/%s", protocol_string, address, port,
queue_name);
else
- data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port, suffix);
+ data->printer_uri = g_strdup_printf ("%s://%s:%u/%s", protocol_string, address, port,
queue_name);
data->host = g_strdup (address);
data->port = port;
+
data->name = g_strdup (name);
data->type = g_strdup (type);
data->domain = g_strdup (domain);
@@ -2701,7 +2801,13 @@ avahi_service_resolver_cb (GObject *source_object,
backend->avahi_cancellable,
avahi_connection_test_cb,
data);
- g_free (suffix);
+ g_free (queue_name);
+ }
+ else
+ {
+ g_free (data->printer_name);
+ g_free (data->location);
+ g_free (data);
}
g_variant_unref (output);
@@ -3326,21 +3432,30 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend,
{
gboolean success = FALSE;
- /* If we get a 404 then it is just a raw printer without a ppd
- and not an error. Standalone Avahi printers also don't have
- PPD files. */
- if (((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
- (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
#ifdef HAVE_CUPS_API_1_6
- || GTK_PRINTER_CUPS (printer)->avahi_browsed
+ /* Standalone Avahi printers don't have PPD files. */
+ if (GTK_PRINTER_CUPS (printer)->avahi_browsed)
+ {
+ cups_request_avahi_printer_info (GTK_PRINTER_CUPS (printer)->printer_uri,
+ GTK_PRINTER_CUPS (printer)->hostname,
+ GTK_PRINTER_CUPS (printer)->port,
+ GTK_PRINT_BACKEND_CUPS (gtk_printer_get_backend (printer)));
+ }
+ else
#endif
- )
{
- gtk_printer_set_has_details (printer, TRUE);
- success = TRUE;
+ /* If we get a 404 then it is just a raw printer without a ppd
+ and not an error. */
+ if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
+ (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
+ {
+ gtk_printer_set_has_details (printer, TRUE);
+ success = TRUE;
+ }
+
+ g_signal_emit_by_name (printer, "details-acquired", success);
}
- g_signal_emit_by_name (printer, "details-acquired", success);
goto done;
}
@@ -3377,7 +3492,11 @@ cups_request_ppd (GtkPrinter *printer)
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: %s\n", G_STRFUNC));
- if (cups_printer->remote)
+ if (cups_printer->remote
+#ifdef HAVE_CUPS_API_1_6
+ && !cups_printer->avahi_browsed
+#endif
+ )
{
GtkCupsConnectionState state;
@@ -3788,7 +3907,11 @@ cups_printer_request_details (GtkPrinter *printer)
if (!cups_printer->reading_ppd &&
gtk_printer_cups_get_ppd (cups_printer) == NULL)
{
- if (cups_printer->remote)
+ if (cups_printer->remote
+#ifdef HAVE_CUPS_API_1_6
+ && !cups_printer->avahi_browsed
+#endif
+ )
{
if (cups_printer->get_remote_ppd_poll == 0)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]