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
This commit is contained in:
parent
da86918c32
commit
376e2c003d
@ -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;
|
||||
set_info_state_message (info);
|
||||
|
||||
printer = gtk_print_backend_find_printer (backend, info->printer_name);
|
||||
if (printer != NULL &&
|
||||
GTK_PRINTER_CUPS (printer)->avahi_browsed)
|
||||
{
|
||||
g_object_ref (printer);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
set_info_state_message (info);
|
||||
|
||||
printer = gtk_print_backend_find_printer (backend, info->printer_name);
|
||||
if (!printer)
|
||||
{
|
||||
printer = cups_create_printer (cups_backend, info);
|
||||
list_has_changed = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_ref (printer);
|
||||
}
|
||||
|
||||
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
|
||||
#endif
|
||||
)
|
||||
/* Standalone Avahi printers don't have PPD files. */
|
||||
if (GTK_PRINTER_CUPS (printer)->avahi_browsed)
|
||||
{
|
||||
gtk_printer_set_has_details (printer, TRUE);
|
||||
success = TRUE;
|
||||
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
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user