+/* Printer messages we're interested in */
+static const char * const printer_messages[] =
+ {
+ "toner-low",
+ "toner-empty",
+ "developer-low",
+ "developer-empty",
+ "marker-supply-low",
+ "marker-supply-empty",
+ "cover-open",
+ "door-open",
+ "media-low",
+ "media-empty",
+ "offline",
+ "other"
+ };
+/* Our translatable versions of the printer messages */
+static const char * printer_strings[] =
+ {
+ N_("Printer '%s' is low on toner."),
+ N_("Printer '%s' has no toner left."),
+ /* Translators: "Developer" like on photo development context */
+ N_("Printer '%s' is low on developer."),
+ /* Translators: "Developer" like on photo development context */
+ N_("Printer '%s' is out of developer."),
+ /* Translators: "marker" is one color bin of the printer */
+ N_("Printer '%s' is low on at least one marker supply."),
+ /* Translators: "marker" is one color bin of the printer */
+ N_("Printer '%s' is out of at least one marker supply."),
+ N_("The cover is open on printer '%s'."),
+ N_("The door is open on printer '%s'."),
+ N_("Printer '%s' is low on paper."),
+ N_("Printer '%s' is out of paper."),
+ N_("Printer '%s' is currently offline."),
+ N_("There is a problem on printer '%s'.")
+ };
+
+typedef enum
+ {
+ GTK_PRINTER_STATE_LEVEL_NONE = 0,
+ GTK_PRINTER_STATE_LEVEL_INFO = 1,
+ GTK_PRINTER_STATE_LEVEL_WARNING = 2,
+ GTK_PRINTER_STATE_LEVEL_ERROR = 3
+ } PrinterStateLevel;
+
+typedef struct
+{
+ const gchar *printer_name;
+ const gchar *printer_uri;
+ const gchar *member_uris;
+ const gchar *location;
+ const gchar *description;
+ gchar *state_msg;
+ const gchar *reason_msg;
+ PrinterStateLevel reason_level;
+ gint state;
+ gint job_count;
+ gboolean is_paused;
+ gboolean is_accepting_jobs;
+ const gchar *default_cover_before;
+ const gchar *default_cover_after;
+ gboolean default_printer;
+ gboolean got_printer_type;
+ gboolean remote_printer;
+ gchar **auth_info_required;
+ gint default_number_up;
+} PrinterSetupInfo;
+
+static void
+cups_printer_handle_attribute (GtkPrintBackendCups *cups_backend,
+ ipp_attribute_t *attr,
+ PrinterSetupInfo *info)
+{
+ gint i, j;
+ if (strcmp (ippGetName (attr), "printer-name") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_NAME)
+ info->printer_name = ippGetString (attr, 0, NULL);
+ else if (strcmp (ippGetName (attr), "printer-uri-supported") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_URI)
+ info->printer_uri = ippGetString (attr, 0, NULL);
+ else if (strcmp (ippGetName (attr), "member-uris") == 0 &&
+ ippGetValueTag (attr) == IPP_TAG_URI)
+ info->member_uris = ippGetString (attr, 0, NULL);
+ else if (strcmp (ippGetName (attr), "printer-location") == 0)
+ info->location = ippGetString (attr, 0, NULL);
+ else if (strcmp (ippGetName (attr), "printer-info") == 0)
+ info->description = ippGetString (attr, 0, NULL);
+ else if (strcmp (ippGetName (attr), "printer-state-message") == 0)
+ info->state_msg = g_strdup (ippGetString (attr, 0, NULL));
+ else if (strcmp (ippGetName (attr), "printer-state-reasons") == 0)
+ /* Store most important reason to reason_msg and set
+ its importance at printer_state_reason_level */
+ {
+ for (i = 0; i < ippGetCount (attr); i++)
+ {
+ if (strcmp (ippGetString (attr, i, NULL), "none") != 0)
+ {
+ gboolean interested_in = FALSE;
+ /* Sets is_paused flag for paused printer. */
+ if (strcmp (ippGetString (attr, i, NULL), "paused") == 0)
+ {
+ info->is_paused = TRUE;
+ }
+
+ for (j = 0; j < G_N_ELEMENTS (printer_messages); j++)
+ if (strncmp (ippGetString (attr, i, NULL), printer_messages[j],
+ strlen (printer_messages[j])) == 0)
+ {
+ interested_in = TRUE;
+ break;
+ }
+
+ if (interested_in)
+ {
+ if (g_str_has_suffix (ippGetString (attr, i, NULL), "-report"))
+ {
+ if (info->reason_level <= GTK_PRINTER_STATE_LEVEL_INFO)
+ {
+ info->reason_msg = ippGetString (attr, i, NULL);
+ info->reason_level = GTK_PRINTER_STATE_LEVEL_INFO;
+ }
+ }
+ else if (g_str_has_suffix (ippGetString (attr, i, NULL), "-warning"))
+ {
+ if (info->reason_level <= GTK_PRINTER_STATE_LEVEL_WARNING)
+ {
+ info->reason_msg = ippGetString (attr, i, NULL);
+ info->reason_level = GTK_PRINTER_STATE_LEVEL_WARNING;
+ }
+ }
+ else /* It is error in the case of no suffix. */
+ {
+ info->reason_msg = ippGetString (attr, i, NULL);
+ info->reason_level = GTK_PRINTER_STATE_LEVEL_ERROR;
+ }
+ }
+ }
+ }
+ }
+ else if (strcmp (ippGetName (attr), "printer-state") == 0)
+ info->state = ippGetInteger (attr, 0);
+ else if (strcmp (ippGetName (attr), "queued-job-count") == 0)
+ info->job_count = ippGetInteger (attr, 0);
+ else if (strcmp (ippGetName (attr), "printer-is-accepting-jobs") == 0)
+ {
+ if (ippGetBoolean (attr, 0) == 1)
+ info->is_accepting_jobs = TRUE;
+ else
+ info->is_accepting_jobs = FALSE;
+ }
+ else if (strcmp (ippGetName (attr), "job-sheets-supported") == 0)
+ {
+ if (cups_backend->covers == NULL)
+ {
+ cups_backend->number_of_covers = ippGetCount (attr);
+ cups_backend->covers = g_new (char *, cups_backend->number_of_covers + 1);
+ for (i = 0; i < cups_backend->number_of_covers; i++)
+ cups_backend->covers[i] = g_strdup (ippGetString (attr, i, NULL));
+ cups_backend->covers[cups_backend->number_of_covers] = NULL;
+ }
+ }
+ else if (strcmp (ippGetName (attr), "job-sheets-default") == 0)
+ {
+ if (ippGetCount (attr) == 2)
+ {
+ info->default_cover_before = ippGetString (attr, 0, NULL);
+ info->default_cover_after = ippGetString (attr, 1, NULL);
+ }
+ }
+ else if (strcmp (ippGetName (attr), "printer-type") == 0)
+ {
+ info->got_printer_type = TRUE;
+ if (ippGetInteger (attr, 0) & 0x00020000)
+ info->default_printer = TRUE;
+ else
+ info->default_printer = FALSE;
+
+ if (ippGetInteger (attr, 0) & 0x00000002)
+ info->remote_printer = TRUE;
+ else
+ info->remote_printer = FALSE;
+ }
+ else if (strcmp (ippGetName (attr), "auth-info-required") == 0)
+ {
+ if (strcmp (ippGetString (attr, 0, NULL), "none") != 0)
+ {
+ info->auth_info_required = g_new0 (gchar *, ippGetCount (attr) + 1);
+ for (i = 0; i < ippGetCount (attr); i++)
+ info->auth_info_required[i] = g_strdup (ippGetString (attr, i, NULL));
+ }
+ }
+ else if (strcmp (ippGetName (attr), "number-up-default") == 0)
+ {
+ info->default_number_up = ippGetInteger (attr, 0);
+ }
+ else
+ {
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Attribute %s ignored", ippGetName (attr)));
+ }
+}
+
+static GtkPrinter*
+cups_create_printer (GtkPrintBackendCups *cups_backend,
+ PrinterSetupInfo *info)
+{
+ GtkPrinterCups *cups_printer;
+ GtkPrinter *printer;
+ GtkPrintBackend *backend = GTK_PRINT_BACKEND (cups_backend);
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ char method[HTTP_MAX_URI]; /* Method/scheme name */
+ char username[HTTP_MAX_URI]; /* Username:password */
+ char hostname[HTTP_MAX_URI]; /* Hostname */
+ char resource[HTTP_MAX_URI]; /* Resource name */
+ int port; /* Port number */
+ char *cups_server; /* CUPS server */
+
+#ifdef HAVE_COLORD
+ 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
+
+ cups_printer->device_uri = g_strdup_printf ("/printers/%s",
+ info->printer_name);
+
+ /* Check to see if we are looking at a class */
+ if (info->member_uris)
+ {
+ cups_printer->printer_uri = g_strdup (info->member_uris);
+ /* TODO if member_uris is a class we need to recursivly find a printer */
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Found class with printer %s\n",
+ info->member_uris));
+ }
+ else
+ {
+ cups_printer->printer_uri = g_strdup (info->printer_uri);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Found printer %s\n",
+ info->printer_uri));
+ }
+
+ httpSeparateURI (HTTP_URI_CODING_ALL, cups_printer->printer_uri,
+ method, sizeof (method),
+ username, sizeof (username),
+ hostname, sizeof (hostname),
+ &port,
+ resource, sizeof (resource));
+
+ if (strncmp (resource, "/printers/", 10) == 0)
+ {
+ cups_printer->ppd_name = g_strdup (resource + 10);
+ GTK_NOTE (PRINTING,
+ g_print ("CUPS Backend: Setting ppd name '%s' for printer/class '%s'\n", cups_printer->ppd_name, info->printer_name));
+ }
+
+ gethostname (uri, sizeof (uri));
+ cups_server = g_strdup (cupsServer());
+
+ if (strcasecmp (uri, hostname) == 0)
+ strcpy (hostname, "localhost");
+
+ /* if the cups server is local and listening at a unix domain socket
+ * then use the socket connection
+ */
+ if ((strstr (hostname, "localhost") != NULL) &&
+ (cups_server[0] == '/'))
+ strcpy (hostname, cups_server);
+
+ g_free (cups_server);
+
+ 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;
+
+ cups_printer->hostname = g_strdup (hostname);
+ cups_printer->port = port;
+
+ cups_printer->auth_info_required = g_strdupv (info->auth_info_required);
+ g_strfreev (info->auth_info_required);
+
+ printer = GTK_PRINTER (cups_printer);
+
+ if (cups_backend->default_printer != NULL &&
+ strcmp (cups_backend->default_printer, gtk_printer_get_name (printer)) == 0)
+ gtk_printer_set_is_default (printer, TRUE);
+
+
+ gtk_print_backend_add_printer (backend, printer);
+ return printer;
+}
+