aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--src/Makefile.am18
-rw-r--r--src/indicator-printers-menu.c136
-rw-r--r--src/org.cups.cupsd.Notifier.xml147
4 files changed, 277 insertions, 25 deletions
diff --git a/.bzrignore b/.bzrignore
index e54d376..8c71946 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -25,4 +25,5 @@ src/Makefile.in
src/indicator-printers-service
src/*.la
src/*.lo
+src/cups-notifier.[ch]
diff --git a/src/Makefile.am b/src/Makefile.am
index 5684e70..7b66b1b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,13 +12,29 @@ libprintersmenu_la_LIBADD = $(APPLET_LIBS)
libprintersmenu_la_LDFLAGS = -module -avoid-version
+cups_notifier_sources = \
+ cups-notifier.c \
+ cups-notifier.h
+
+$(cups_notifier_sources): org.cups.cupsd.Notifier.xml
+ gdbus-codegen \
+ --interface-prefix org.cups.cupsd \
+ --c-namespace Cups \
+ --generate-c-code cups-notifier \
+ $^
+
+
libexec_PROGRAMS = indicator-printers-service
indicator_printers_service_SOURCES = \
indicator-printers-service.c \
indicator-printers-service.h \
indicator-printers-menu.c \
- indicator-printers-menu.h
+ indicator-printers-menu.h \
+ $(cups_notifier_sources)
indicator_printers_service_CPPFLAGS = $(SERVICE_CFLAGS)
indicator_printers_service_LDADD = $(SERVICE_LIBS)
+
+BUILT_SOURCES = $(cups_notifier_sources)
+
diff --git a/src/indicator-printers-menu.c b/src/indicator-printers-menu.c
index e0cfd4b..8aa4c62 100644
--- a/src/indicator-printers-menu.c
+++ b/src/indicator-printers-menu.c
@@ -4,6 +4,8 @@
#include <gio/gio.h>
#include <cups/cups.h>
+#include "cups-notifier.h"
+
G_DEFINE_TYPE (IndicatorPrintersMenu, indicator_printers_menu, G_TYPE_OBJECT)
@@ -15,6 +17,7 @@ struct _IndicatorPrintersMenuPrivate
{
DbusmenuMenuitem *root;
GHashTable *printers; /* printer name -> dbusmenuitem */
+ CupsNotifier *cups_notifier;
};
@@ -29,6 +32,7 @@ dispose (GObject *object)
}
g_clear_object (&priv->root);
+ g_clear_object (&priv->cups_notifier);
G_OBJECT_CLASS (indicator_printers_menu_parent_class)->dispose (object);
}
@@ -45,6 +49,19 @@ indicator_printers_menu_class_init (IndicatorPrintersMenuClass *klass)
}
+static int
+get_number_of_active_jobs (const gchar *printer)
+{
+ int njobs;
+ cups_job_t *jobs;
+
+ njobs = cupsGetJobs (&jobs, printer, 1, CUPS_WHICHJOBS_ACTIVE);
+ cupsFreeJobs (njobs, jobs);
+
+ return njobs;
+}
+
+
static void
show_system_settings (DbusmenuMenuitem *menuitem,
guint timestamp,
@@ -79,19 +96,35 @@ show_system_settings (DbusmenuMenuitem *menuitem,
g_object_unref (appinfo);
}
+
static void
-add_printer_menuitem (IndicatorPrintersMenu *self,
- const char *printer,
- int state,
- int njobs)
+update_printer_menuitem (IndicatorPrintersMenu *self,
+ const char *printer,
+ int state,
+ int njobs)
{
IndicatorPrintersMenuPrivate *priv = PRINTERS_MENU_PRIVATE (self);
DbusmenuMenuitem *item;
- item = dbusmenu_menuitem_new ();
- dbusmenu_menuitem_property_set (item, "type", "indicator-item");
- dbusmenu_menuitem_property_set (item, "indicator-icon-name", "printer");
- dbusmenu_menuitem_property_set (item, "indicator-label", printer);
+ item = g_hash_table_lookup (priv->printers, printer);
+
+ if (!item) {
+ item = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (item, "type", "indicator-item");
+ dbusmenu_menuitem_property_set (item, "indicator-icon-name", "printer");
+ g_signal_connect_data (item, "item-activated",
+ G_CALLBACK (show_system_settings),
+ g_strdup (printer), (GClosureNotify) g_free, 0);
+
+ dbusmenu_menuitem_child_append(priv->root, item);
+ g_hash_table_insert (priv->printers, g_strdup (printer), item);
+ }
+
+ if (njobs == 0) {
+ dbusmenu_menuitem_property_set_bool (item, "visible", FALSE);
+ return;
+ }
+
dbusmenu_menuitem_property_set_bool (item, "visible", TRUE);
switch (state) {
@@ -108,13 +141,49 @@ add_printer_menuitem (IndicatorPrintersMenu *self,
break;
}
}
+}
+
+
+static void
+update_job (CupsNotifier *cups_notifier,
+ const gchar *text,
+ const gchar *printer_uri,
+ const gchar *printer_name,
+ guint printer_state,
+ const gchar *printer_state_reasons,
+ gboolean printer_is_accepting_jobs,
+ guint job_id,
+ guint job_state,
+ const gchar *job_state_reasons,
+ const gchar *job_name,
+ guint job_impressions_completed,
+ gpointer user_data)
+{
+ IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data);
+
+ update_printer_menuitem (self,
+ printer_name,
+ printer_state,
+ get_number_of_active_jobs (printer_name));
+}
+
- g_signal_connect_data (item, "item-activated",
- G_CALLBACK (show_system_settings),
- g_strdup (printer), (GClosureNotify) g_free, 0);
+static void
+on_printer_state_changed (CupsNotifier *object,
+ const gchar *text,
+ const gchar *printer_uri,
+ const gchar *printer_name,
+ guint printer_state,
+ const gchar *printer_state_reasons,
+ gboolean printer_is_accepting_jobs,
+ gpointer user_data)
+{
+ IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data);
- dbusmenu_menuitem_child_append(priv->root, item);
- g_hash_table_insert (priv->printers, g_strdup (printer), item);
+ update_printer_menuitem (self,
+ printer_name,
+ printer_state,
+ get_number_of_active_jobs (printer_name));
}
@@ -122,9 +191,9 @@ static void
indicator_printers_menu_init (IndicatorPrintersMenu *self)
{
IndicatorPrintersMenuPrivate *priv = PRINTERS_MENU_PRIVATE (self);
- int ndests, njobs, i, state;
+ int ndests, i;
cups_dest_t *dests;
- cups_job_t *jobs;
+ GError *error = NULL;
priv->root = dbusmenu_menuitem_new ();
@@ -133,18 +202,37 @@ indicator_printers_menu_init (IndicatorPrintersMenu *self)
g_free,
g_object_unref);
+ priv->cups_notifier = cups_notifier_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ 0,
+ NULL,
+ "/org/cups/cupsd/Notifier",
+ NULL,
+ &error);
+ if (error) {
+ g_warning ("Error creating cups notify handler: %s", error->message);
+ g_clear_error (&error);
+ }
+ else {
+ g_signal_connect (priv->cups_notifier, "job-created",
+ G_CALLBACK (update_job), self);
+ g_signal_connect (priv->cups_notifier, "job-state",
+ G_CALLBACK (update_job), self);
+ g_signal_connect (priv->cups_notifier, "job-completed",
+ G_CALLBACK (update_job), self);
+ g_signal_connect (priv->cups_notifier, "printer-state-changed",
+ G_CALLBACK (on_printer_state_changed), self);
+ }
+
/* create initial menu items */
ndests = cupsGetDests (&dests);
for (i = 0; i < ndests; i++) {
- njobs = cupsGetJobs (&jobs, dests[i].name, 1, CUPS_WHICHJOBS_ACTIVE);
- state = atoi (cupsGetOption ("printer-state",
- dests[i].num_options,
- dests[i].options));
-
- if (njobs > 0)
- add_printer_menuitem (self, dests[i].name, state, njobs);
-
- cupsFreeJobs (njobs, jobs);
+ int state = atoi (cupsGetOption ("printer-state",
+ dests[i].num_options,
+ dests[i].options));
+ update_printer_menuitem (self,
+ dests[i].name,
+ state,
+ get_number_of_active_jobs (dests[i].name));
}
cupsFreeDests (ndests, dests);
}
diff --git a/src/org.cups.cupsd.Notifier.xml b/src/org.cups.cupsd.Notifier.xml
new file mode 100644
index 0000000..e70a5c3
--- /dev/null
+++ b/src/org.cups.cupsd.Notifier.xml
@@ -0,0 +1,147 @@
+<node>
+
+ <interface name="org.cups.cupsd.Notifier">
+
+ <signal name="ServerStarted">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerRestarted">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerStopped">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerAudit">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="PrinterAdded">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterDeleted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterModified">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterRestarted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterStopped">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterShutdown">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterStateChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterFinishingsChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterMediaChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="JobCreated">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ <signal name="JobCompleted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ <signal name="JobState">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ </interface>
+
+</node>
+