[gnome-settings-daemon] printers: Use new DBus API for communication with CUPS
- From: Marek Kašík <mkasik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] printers: Use new DBus API for communication with CUPS
- Date: Sat, 26 Feb 2011 15:09:45 +0000 (UTC)
commit 04c122d2c8bcdf8916582659541ef3675259a3a4
Author: Marek Kasik <mkasik redhat com>
Date: Sat Feb 26 15:55:21 2011 +0100
printers: Use new DBus API for communication with CUPS
Use org.cups.cupsd.Notifier instead of com.redhat.PrinterSpooler.
Improve efficiency of getting information about jobs (solves
problems mentioned in
https://bugzilla.redhat.com/show_bug.cgi?id=677676#c5).
.../gsd-print-notifications-manager.c | 344 +++++++++++---------
1 files changed, 195 insertions(+), 149 deletions(-)
---
diff --git a/plugins/print-notifications/gsd-print-notifications-manager.c b/plugins/print-notifications/gsd-print-notifications-manager.c
index ba2ba16..eedc6fe 100644
--- a/plugins/print-notifications/gsd-print-notifications-manager.c
+++ b/plugins/print-notifications/gsd-print-notifications-manager.c
@@ -42,15 +42,15 @@
#define GSD_PRINT_NOTIFICATIONS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_PRINT_NOTIFICATIONS_MANAGER, GsdPrintNotificationsManagerPrivate))
-#define CUPS_DBUS_NAME "com.redhat.PrinterSpooler"
-#define CUPS_DBUS_PATH "/com/redhat/PrinterSpooler"
-#define CUPS_DBUS_INTERFACE "com.redhat.PrinterSpooler"
+#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier"
+#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier"
+#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier"
struct GsdPrintNotificationsManagerPrivate
{
GDBusProxy *cups_proxy;
GDBusConnection *bus_connection;
- GSList *actual_jobs;
+ gint subscription_id;
};
enum {
@@ -135,155 +135,157 @@ on_cups_notification (GDBusConnection *connection,
gpointer user_data)
{
GsdPrintNotificationsManager *manager = GSD_PRINT_NOTIFICATIONS_MANAGER (user_data);
- cups_job_t *jobs;
- GSList *actual = NULL;
- GSList *tmp = NULL;
+ gboolean printer_is_accepting_jobs;
+ gboolean my_job = FALSE;
+ http_t *http;
gchar *printer_name = NULL;
gchar *display_name = NULL;
- gchar *user_name = NULL;
gchar *primary_text = NULL;
gchar *secondary_text = NULL;
+ gchar *text = NULL;
+ gchar *printer_uri = NULL;
+ gchar *printer_state_reasons = NULL;
+ gchar *job_state_reasons = NULL;
+ gchar *job_name = NULL;
+ gchar *job_uri = NULL;
guint job_id;
- gint actual_job = -1;
- gint num_jobs, i;
- gint index = -1;
+ ipp_t *request, *response;
+ gint printer_state;
+ gint job_state;
+ gint job_impressions_completed;
+
+ if (g_strcmp0 (signal_name, "PrinterAdded") != 0 &&
+ g_strcmp0 (signal_name, "PrinterDeleted") != 0 &&
+ g_strcmp0 (signal_name, "JobCompleted") != 0 &&
+ g_strcmp0 (signal_name, "JobState") != 0 &&
+ g_strcmp0 (signal_name, "JobCreated") != 0)
+ return;
+
+ if (g_variant_n_children (parameters) == 1) {
+ g_variant_get (parameters, "(&s)", &text);
+ } else if (g_variant_n_children (parameters) == 6) {
+ g_variant_get (parameters, "(&s&s&su&sb)",
+ &text,
+ &printer_uri,
+ &printer_name,
+ &printer_state,
+ &printer_state_reasons,
+ &printer_is_accepting_jobs);
+ } else if (g_variant_n_children (parameters) == 11) {
+ ipp_attribute_t *attr;
+
+ g_variant_get (parameters, "(&s&s&su&sbuu&s&su)",
+ &text,
+ &printer_uri,
+ &printer_name,
+ &printer_state,
+ &printer_state_reasons,
+ &printer_is_accepting_jobs,
+ &job_id,
+ &job_state,
+ &job_state_reasons,
+ &job_name,
+ &job_impressions_completed);
+
+ if ((http = httpConnectEncrypt (cupsServer (), ippPort (),
+ cupsEncryption ())) == NULL) {
+ g_debug ("Connection to CUPS server \'%s\' failed.", cupsServer ());
+ }
+ else {
+ job_uri = g_strdup_printf ("ipp://localhost/jobs/%d", job_id);
+
+ request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, job_uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "job-originating-user-name");
+ response = cupsDoRequest(http, request, "/");
+
+ if (response) {
+ if (response->request.status.status_code <= IPP_OK_CONFLICT &&
+ (attr = ippFindAttribute(response, "job-originating-user-name",
+ IPP_TAG_NAME))) {
+ if (g_strcmp0 (attr->values[0].string.text, cupsUser ()) == 0)
+ my_job = TRUE;
+ }
+ ippDelete(response);
+ }
+ g_free (job_uri);
+ }
+ }
if (g_strcmp0 (signal_name, "PrinterAdded") == 0) {
/* Translators: New printer has been added */
- if (g_variant_n_children (parameters) == 1) {
- g_variant_get (parameters, "(&s)", &printer_name);
- if (is_local_dest (printer_name)) {
- primary_text = g_strdup (_("Printer added"));
- secondary_text = g_strdup (printer_name);
- }
+ if (is_local_dest (printer_name)) {
+ primary_text = g_strdup (_("Printer added"));
+ secondary_text = g_strdup (printer_name);
}
- } else if (g_strcmp0 (signal_name, "PrinterRemoved") == 0) {
+ } else if (g_strcmp0 (signal_name, "PrinterDeleted") == 0) {
/* Translators: A printer has been removed */
- if (g_variant_n_children (parameters) == 1) {
- g_variant_get (parameters, "(&s)", &printer_name);
- if (is_local_dest (printer_name)) {
- primary_text = g_strdup (_("Printer removed"));
- secondary_text = g_strdup (printer_name);
- }
- }
- } else if (g_strcmp0 (signal_name, "QueueChanged") == 0) {
- if (g_variant_n_children (parameters) == 1 ||
- g_variant_n_children (parameters) == 3) {
- g_variant_get (parameters, "(&s)", &printer_name);
+ if (is_local_dest (printer_name)) {
+ primary_text = g_strdup (_("Printer removed"));
+ secondary_text = g_strdup (printer_name);
}
-
+ } else if (g_strcmp0 (signal_name, "JobCompleted") == 0 && my_job) {
/* FIXME: get a better human readable name */
display_name = g_strdup (printer_name);
- if (manager->priv->actual_jobs != NULL) {
- num_jobs = cupsGetJobs (&jobs, printer_name, 1, CUPS_WHICHJOBS_ALL);
-
- for (actual = manager->priv->actual_jobs; actual; actual = actual->next) {
- actual_job = GPOINTER_TO_INT (actual->data);
- for (i = 0; i < num_jobs; i++) {
- if (jobs[i].id == actual_job) {
- switch (jobs[i].state) {
- case IPP_JOB_PENDING:
- case IPP_JOB_HELD:
- case IPP_JOB_PROCESSING:
- break;
- case IPP_JOB_STOPPED:
- /* Translators: A print job has been stopped */
- primary_text = g_strdup (_("Printing stopped"));
- /* Translators: "print-job xy" on a printer */
- secondary_text = g_strdup_printf (_("\"%s\" on %s"), jobs[i].title, display_name);
- actual->data = GINT_TO_POINTER (-1);
- break;
- case IPP_JOB_CANCELED:
- /* Translators: A print job has been canceled */
- primary_text = g_strdup (_("Printing canceled"));
- /* Translators: "print-job xy" on a printer */
- secondary_text = g_strdup_printf (_("\"%s\" on %s"), jobs[i].title, display_name);
- actual->data = GINT_TO_POINTER (-1);
- break;
- case IPP_JOB_ABORTED:
- /* Translators: A print job has been aborted */
- primary_text = g_strdup (_("Printing aborted"));
- /* Translators: "print-job xy" on a printer */
- secondary_text = g_strdup_printf (_("\"%s\" on %s"), jobs[i].title, display_name);
- actual->data = GINT_TO_POINTER (-1);
- break;
- case IPP_JOB_COMPLETED:
- /* Translators: A print job has been completed */
- primary_text = g_strdup (_("Printing completed"));
- /* Translators: "print-job xy" on a printer */
- secondary_text = g_strdup_printf (_("\"%s\" on %s"), jobs[i].title, display_name);
- actual->data = GINT_TO_POINTER (-1);
- break;
- }
- break;
- }
- }
- }
-
- for (actual = manager->priv->actual_jobs; actual; actual = actual->next) {
- if (GPOINTER_TO_INT (actual->data) < 0) {
- tmp = actual->next;
- manager->priv->actual_jobs =
- g_slist_delete_link (manager->priv->actual_jobs, actual);
- actual = tmp;
- if (!actual)
- break;
- }
- }
-
- cupsFreeJobs (num_jobs, jobs);
+ switch (job_state) {
+ case IPP_JOB_PENDING:
+ case IPP_JOB_HELD:
+ case IPP_JOB_PROCESSING:
+ break;
+ case IPP_JOB_STOPPED:
+ /* Translators: A print job has been stopped */
+ primary_text = g_strdup (_("Printing stopped"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
+ break;
+ case IPP_JOB_CANCELED:
+ /* Translators: A print job has been canceled */
+ primary_text = g_strdup (_("Printing canceled"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
+ break;
+ case IPP_JOB_ABORTED:
+ /* Translators: A print job has been aborted */
+ primary_text = g_strdup (_("Printing aborted"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
+ break;
+ case IPP_JOB_COMPLETED:
+ /* Translators: A print job has been completed */
+ primary_text = g_strdup (_("Printing completed"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
+ break;
}
- } else if (g_strcmp0 (signal_name, "JobQueuedLocal") == 0) {
- if (g_variant_n_children (parameters) == 3) {
- g_variant_get (parameters, "(&su&s)", &printer_name, &job_id, &user_name);
-
- num_jobs = cupsGetJobs (&jobs, printer_name, 1, CUPS_WHICHJOBS_ALL);
-
- index = -1;
- for (i = 0; i < num_jobs; i++)
- if (jobs[i].id == job_id)
- index = i;
-
- if (index >= 0) {
- /* Only display a notification if there is some problem */
- }
-
- manager->priv->actual_jobs =
- g_slist_append (manager->priv->actual_jobs, GUINT_TO_POINTER (job_id));
-
- cupsFreeJobs (num_jobs, jobs);
+ } else if (g_strcmp0 (signal_name, "JobState") == 0 && my_job) {
+ display_name = get_dest_attr (printer_name, "printer-info");
+
+ switch (job_state) {
+ case IPP_JOB_PROCESSING:
+ /* Translators: A job is printing */
+ primary_text = g_strdup (_("Printing"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
+ break;
+ default:
+ break;
}
- } else if (g_strcmp0 (signal_name, "JobStartedLocal") == 0) {
- if (g_variant_n_children (parameters) == 3) {
- g_variant_get (parameters, "(&su&s)", &printer_name, &job_id, &user_name);
-
- display_name = get_dest_attr (printer_name, "printer-info");
-
- for (actual = manager->priv->actual_jobs; actual; actual = actual->next) {
- if (GPOINTER_TO_INT (actual->data) == job_id) {
- num_jobs = cupsGetJobs (&jobs, printer_name, 1, CUPS_WHICHJOBS_ALL);
-
- index = -1;
- for (i = 0; i < num_jobs; i++)
- if (jobs[i].id == job_id)
- index = i;
-
- if (index >= 0) {
- /* Translators: A job is printing */
- primary_text = g_strdup (_("Printing"));
- /* Translators: "print-job xy" on a printer */
- secondary_text = g_strdup_printf (_("\"%s\" on %s"), jobs[index].title, display_name);
- }
-
- cupsFreeJobs (num_jobs, jobs);
- }
- }
+ } else if (g_strcmp0 (signal_name, "JobCreated") == 0 && my_job) {
+ display_name = get_dest_attr (printer_name, "printer-info");
+
+ if (job_state == IPP_JOB_PROCESSING) {
+ /* Translators: A job is printing */
+ primary_text = g_strdup (_("Printing"));
+ /* Translators: "print-job xy" on a printer */
+ secondary_text = g_strdup_printf (_("\"%s\" on %s"), job_name, display_name);
}
}
g_free (display_name);
+
if (primary_text) {
NotifyNotification *notification;
notification = notify_notification_new (primary_text,
@@ -299,16 +301,58 @@ gboolean
gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
GError **error)
{
- cups_job_t *jobs;
GError *lerror;
- int num_jobs;
- int i;
+ ipp_t *request, *response;
+ http_t *http;
+ gint num_events = 6;
+ static const char * const events[] = {
+ "job-created",
+ "job-completed",
+ "job-state-changed",
+ "job-state",
+ "printer-added",
+ "printer-deleted"};
+ ipp_attribute_t *attr = NULL;
g_debug ("Starting print-notifications manager");
gnome_settings_profile_start (NULL);
- manager->priv->actual_jobs = NULL;
+ manager->priv->subscription_id = -1;
+
+ if ((http = httpConnectEncrypt (cupsServer (), ippPort (),
+ cupsEncryption ())) == NULL) {
+ g_debug ("Connection to CUPS server \'%s\' failed.", cupsServer ());
+ }
+ else {
+ request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ "/");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser ());
+ ippAddStrings(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events",
+ num_events, NULL, events);
+ ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
+ "notify-pull-method", NULL, "ippget");
+ ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-recipient-uri",
+ NULL, "dbus://");
+ ippAddInteger(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", 0);
+ response = cupsDoRequest(http, request, "/");
+
+ if (response != NULL && response->request.status.status_code <= IPP_OK_CONFLICT) {
+ if ((attr = ippFindAttribute(response, "notify-subscription-id",
+ IPP_TAG_INTEGER)) == NULL)
+ g_debug ("No notify-subscription-id in response!\n");
+ else
+ manager->priv->subscription_id = attr->values[0].integer;
+ }
+
+ if (response)
+ ippDelete(response);
+
+ httpClose(http);
+ }
lerror = NULL;
manager->priv->cups_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
@@ -319,6 +363,7 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
CUPS_DBUS_INTERFACE,
NULL,
&lerror);
+
if (lerror != NULL) {
g_propagate_error (error, lerror);
return FALSE;
@@ -337,14 +382,6 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
manager,
NULL);
- num_jobs = cupsGetJobs (&jobs, NULL, 1, CUPS_WHICHJOBS_ACTIVE);
-
- for (i = 0; i < num_jobs; i++) {
- manager->priv->actual_jobs = g_slist_append (manager->priv->actual_jobs, GUINT_TO_POINTER (jobs[i].id));
- }
-
- cupsFreeJobs (num_jobs, jobs);
-
gnome_settings_profile_end (NULL);
return TRUE;
@@ -353,11 +390,22 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
void
gsd_print_notifications_manager_stop (GsdPrintNotificationsManager *manager)
{
+ ipp_t *request;
+ http_t *http;
+
g_debug ("Stopping print-notifications manager");
- if (manager->priv->actual_jobs != NULL) {
- g_slist_free (manager->priv->actual_jobs);
- manager->priv->actual_jobs = NULL;
+ if (manager->priv->subscription_id >= 0 &&
+ ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) != NULL)) {
+ request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ "/");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser ());
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "notify-subscription-ids", manager->priv->subscription_id);
+ ippDelete(cupsDoRequest(http, request, "/"));
}
manager->priv->bus_connection = NULL;
@@ -466,8 +514,6 @@ gsd_print_notifications_manager_finalize (GObject *object)
g_object_unref (manager->priv->cups_proxy);
}
- g_slist_free (manager->priv->actual_jobs);
-
G_OBJECT_CLASS (gsd_print_notifications_manager_parent_class)->finalize (object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]