summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorMarek Kasik <mkasik@redhat.com>2013-03-04 14:29:24 +0100
committerMarek Kasik <mkasik@redhat.com>2013-03-04 14:30:49 +0100
commiteed9e72e831e54f4a405474316835685f3a61e79 (patch)
tree4b3451f58d8458c7f16996237184c42cc127eb62 /modules
parentbfb327deda4983adb3f2d317d4b763e59e5f109e (diff)
downloadgtk+-eed9e72e831e54f4a405474316835685f3a61e79.tar.gz
printing: List Avahi printers
Show printers advertised by avahi on local network. CUPS backend now looks for _ipps._tcp and _ipp._tcp services offered by avahi. If it finds such a service (printer) it requests its attributes through IPP_GET_PRINTER_ATTRIBUTES ipp request and adds it to the list of printers. Such printer behaves like a remote printer then. If an avahi printer is a default printer then it is considered default by the backend only if there is no local or remote default printer. This functionality is enabled when building Gtk+ with CUPS 1.6 or later because it replaces browsing protocol removed in CUPS 1.6. https://bugzilla.gnome.org/show_bug.cgi?id=688956
Diffstat (limited to 'modules')
-rw-r--r--modules/printbackends/cups/Makefile.am3
-rw-r--r--modules/printbackends/cups/gtkcupsutils.c21
-rw-r--r--modules/printbackends/cups/gtkcupsutils.h3
-rw-r--r--modules/printbackends/cups/gtkprintbackendcups.c1124
-rw-r--r--modules/printbackends/cups/gtkprintercups.c35
-rw-r--r--modules/printbackends/cups/gtkprintercups.h11
6 files changed, 1039 insertions, 158 deletions
diff --git a/modules/printbackends/cups/Makefile.am b/modules/printbackends/cups/Makefile.am
index e9d4c2fdd1..2e5b92791b 100644
--- a/modules/printbackends/cups/Makefile.am
+++ b/modules/printbackends/cups/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
-I$(top_builddir)/gdk \
$(CUPS_CFLAGS) \
$(COLORD_CFLAGS) \
+ $(AVAHI_CFLAGS) \
-DGTK_COMPILATION \
-DGTK_PRINT_BACKEND_ENABLE_UNSUPPORTED \
$(GTK_DEP_CFLAGS) \
@@ -37,6 +38,6 @@ noinst_HEADERS = \
gtkcupsutils.h
libprintbackend_cups_la_LDFLAGS = -avoid-version -module $(no_undefined)
-libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS)
+libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS) $(AVAHI_LIBS)
-include $(top_srcdir)/git.mk
diff --git a/modules/printbackends/cups/gtkcupsutils.c b/modules/printbackends/cups/gtkcupsutils.c
index 15132a8265..f0bb951b5d 100644
--- a/modules/printbackends/cups/gtkcupsutils.c
+++ b/modules/printbackends/cups/gtkcupsutils.c
@@ -87,6 +87,20 @@ static GtkCupsRequestStateFunc get_states[] = {
#define ippSetState(ipp_request, ipp_state) ipp_request->state = ipp_state
#define ippGetString(attr, index, foo) attr->values[index].string.text
#define ippGetCount(attr) attr->num_values
+
+int
+ippSetVersion (ipp_t *ipp,
+ int major,
+ int minor)
+{
+ if (!ipp || major < 0 || minor < 0)
+ return 0;
+
+ ipp->request.any.version[0] = major;
+ ipp->request.any.version[1] = minor;
+
+ return 1;
+}
#endif
static void
@@ -656,6 +670,13 @@ gtk_cups_request_encode_option (GtkCupsRequest *request,
}
}
+void
+gtk_cups_request_set_ipp_version (GtkCupsRequest *request,
+ gint major,
+ gint minor)
+{
+ ippSetVersion (request->ipp_request, major, minor);
+}
static void
_connect (GtkCupsRequest *request)
diff --git a/modules/printbackends/cups/gtkcupsutils.h b/modules/printbackends/cups/gtkcupsutils.h
index e49a5d3bc5..55186f590b 100644
--- a/modules/printbackends/cups/gtkcupsutils.h
+++ b/modules/printbackends/cups/gtkcupsutils.h
@@ -178,6 +178,9 @@ gboolean gtk_cups_request_is_done (GtkCupsRequest *
void gtk_cups_request_encode_option (GtkCupsRequest *request,
const gchar *option,
const gchar *value);
+void gtk_cups_request_set_ipp_version (GtkCupsRequest *request,
+ gint major,
+ gint minor);
gboolean gtk_cups_result_is_error (GtkCupsResult *result);
ipp_t * gtk_cups_result_get_response (GtkCupsResult *result);
GtkCupsErrorType gtk_cups_result_get_error_type (GtkCupsResult *result);
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c
index 96f4be4103..ffecd18a13 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -53,6 +53,12 @@
#include <gtk/gtkprintbackend.h>
#include <gtk/gtkunixprint.h>
#include <gtk/gtkprinter-private.h>
+#ifdef HAVE_AVAHI_BROWSING
+#include <avahi-gobject/ga-client.h>
+#include <avahi-gobject/ga-service-browser.h>
+#include <avahi-gobject/ga-service-resolver.h>
+#include <avahi-gobject/ga-error.h>
+#endif
#include "gtkprintbackendcups.h"
#include "gtkprintercups.h"
@@ -137,6 +143,13 @@ struct _GtkPrintBackendCups
#ifdef HAVE_COLORD
CdClient *colord_client;
#endif
+#ifdef HAVE_AVAHI_BROWSING
+ gchar *avahi_default_printer;
+ GList *avahi_resolvers;
+ GaServiceBrowser *avahi_ipp_browser;
+ GaServiceBrowser *avahi_ipps_browser;
+ GaClient *avahi_client;
+#endif
};
static GObjectClass *backend_parent_class;
@@ -203,6 +216,11 @@ void overwrite_and_free (gpointer
static gboolean is_address_local (const gchar *address);
static gboolean request_auth_info (gpointer data);
+#ifdef HAVE_AVAHI_BROWSING
+static void avahi_data_free (GtkPrintBackendCups *cups_backend);
+static void avahi_request_printer_list (GtkPrintBackendCups *cups_backend);
+#endif
+
static void
gtk_print_backend_cups_register_type (GTypeModule *module)
{
@@ -261,6 +279,15 @@ pb_module_create (void)
#define ippGetName(attr) attr->name
#define ippGetCount(attr) attr->num_values
#define ippGetGroupTag(attr) attr->group_tag
+
+static int
+ippGetRange (ipp_attribute_t *attr,
+ int element,
+ int *upper)
+{
+ *upper = attr->values[element].range.upper;
+ return (attr->values[element].range.lower);
+}
#endif
/*
* GtkPrintBackendCups
@@ -584,7 +611,7 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
GtkPrinterCups *cups_printer;
CupsPrintStreamData *ps;
CupsOptionsData *options_data;
- GtkCupsRequest *request;
+ GtkCupsRequest *request = NULL;
GtkPrintSettings *settings;
const gchar *title;
char printer_absolute_uri[HTTP_MAX_URI];
@@ -595,23 +622,74 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend,
cups_printer = GTK_PRINTER_CUPS (gtk_print_job_get_printer (job));
settings = gtk_print_job_get_settings (job);
- request = gtk_cups_request_new_with_username (NULL,
- GTK_CUPS_POST,
- IPP_PRINT_JOB,
- data_io,
- NULL,
- cups_printer->device_uri,
- GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+#ifdef HAVE_AVAHI_BROWSING
+ if (cups_printer->avahi_browsed)
+ {
+ http_t *http;
+
+ http = httpConnect (cups_printer->hostname, cups_printer->port);
+ if (http)
+ {
+ request = gtk_cups_request_new_with_username (http,
+ GTK_CUPS_POST,
+ IPP_PRINT_JOB,
+ data_io,
+ cups_printer->hostname,
+ cups_printer->device_uri,
+ GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+ g_snprintf (printer_absolute_uri, HTTP_MAX_URI, cups_printer->printer_uri);
+ }
+ else
+ {
+ GError *error = NULL;
+
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error connecting to %s:%d",
+ cups_printer->hostname,
+ cups_printer->port));
+
+ error = g_error_new (gtk_print_error_quark (),
+ GTK_CUPS_ERROR_GENERAL,
+ "Error connecting to %s",
+ cups_printer->hostname);
+
+ gtk_print_job_set_status (job, GTK_PRINT_STATUS_FINISHED_ABORTED);
+
+ if (callback)
+ {
+ callback (job, user_data, error);
+ }
+
+ g_clear_error (&error);
+
+ return;
+ }
+ }
+ else
+#endif
+ {
+ request = gtk_cups_request_new_with_username (NULL,
+ GTK_CUPS_POST,
+ IPP_PRINT_JOB,
+ data_io,
+ NULL,
+ cups_printer->device_uri,
+ GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+
+ httpAssembleURIf (HTTP_URI_CODING_ALL,
+ printer_absolute_uri,
+ sizeof (printer_absolute_uri),
+ "ipp",
+ NULL,
+ "localhost",
+ ippPort (),
+ "/printers/%s",
+ gtk_printer_get_name (gtk_print_job_get_printer (job)));
+ }
- httpAssembleURIf (HTTP_URI_CODING_ALL,
- printer_absolute_uri,
- sizeof (printer_absolute_uri),
- "ipp",
- NULL,
- "localhost",
- ippPort (),
- "/printers/%s",
- gtk_printer_get_name (gtk_print_job_get_printer (job)));
+ gtk_cups_request_set_ipp_version (request,
+ cups_printer->ipp_version_major,
+ cups_printer->ipp_version_minor);
gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION,
IPP_TAG_URI, "printer-uri",
@@ -681,6 +759,14 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
backend_cups->colord_client = cd_client_new ();
#endif
+#ifdef HAVE_AVAHI_BROWSING
+ backend_cups->avahi_default_printer = NULL;
+ backend_cups->avahi_resolvers = NULL;
+ backend_cups->avahi_ipp_browser = NULL;
+ backend_cups->avahi_ipps_browser = NULL;
+ backend_cups->avahi_client = NULL;
+#endif
+
cups_get_local_default_printer (backend_cups);
}
@@ -711,6 +797,10 @@ gtk_print_backend_cups_finalize (GObject *object)
g_object_unref (backend_cups->colord_client);
#endif
+#ifdef HAVE_AVAHI_BROWSING
+ avahi_data_free (backend_cups);
+#endif
+
backend_parent_class->finalize (object);
}
@@ -1681,6 +1771,30 @@ static const char * printer_strings[] =
N_("There is a problem on printer '%s'.")
};
+/* Attributes we're interested in for printers */
+static const char * const printer_attrs[] =
+ {
+ "printer-name",
+ "printer-uri-supported",
+ "member-uris",
+ "printer-location",
+ "printer-info",
+ "printer-state-message",
+ "printer-state-reasons",
+ "printer-state",
+ "queued-job-count",
+ "printer-is-accepting-jobs",
+ "job-sheets-supported",
+ "job-sheets-default",
+ "printer-type",
+ "auth-info-required",
+ "number-up-default",
+ "ipp-versions-supported",
+ "multiple-document-handling-supported",
+ "copies-supported",
+ "number-up-supported"
+ };
+
typedef enum
{
GTK_PRINTER_STATE_LEVEL_NONE = 0,
@@ -1708,11 +1822,89 @@ typedef struct
gboolean default_printer;
gboolean got_printer_type;
gboolean remote_printer;
+#ifdef HAVE_AVAHI_BROWSING
+ gboolean avahi_printer;
+#endif
gchar **auth_info_required;
gint default_number_up;
+ guchar ipp_version_major;
+ guchar ipp_version_minor;
+ gboolean supports_copies;
+ gboolean supports_collate;
+ gboolean supports_number_up;
} PrinterSetupInfo;
static void
+get_ipp_version (const char *ipp_version_string,
+ guchar *ipp_version_major,
+ guchar *ipp_version_minor)
+{
+ gchar **ipp_version_strv;
+ gchar *endptr;
+
+ *ipp_version_major = 1;
+ *ipp_version_minor = 1;
+
+ if (ipp_version_string)
+ {
+ ipp_version_strv = g_strsplit (ipp_version_string, ".", 0);
+
+ if (ipp_version_strv)
+ {
+ if (g_strv_length (ipp_version_strv) == 2)
+ {
+ *ipp_version_major = (guchar) g_ascii_strtoull (ipp_version_strv[0], &endptr, 10);
+ if (endptr == ipp_version_strv[0])
+ *ipp_version_major = 1;
+
+ *ipp_version_minor = (guchar) g_ascii_strtoull (ipp_version_strv[1], &endptr, 10);
+ if (endptr == ipp_version_strv[1])
+ *ipp_version_minor = 1;
+ }
+
+ g_strfreev (ipp_version_strv);
+ }
+ }
+}
+
+static void
+get_server_ipp_version (guchar *ipp_version_major,
+ guchar *ipp_version_minor)
+{
+ *ipp_version_major = 1;
+ *ipp_version_minor = 1;
+
+ if (IPP_VERSION && strlen (IPP_VERSION) == 2)
+ {
+ *ipp_version_major = (unsigned char) IPP_VERSION[0];
+ *ipp_version_minor = (unsigned char) IPP_VERSION[1];
+ }
+}
+
+static gint
+ipp_version_cmp (guchar ipp_version_major1,
+ guchar ipp_version_minor1,
+ guchar ipp_version_major2,
+ guchar ipp_version_minor2)
+{
+ if (ipp_version_major1 == ipp_version_major2 &&
+ ipp_version_minor1 == ipp_version_minor2)
+ {
+ return 0;
+ }
+ else if (ipp_version_major1 < ipp_version_major2 ||
+ (ipp_version_major1 == ipp_version_major2 &&
+ ipp_version_minor1 < ipp_version_minor2))
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static void
cups_printer_handle_attribute (GtkPrintBackendCups *cups_backend,
ipp_attribute_t *attr,
PrinterSetupInfo *info)
@@ -1839,6 +2031,63 @@ cups_printer_handle_attribute (GtkPrintBackendCups *cups_backend,
{
info->default_number_up = ippGetInteger (attr, 0);
}
+ else if (g_strcmp0 (ippGetName (attr), "ipp-versions-supported") == 0)
+ {
+ guchar server_ipp_version_major;
+ guchar server_ipp_version_minor;
+ guchar ipp_version_major;
+ guchar ipp_version_minor;
+
+ get_server_ipp_version (&server_ipp_version_major,
+ &server_ipp_version_minor);
+
+ for (i = 0; i < ippGetCount (attr); i++)
+ {
+ get_ipp_version (ippGetString (attr, i, NULL),
+ &ipp_version_major,
+ &ipp_version_minor);
+
+ if (ipp_version_cmp (ipp_version_major,
+ ipp_version_minor,
+ info->ipp_version_major,
+ info->ipp_version_minor) > 0 &&
+ ipp_version_cmp (ipp_version_major,
+ ipp_version_minor,
+ server_ipp_version_major,
+ server_ipp_version_minor) <= 0)
+ {
+ info->ipp_version_major = ipp_version_major;
+ info->ipp_version_minor = ipp_version_minor;
+ }
+ }
+ }
+ else if (g_strcmp0 (ippGetName (attr), "number-up-supported") == 0)
+ {
+ if (ippGetCount (attr) == 6)
+ {
+ info->supports_number_up = TRUE;
+ }
+ }
+ else if (g_strcmp0 (ippGetName (attr), "copies-supported") == 0)
+ {
+ int upper = 1;
+
+ ippGetRange (attr, 0, &upper);
+ if (upper > 1)
+ {
+ info->supports_copies = TRUE;
+ }
+ }
+ else if (g_strcmp0 (ippGetName (attr), "multiple-document-handling-supported") == 0)
+ {
+ for (i = 0; i < ippGetCount (attr); i++)
+ {
+ if (g_strcmp0 (ippGetString (attr, i, NULL), "separate-documents-collated-copies") == 0)
+ {
+ info->supports_collate = TRUE;
+ }
+ }
+ }
else
{
GTK_NOTE (PRINTING,
@@ -1862,9 +2111,16 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
char *cups_server; /* CUPS server */
#ifdef HAVE_COLORD
- cups_printer = gtk_printer_cups_new (info->printer_name,
- backend,
- cups_backend->colord_client);
+#ifdef HAVE_AVAHI_BROWSING
+ if (info->avahi_printer)
+ cups_printer = gtk_printer_cups_new (info->printer_name,
+ backend,
+ NULL);
+ else
+#endif
+ cups_printer = gtk_printer_cups_new (info->printer_name,
+ backend,
+ cups_backend->colord_client);
#else
cups_printer = gtk_printer_cups_new (info->printer_name, backend, NULL);
#endif
@@ -1921,7 +2177,8 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
cups_printer->default_cover_before = g_strdup (info->default_cover_before);
cups_printer->default_cover_after = g_strdup (info->default_cover_after);
- cups_printer->default_number_up = info->default_number_up;
+ if (info->default_number_up > 0)
+ cups_printer->default_number_up = info->default_number_up;
cups_printer->hostname = g_strdup (hostname);
cups_printer->port = port;
@@ -1935,11 +2192,592 @@ cups_create_printer (GtkPrintBackendCups *cups_backend,
strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
gtk_printer_set_is_default (printer, TRUE);
+#ifdef HAVE_AVAHI_BROWSING
+ cups_printer->avahi_browsed = info->avahi_printer;
+#endif
gtk_print_backend_add_printer (backend, printer);
return printer;
}
+static void
+set_printer_icon_name_from_info (GtkPrinter *printer,
+ PrinterSetupInfo *info)
+{
+ /* Set printer icon according to importance
+ (none, report, warning, error - report is omitted). */
+ if (info->reason_level == GTK_PRINTER_STATE_LEVEL_ERROR)
+ gtk_printer_set_icon_name (printer, "printer-error");
+ else if (info->reason_level == GTK_PRINTER_STATE_LEVEL_WARNING)
+ gtk_printer_set_icon_name (printer, "printer-warning");
+ else if (gtk_printer_is_paused (printer))
+ gtk_printer_set_icon_name (printer, "printer-paused");
+ else
+ gtk_printer_set_icon_name (printer, "printer");
+}
+
+static void
+set_info_state_message (PrinterSetupInfo *info)
+{
+ gint i;
+
+ if (info->state_msg && strlen (info->state_msg) == 0)
+ {
+ gchar *tmp_msg2 = NULL;
+ if (info->is_paused && !info->is_accepting_jobs)
+ /* Translators: this is a printer status. */
+ tmp_msg2 = g_strdup ( N_("Paused ; Rejecting Jobs"));
+ if (info->is_paused && info->is_accepting_jobs)
+ /* Translators: this is a printer status. */
+ tmp_msg2 = g_strdup ( N_("Paused"));
+ if (!info->is_paused && !info->is_accepting_jobs)
+ /* Translators: this is a printer status. */
+ tmp_msg2 = g_strdup ( N_("Rejecting Jobs"));
+
+ if (tmp_msg2 != NULL)
+ {
+ g_free (info->state_msg);
+ info->state_msg = tmp_msg2;
+ }
+ }
+
+ /* Set description of the reason and combine it with printer-state-message. */
+ if (info->reason_msg)
+ {
+ gchar *reason_msg_desc = NULL;
+ gboolean found = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (printer_messages); i++)
+ {
+ if (strncmp (info->reason_msg, printer_messages[i],
+ strlen (printer_messages[i])) == 0)
+ {
+ reason_msg_desc = g_strdup_printf (printer_strings[i],
+ info->printer_name);
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ info->reason_level = GTK_PRINTER_STATE_LEVEL_NONE;
+
+ if (info->reason_level >= GTK_PRINTER_STATE_LEVEL_WARNING)
+ {
+ if (strlen (info->state_msg) == 0)
+ {
+ g_free (info->state_msg);
+ info->state_msg = reason_msg_desc;
+ reason_msg_desc = NULL;
+ }
+ else
+ {
+ gchar *tmp_msg = NULL;
+ tmp_msg = g_strjoin (" ; ", info->state_msg,
+ reason_msg_desc, NULL);
+ g_free (info->state_msg);
+ info->state_msg = tmp_msg;
+ }
+ }
+
+ g_free (reason_msg_desc);
+ }
+}
+
+static void
+set_default_printer (GtkPrintBackendCups *cups_backend,
+ const gchar *default_printer_name)
+{
+ cups_backend->default_printer = g_strdup (default_printer_name);
+ cups_backend->got_default_printer = TRUE;
+
+ if (cups_backend->default_printer != NULL)
+ {
+ GtkPrinter *default_printer = NULL;
+ default_printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (cups_backend),
+ cups_backend->default_printer);
+ if (default_printer != NULL)
+ {
+ gtk_printer_set_is_default (default_printer, TRUE);
+ g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend),
+ "printer-status-changed", default_printer);
+ }
+ }
+}
+
+#ifdef HAVE_AVAHI_BROWSING
+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
+avahi_data_free (GtkPrintBackendCups *cups_backend)
+{
+ if (cups_backend)
+ {
+ g_clear_pointer (&cups_backend->avahi_default_printer, g_free);
+ g_list_free_full (cups_backend->avahi_resolvers, g_object_unref);
+ cups_backend->avahi_resolvers = NULL;
+ g_clear_object (&cups_backend->avahi_ipp_browser);
+ g_clear_object (&cups_backend->avahi_ipps_browser);
+ g_clear_object (&cups_backend->avahi_client);
+ }
+}
+
+static void
+cups_request_avahi_printer_info_cb (GtkPrintBackendCups *cups_backend,
+ GtkCupsResult *result,
+ gpointer user_data)
+{
+ 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;
+
+ gdk_threads_enter ();
+
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: %s\n", G_STRFUNC));
+
+ if (gtk_cups_result_is_error (result))
+ {
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error getting printer info: %s %d %d",
+ gtk_cups_result_get_error_string (result),
+ gtk_cups_result_get_error_type (result),
+ gtk_cups_result_get_error_code (result)));
+
+ goto done;
+ }
+
+ response = gtk_cups_result_get_response (result);
+ attr = ippFirstAttribute (response);
+ while (attr && ippGetGroupTag (attr) != IPP_TAG_PRINTER)
+ attr = ippNextAttribute (response);
+
+ if (attr)
+ {
+ while (attr && ippGetGroupTag (attr) == IPP_TAG_PRINTER)
+ {
+ cups_printer_handle_attribute (cups_backend, attr, info);
+ attr = ippNextAttribute (response);
+ }
+
+ 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)
+ {
+ 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;
+ GTK_PRINTER_CUPS (printer)->supports_copies = info->supports_copies;
+ GTK_PRINTER_CUPS (printer)->supports_collate = info->supports_collate;
+ GTK_PRINTER_CUPS (printer)->supports_number_up = info->supports_number_up;
+ status_changed = gtk_printer_set_job_count (printer, info->job_count);
+ status_changed |= gtk_printer_set_location (printer, info->location);
+ status_changed |= gtk_printer_set_description (printer, info->description);
+ status_changed |= gtk_printer_set_state_message (printer, info->state_msg);
+ status_changed |= gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
+
+ 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);
+ }
+
+ if (status_changed)
+ g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
+ "printer-status-changed", printer);
+
+ /* The ref is held by GtkPrintBackend, in add_printer() */
+ g_object_unref (printer);
+ }
+ }
+
+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)
+ {
+ set_default_printer (cups_backend, cups_backend->avahi_default_printer);
+ }
+
+ g_slice_free (PrinterSetupInfo, info);
+
+ gdk_threads_leave ();
+}
+
+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,
+ NULL,
+ NULL,
+ NULL,
+ backend->username);
+
+ gtk_cups_request_set_ipp_version (request, 1, 1);
+
+ gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+
+ gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", G_N_ELEMENTS (printer_attrs),
+ NULL, printer_attrs);
+
+ cups_request_execute (backend,
+ request,
+ (GtkPrintCupsResponseCallbackFunc) cups_request_avahi_printer_info_cb,
+ service,
+ (GDestroyNotify) avahi_service_free);
+ }
+}
+
+static void
+avahi_resolver_found_cb (GaServiceResolver *resolver,
+ int interface,
+ GaProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ guint16 port,
+ AvahiStringList *txt,
+ glong flags,
+ gpointer *user_data)
+{
+ GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+ AvahiStringList *item;
+ gchar host[AVAHI_ADDRESS_STR_MAX];
+ gchar *suffix = NULL;
+ gchar *printer_uri;
+
+ avahi_address_snprint (host, sizeof (host), address);
+
+ item = avahi_string_list_find (txt, "rp");
+ if (item)
+ avahi_string_list_get_pair (item, NULL, &suffix, NULL);
+
+ if (suffix)
+ {
+ if (g_strcmp0 (type, "_ipp._tcp") == 0)
+ printer_uri = g_strdup_printf ("ipp://%s:%u/%s", host, port, suffix);
+ else
+ printer_uri = g_strdup_printf ("ipps://%s:%u/%s", host, port, suffix);
+
+ cups_request_avahi_printer_info (printer_uri,
+ host,
+ port,
+ name,
+ type,
+ domain,
+ backend);
+
+ g_free (printer_uri);
+ g_free (suffix);
+ }
+}
+
+static void
+avahi_browser_new_service_cb (GaServiceBrowser *browser,
+ int interface,
+ GaProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ glong flags,
+ gpointer user_data)
+{
+ GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+ GaServiceResolver *resolver;
+ GError *error = NULL;
+
+ resolver = ga_service_resolver_new (AVAHI_IF_UNSPEC,
+ AVAHI_PROTO_UNSPEC,
+ name, type, domain,
+ AVAHI_PROTO_UNSPEC,
+ GA_LOOKUP_USE_MULTICAST);
+
+ g_signal_connect (resolver, "found",
+ G_CALLBACK (avahi_resolver_found_cb), user_data);
+
+ if (!ga_service_resolver_attach (resolver,
+ backend->avahi_client,
+ &error))
+ {
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error resolving Avahi service %s: %s",
+ name, error->message));
+ g_clear_object (&resolver);
+ g_clear_error (&error);
+ return;
+ }
+
+ backend->avahi_resolvers = g_list_append (backend->avahi_resolvers, resolver);
+}
+
+static void
+avahi_browser_removed_service_cb (GaServiceBrowser *browser,
+ int interface,
+ GaProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ glong flags,
+ gpointer user_data)
+{
+ GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+ GtkPrinterCups *printer;
+ GList *list;
+ GList *iter;
+
+ list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+ for (iter = list; iter; iter = iter->next)
+ {
+ printer = GTK_PRINTER_CUPS (iter->data);
+ if (g_strcmp0 (printer->avahi_name, name) == 0 &&
+ g_strcmp0 (printer->avahi_type, type) == 0 &&
+ g_strcmp0 (printer->avahi_domain, domain) == 0)
+ {
+ if (g_strcmp0 (gtk_printer_get_name (GTK_PRINTER (printer)),
+ backend->avahi_default_printer) == 0)
+ g_clear_pointer (&backend->avahi_default_printer, g_free);
+
+ g_signal_emit_by_name (backend, "printer-removed", printer);
+ gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+ GTK_PRINTER (printer));
+ g_signal_emit_by_name (backend, "printer-list-changed");
+ break;
+ }
+ }
+
+ g_list_free (list);
+}
+
+static gboolean
+avahi_client_renew (gpointer user_data)
+{
+ GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+ gboolean avahi_printers_removed = TRUE;
+ GList *list;
+ GList *iter;
+
+ list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+ for (iter = list; iter; iter = iter->next)
+ if (GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
+ avahi_printers_removed = FALSE;
+
+ g_list_free (list);
+
+ if (avahi_printers_removed)
+ {
+ avahi_data_free (backend);
+ avahi_request_printer_list (backend);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+static void
+avahi_client_state_changed_cb (GaClient *ga_client,
+ GaClientState state,
+ gpointer user_data)
+{
+ GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
+ GtkPrinterCups *printer;
+ gboolean list_has_changed = FALSE;
+ GError *error = NULL;
+ GList *list;
+ GList *iter;
+
+ switch (state)
+ {
+ case GA_CLIENT_STATE_FAILURE:
+ if (avahi_client_errno (ga_client->avahi_client) == AVAHI_ERR_DISCONNECTED)
+ {
+ list = gtk_print_backend_get_printer_list (GTK_PRINT_BACKEND (backend));
+
+ for (iter = list; iter; iter = iter->next)
+ {
+ printer = GTK_PRINTER_CUPS (iter->data);
+ if (printer->avahi_browsed)
+ {
+ g_signal_emit_by_name (backend, "printer-removed", printer);
+ gtk_print_backend_remove_printer (GTK_PRINT_BACKEND (backend),
+ GTK_PRINTER (printer));
+ list_has_changed = TRUE;
+ }
+ }
+
+ if (list_has_changed)
+ g_signal_emit_by_name (backend, "printer-list-changed");
+
+ g_idle_add (avahi_client_renew, backend);
+
+ g_list_free (list);
+ }
+ break;
+
+ case GA_CLIENT_STATE_S_RUNNING:
+ backend->avahi_ipp_browser = ga_service_browser_new ("_ipp._tcp");
+
+ g_signal_connect (backend->avahi_ipp_browser, "new-service",
+ G_CALLBACK (avahi_browser_new_service_cb),
+ user_data);
+
+ g_signal_connect (backend->avahi_ipp_browser, "removed-service",
+ G_CALLBACK (avahi_browser_removed_service_cb),
+ user_data);
+
+ if (!ga_service_browser_attach (backend->avahi_ipp_browser,
+ backend->avahi_client,
+ &error))
+ {
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+ error->message));
+ g_clear_object (&backend->avahi_ipp_browser);
+ g_clear_error (&error);
+ }
+
+ backend->avahi_ipps_browser = ga_service_browser_new ("_ipps._tcp");
+
+ g_signal_connect (backend->avahi_ipps_browser, "new-service",
+ G_CALLBACK (avahi_browser_new_service_cb),
+ user_data);
+
+ g_signal_connect (backend->avahi_ipps_browser, "removed-service",
+ G_CALLBACK (avahi_browser_removed_service_cb),
+ user_data);
+
+ if (!ga_service_browser_attach (backend->avahi_ipps_browser,
+ backend->avahi_client,
+ &error))
+ {
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+ error->message));
+ g_clear_object (&backend->avahi_ipps_browser);
+ g_clear_error (&error);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+avahi_request_printer_list (GtkPrintBackendCups *cups_backend)
+{
+ GError *error = NULL;
+
+ if (!cups_backend->avahi_client)
+ {
+ cups_backend->avahi_client = ga_client_new (GA_CLIENT_FLAG_NO_FAIL);
+
+ g_signal_connect (cups_backend->avahi_client, "state-changed",
+ G_CALLBACK (avahi_client_state_changed_cb),
+ cups_backend);
+
+ if (!ga_client_start (cups_backend->avahi_client, &error))
+ {
+ GTK_NOTE (PRINTING,
+ g_warning ("CUPS Backend: Error getting printer list from Avahi: %s",
+ error->message));
+ g_clear_object (&cups_backend->avahi_client);
+ g_clear_error (&error);
+ }
+ }
+}
+#endif
static void
cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
@@ -1952,6 +2790,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
gboolean list_has_changed;
GList *removed_printer_checklist;
gchar *remote_default_printer = NULL;
+ GList *iter;
gdk_threads_enter ();
@@ -1996,7 +2835,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
GtkPrinter *printer;
gboolean status_changed = FALSE;
GList *node;
- gint i;
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
/* Skip leading attributes until we hit a printer...
@@ -2017,7 +2855,6 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
GtkPrinter *printer;
gboolean status_changed = FALSE;
GList *node;
- gint i;
PrinterSetupInfo *info = g_slice_new0 (PrinterSetupInfo);
info->default_number_up = 1;
@@ -2110,88 +2947,22 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
#endif
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;
+ GTK_PRINTER_CUPS (printer)->supports_copies = info->supports_copies;
+ GTK_PRINTER_CUPS (printer)->supports_collate = info->supports_collate;
+ GTK_PRINTER_CUPS (printer)->supports_number_up = info->supports_number_up;
status_changed = gtk_printer_set_job_count (printer, info->job_count);
status_changed |= gtk_printer_set_location (printer, info->location);
status_changed |= gtk_printer_set_description (printer,
info->description);
- if (info->state_msg != NULL && strlen (info->state_msg) == 0)
- {
- gchar *tmp_msg2 = NULL;
- if (info->is_paused && !info->is_accepting_jobs)
- /* Translators: this is a printer status. */
- tmp_msg2 = g_strdup ( N_("Paused ; Rejecting Jobs"));
- if (info->is_paused && info->is_accepting_jobs)
- /* Translators: this is a printer status. */
- tmp_msg2 = g_strdup ( N_("Paused"));
- if (!info->is_paused && !info->is_accepting_jobs)
- /* Translators: this is a printer status. */
- tmp_msg2 = g_strdup ( N_("Rejecting Jobs"));
-
- if (tmp_msg2 != NULL)
- {
- g_free (info->state_msg);
- info->state_msg = tmp_msg2;
- }
- }
-
- /* Set description of the reason and combine it with printer-state-message. */
- if ( (info->reason_msg != NULL))
- {
- gchar *reason_msg_desc = NULL;
- gboolean found = FALSE;
-
- for (i = 0; i < G_N_ELEMENTS (printer_messages); i++)
- {
- if (strncmp (info->reason_msg, printer_messages[i],
- strlen (printer_messages[i])) == 0)
- {
- reason_msg_desc = g_strdup_printf (printer_strings[i],
- info->printer_name);
- found = TRUE;
- break;
- }
- }
-
- if (!found)
- info->reason_level = GTK_PRINTER_STATE_LEVEL_NONE;
-
- if (info->reason_level >= GTK_PRINTER_STATE_LEVEL_WARNING)
- {
- if (strlen (info->state_msg) == 0)
- {
- g_free (info->state_msg);
- info->state_msg = reason_msg_desc;
- reason_msg_desc = NULL;
- }
- else
- {
- gchar *tmp_msg = NULL;
- tmp_msg = g_strjoin (" ; ", info->state_msg,
- reason_msg_desc, NULL);
- g_free (info->state_msg);
- info->state_msg = tmp_msg;
- }
- }
- if (reason_msg_desc != NULL)
- g_free (reason_msg_desc);
- }
+ set_info_state_message (info);
status_changed |= gtk_printer_set_state_message (printer, info->state_msg);
status_changed |= gtk_printer_set_is_accepting_jobs (printer, info->is_accepting_jobs);
-
-
- /* Set printer icon according to importance
- (none, report, warning, error - report is omitted). */
- if (info->reason_level == GTK_PRINTER_STATE_LEVEL_ERROR)
- gtk_printer_set_icon_name (printer, "printer-error");
- else if (info->reason_level == GTK_PRINTER_STATE_LEVEL_WARNING)
- gtk_printer_set_icon_name (printer, "printer-warning");
- else if (gtk_printer_is_paused (printer))
- gtk_printer_set_icon_name (printer, "printer-paused");
- else
- gtk_printer_set_icon_name (printer, "printer");
+ set_printer_icon_name_from_info (printer, info);
if (status_changed)
g_signal_emit_by_name (GTK_PRINT_BACKEND (backend),
@@ -2210,9 +2981,18 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend,
as inactive if it is in the list, emitting a printer_removed signal */
if (removed_printer_checklist != NULL)
{
- g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, backend);
+ for (iter = removed_printer_checklist; iter; iter = iter->next)
+ {
+#ifdef HAVE_AVAHI_BROWSING
+ if (!GTK_PRINTER_CUPS (iter->data)->avahi_browsed)
+#endif
+ {
+ mark_printer_inactive (GTK_PRINTER (iter->data), backend);
+ list_has_changed = TRUE;
+ }
+ }
+
g_list_free (removed_printer_checklist);
- list_has_changed = TRUE;
}
done:
@@ -2223,23 +3003,16 @@ done:
if (!cups_backend->got_default_printer && remote_default_printer != NULL)
{
- cups_backend->default_printer = g_strdup (remote_default_printer);
- cups_backend->got_default_printer = TRUE;
+ set_default_printer (cups_backend, remote_default_printer);
g_free (remote_default_printer);
+ }
- if (cups_backend->default_printer != NULL)
- {
- GtkPrinter *default_printer = NULL;
- default_printer = gtk_print_backend_find_printer (GTK_PRINT_BACKEND (cups_backend),
- cups_backend->default_printer);
- if (default_printer != NULL)
- {
- gtk_printer_set_is_default (default_printer, TRUE);
- g_signal_emit_by_name (GTK_PRINT_BACKEND (cups_backend),
- "printer-status-changed", default_printer);
- }
- }
+#ifdef HAVE_AVAHI_BROWSING
+ if (!cups_backend->got_default_printer && cups_backend->avahi_default_printer != NULL)
+ {
+ set_default_printer (cups_backend, cups_backend->avahi_default_printer);
}
+#endif
gdk_threads_leave ();
}
@@ -2265,24 +3038,6 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
{
GtkCupsConnectionState state;
GtkCupsRequest *request;
- static const char * const pattrs[] = /* Attributes we're interested in */
- {
- "printer-name",
- "printer-uri-supported",
- "member-uris",
- "printer-location",
- "printer-info",
- "printer-state-message",
- "printer-state-reasons",
- "printer-state",
- "queued-job-count",
- "printer-is-accepting-jobs",
- "job-sheets-supported",
- "job-sheets-default",
- "printer-type",
- "auth-info-required",
- "number-up-default"
- };
if (cups_backend->reading_ppds > 0 || cups_backend->list_printers_pending)
return TRUE;
@@ -2319,8 +3074,8 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend)
cups_backend->username);
gtk_cups_request_ipp_add_strings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", G_N_ELEMENTS (pattrs),
- NULL, pattrs);
+ "requested-attributes", G_N_ELEMENTS (printer_attrs),
+ NULL, printer_attrs);
cups_request_execute (cups_backend,
request,
@@ -2347,6 +3102,10 @@ cups_get_printer_list (GtkPrintBackend *backend)
cups_backend->list_printers_poll = gdk_threads_add_timeout (50,
(GSourceFunc) cups_request_printer_list,
backend);
+
+#ifdef HAVE_AVAHI_BROWSING
+ avahi_request_printer_list (cups_backend);
+#endif
}
}
@@ -2387,10 +3146,15 @@ 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 */
- if ((gtk_cups_result_get_error_type (result) == GTK_CUPS_ERROR_HTTP) &&
- (gtk_cups_result_get_error_status (result) == HTTP_NOT_FOUND))
+ /* 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_AVAHI_BROWSING
+ || GTK_PRINTER_CUPS (printer)->avahi_browsed
+#endif
+ )
{
gtk_printer_set_has_details (printer, TRUE);
success = TRUE;
@@ -2521,6 +3285,10 @@ cups_request_ppd (GtkPrinter *printer)
resource,
GTK_PRINT_BACKEND_CUPS (print_backend)->username);
+ gtk_cups_request_set_ipp_version (request,
+ cups_printer->ipp_version_major,
+ cups_printer->ipp_version_minor);
+
GTK_NOTE (PRINTING,
g_print ("CUPS Backend: Requesting resource %s to be written to temp file %s\n", resource, ppd_filename));
@@ -4524,12 +5292,11 @@ cups_printer_get_settings_from_options (GtkPrinter *printer,
data.settings = settings;
data.ppd_file = gtk_printer_cups_get_ppd (GTK_PRINTER_CUPS (printer));
+ gtk_printer_option_set_foreach (options, foreach_option_get_settings, &data);
if (data.ppd_file != NULL)
{
GtkPrinterOption *cover_before, *cover_after;
- gtk_printer_option_set_foreach (options, foreach_option_get_settings, &data);
-
cover_before = gtk_printer_option_set_lookup (options, "gtk-cover-before");
cover_after = gtk_printer_option_set_lookup (options, "gtk-cover-after");
if (cover_before && cover_after)
@@ -4574,7 +5341,9 @@ cups_printer_prepare_for_print (GtkPrinter *printer,
GtkPaperSize *paper_size;
const char *ppd_paper_name;
double scale;
+ GtkPrintCapabilities capabilities;
+ capabilities = cups_printer_get_capabilities (printer);
pages = gtk_print_settings_get_print_pages (settings);
gtk_print_job_set_pages (print_job, pages);
@@ -4587,18 +5356,40 @@ cups_printer_prepare_for_print (GtkPrinter *printer,
}
gtk_print_job_set_page_ranges (print_job, ranges, n_ranges);
- if (gtk_print_settings_get_collate (settings))
- gtk_print_settings_set (settings, "cups-Collate", "True");
- gtk_print_job_set_collate (print_job, FALSE);
- if (gtk_print_settings_get_reverse (settings))
- gtk_print_settings_set (settings, "cups-OutputOrder", "Reverse");
- gtk_print_job_set_reverse (print_job, FALSE);
+ if (capabilities & GTK_PRINT_CAPABILITY_COLLATE)
+ {
+ if (gtk_print_settings_get_collate (settings))
+ gtk_print_settings_set (settings, "cups-Collate", "True");
+ gtk_print_job_set_collate (print_job, FALSE);
+ }
+ else
+ {
+ gtk_print_job_set_collate (print_job, gtk_print_settings_get_collate (settings));
+ }
- if (gtk_print_settings_get_n_copies (settings) > 1)
- gtk_print_settings_set_int (settings, "cups-copies",
- gtk_print_settings_get_n_copies (settings));
- gtk_print_job_set_num_copies (print_job, 1);
+ if (capabilities & GTK_PRINT_CAPABILITY_REVERSE)
+ {
+ if (gtk_print_settings_get_reverse (settings))
+ gtk_print_settings_set (settings, "cups-OutputOrder", "Reverse");
+ gtk_print_job_set_reverse (print_job, FALSE);
+ }
+ else
+ {
+ gtk_print_job_set_reverse (print_job, gtk_print_settings_get_reverse (settings));
+ }
+
+ if (capabilities & GTK_PRINT_CAPABILITY_COPIES)
+ {
+ if (gtk_print_settings_get_n_copies (settings) > 1)
+ gtk_print_settings_set_int (settings, "cups-copies",
+ gtk_print_settings_get_n_copies (settings));
+ gtk_print_job_set_num_copies (print_job, 1);
+ }
+ else
+ {
+ gtk_print_job_set_num_copies (print_job, gtk_print_settings_get_n_copies (settings));
+ }
scale = gtk_print_settings_get_scale (settings);
if (scale != 100.0)
@@ -4659,6 +5450,12 @@ cups_printer_prepare_for_print (GtkPrinter *printer,
enum_value = g_enum_get_value (enum_class, layout);
gtk_print_settings_set (settings, "cups-number-up-layout", enum_value->value_nick);
g_type_class_unref (enum_class);
+
+ if (!(capabilities & GTK_PRINT_CAPABILITY_NUMBER_UP))
+ {
+ gtk_print_job_set_n_up (print_job, gtk_print_settings_get_number_up (settings));
+ gtk_print_job_set_n_up_layout (print_job, gtk_print_settings_get_number_up_layout (settings));
+ }
}
gtk_print_job_set_rotate (print_job, TRUE);
@@ -4778,10 +5575,29 @@ cups_printer_get_hard_margins (GtkPrinter *printer,
static GtkPrintCapabilities
cups_printer_get_capabilities (GtkPrinter *printer)
{
- return
- GTK_PRINT_CAPABILITY_COPIES |
- GTK_PRINT_CAPABILITY_COLLATE |
- GTK_PRINT_CAPABILITY_REVERSE |
- GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT |
- GTK_PRINT_CAPABILITY_NUMBER_UP;
+ GtkPrintCapabilities capabilities = 0;
+ GtkPrinterCups *cups_printer = GTK_PRINTER_CUPS (printer);
+
+ if (gtk_printer_cups_get_ppd (cups_printer))
+ {
+ capabilities = GTK_PRINT_CAPABILITY_REVERSE;
+ }
+
+ if (cups_printer->supports_copies)
+ {
+ capabilities |= GTK_PRINT_CAPABILITY_COPIES;
+ }
+
+ if (cups_printer->supports_collate)
+ {
+ capabilities |= GTK_PRINT_CAPABILITY_COLLATE;
+ }
+
+ if (cups_printer->supports_number_up)
+ {
+ capabilities |= GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT |
+ GTK_PRINT_CAPABILITY_NUMBER_UP;
+ }
+
+ return capabilities;
}
diff --git a/modules/printbackends/cups/gtkprintercups.c b/modules/printbackends/cups/gtkprintercups.c
index 128b3b3854..f2adb0ce5b 100644
--- a/modules/printbackends/cups/gtkprintercups.c
+++ b/modules/printbackends/cups/gtkprintercups.c
@@ -114,6 +114,17 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
printer->remote_cups_connection_test = NULL;
printer->auth_info_required = NULL;
printer->default_number_up = 1;
+#ifdef HAVE_AVAHI_BROWSING
+ printer->avahi_browsed = FALSE;
+ printer->avahi_name = NULL;
+ printer->avahi_type = NULL;
+ printer->avahi_domain = NULL;
+#endif
+ printer->ipp_version_major = 1;
+ printer->ipp_version_minor = 1;
+ printer->supports_copies = FALSE;
+ printer->supports_collate = FALSE;
+ printer->supports_number_up = FALSE;
}
static void
@@ -134,8 +145,11 @@ gtk_printer_cups_finalize (GObject *object)
g_strfreev (printer->auth_info_required);
#ifdef HAVE_COLORD
- g_cancellable_cancel (printer->colord_cancellable);
- g_object_unref (printer->colord_cancellable);
+ if (printer->colord_cancellable)
+ {
+ g_cancellable_cancel (printer->colord_cancellable);
+ g_object_unref (printer->colord_cancellable);
+ }
g_free (printer->colord_title);
g_free (printer->colord_qualifier);
if (printer->colord_client)
@@ -146,6 +160,12 @@ gtk_printer_cups_finalize (GObject *object)
g_object_unref (printer->colord_profile);
#endif
+#ifdef HAVE_AVAHI_BROWSING
+ g_free (printer->avahi_name);
+ g_free (printer->avahi_type);
+ g_free (printer->avahi_domain);
+#endif
+
if (printer->ppd_file)
ppdClose (printer->ppd_file);
@@ -512,7 +532,8 @@ colord_printer_details_aquired_cb (GtkPrinterCups *printer,
gpointer user_data)
{
/* refresh the device */
- colord_update_device (printer);
+ if (printer->colord_client)
+ colord_update_device (printer);
}
#endif
@@ -565,6 +586,14 @@ gtk_printer_cups_new (const char *name,
G_CALLBACK (colord_printer_details_aquired_cb),
printer);
#endif
+
+ /*
+ * IPP version 1.1 has to be supported
+ * by all implementations according to rfc 2911
+ */
+ printer->ipp_version_major = 1;
+ printer->ipp_version_minor = 1;
+
return printer;
}
diff --git a/modules/printbackends/cups/gtkprintercups.h b/modules/printbackends/cups/gtkprintercups.h
index ecc5e38d3e..7b14af6185 100644
--- a/modules/printbackends/cups/gtkprintercups.h
+++ b/modules/printbackends/cups/gtkprintercups.h
@@ -75,6 +75,17 @@ struct _GtkPrinterCups
gchar *colord_title;
gchar *colord_qualifier;
#endif
+#ifdef HAVE_AVAHI_BROWSING
+ gboolean avahi_browsed;
+ gchar *avahi_name;
+ gchar *avahi_type;
+ gchar *avahi_domain;
+#endif
+ guchar ipp_version_major;
+ guchar ipp_version_minor;
+ gboolean supports_copies;
+ gboolean supports_collate;
+ gboolean supports_number_up;
};
struct _GtkPrinterCupsClass