[gnome-settings-daemon] printers: Handle system-config-printer-udev's DBus calls



commit 33327be683a259df7bc070df7194f0e07d8a8bb2
Author: Marek Kasik <mkasik redhat com>
Date:   Fri Mar 11 16:14:28 2011 +0100

    printers: Handle system-config-printer-udev's DBus calls
    
    Implement com.redhat.NewPrinterNotification and
    com.redhat.PrinterDriversInstaller DBus interfaces.
    
    The first one notifies about installation of new printer
    (method GetReady). It should also install missing packages
    but it is not implemented yet (2nd part of method NewPrinter).
    
    The second one installs packages with printer drivers
    if needed (method InstallDrivers).

 plugins/print-notifications/Makefile.am            |   15 +
 .../gsd-print-notifications-manager.c              |   49 +++-
 plugins/print-notifications/gsd-printer.c          |  314 ++++++++++++++++++++
 3 files changed, 373 insertions(+), 5 deletions(-)
---
diff --git a/plugins/print-notifications/Makefile.am b/plugins/print-notifications/Makefile.am
index 47a92ca..e49c3c0 100644
--- a/plugins/print-notifications/Makefile.am
+++ b/plugins/print-notifications/Makefile.am
@@ -10,6 +10,7 @@ libprint_notifications_la_SOURCES = 		\
 libprint_notifications_la_CPPFLAGS = \
 	-I$(top_srcdir)/gnome-settings-daemon		\
 	-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+	-DLIBEXECDIR=\""$(libexecdir)"\" \
 	$(AM_CPPFLAGS)
 
 libprint_notifications_la_CFLAGS = \
@@ -28,6 +29,20 @@ plugin_in_files = 		\
 
 plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
 
+libexec_PROGRAMS = gsd-printer
+
+gsd_printer_SOURCES = 	\
+	gsd-printer.c
+
+gsd_printer_CFLAGS = \
+	$(SETTINGS_PLUGIN_CFLAGS)	\
+	$(LIBNOTIFY_CFLAGS)		\
+	$(AM_CFLAGS)
+
+gsd_printer_LDADD  = 		\
+	$(SETTINGS_PLUGIN_LIBS)	\
+	$(LIBNOTIFY_LIBS)
+
 EXTRA_DIST = 			\
 	$(plugin_in_files)
 
diff --git a/plugins/print-notifications/gsd-print-notifications-manager.c b/plugins/print-notifications/gsd-print-notifications-manager.c
index 845cc42..eed6ee4 100644
--- a/plugins/print-notifications/gsd-print-notifications-manager.c
+++ b/plugins/print-notifications/gsd-print-notifications-manager.c
@@ -35,7 +35,6 @@
 
 #include <cups/cups.h>
 #include <libnotify/notify.h>
-#include <libnotify/notify.h>
 
 #include "gnome-settings-profile.h"
 #include "gsd-print-notifications-manager.h"
@@ -49,10 +48,12 @@
 struct GsdPrintNotificationsManagerPrivate
 {
         GDBusProxy                   *cups_proxy;
-        GDBusConnection              *bus_connection;
+        GDBusConnection              *cups_bus_connection;
         gint                          subscription_id;
         cups_dest_t                  *dests;
         gint                          num_dests;
+        gboolean                      scp_handler_spawned;
+        GPid                          scp_handler_pid;
 };
 
 enum {
@@ -478,6 +479,39 @@ on_cups_notification (GDBusConnection *connection,
         }
 }
 
+static void
+scp_handler (GsdPrintNotificationsManager *manager,
+             gboolean                      start)
+{
+        if (start) {
+                GError *error = NULL;
+                char *args[2];
+
+                if (manager->priv->scp_handler_spawned)
+                        return;
+
+                args[0] = LIBEXECDIR "/gsd-printer";
+                args[1] = NULL;
+
+                g_spawn_async (NULL, args, NULL,
+                               0, NULL, NULL,
+                               &manager->priv->scp_handler_pid, &error);
+
+                manager->priv->scp_handler_spawned = (error == NULL);
+
+                if (error) {
+                        g_warning ("Could not execute system-config-printer-udev handler: %s",
+                                   error->message);
+                        g_error_free (error);
+                }
+        }
+        else if (manager->priv->scp_handler_spawned) {
+                kill (manager->priv->scp_handler_pid, SIGHUP);
+                g_spawn_close_pid (manager->priv->scp_handler_pid);
+                manager->priv->scp_handler_spawned = FALSE;
+        }
+}
+
 gboolean
 gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
                                        GError                      **error)
@@ -503,6 +537,7 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
         manager->priv->subscription_id = -1;
         manager->priv->dests = NULL;
         manager->priv->num_dests = 0;
+        manager->priv->scp_handler_spawned = FALSE;
 
         if ((http = httpConnectEncrypt (cupsServer (), ippPort (),
                                         cupsEncryption ())) == NULL) {
@@ -555,9 +590,9 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
                 return FALSE;
         }
 
-        manager->priv->bus_connection = g_dbus_proxy_get_connection (manager->priv->cups_proxy);
+        manager->priv->cups_bus_connection = g_dbus_proxy_get_connection (manager->priv->cups_proxy);
 
-        g_dbus_connection_signal_subscribe (manager->priv->bus_connection,
+        g_dbus_connection_signal_subscribe (manager->priv->cups_bus_connection,
                                             NULL,
                                             CUPS_DBUS_INTERFACE,
                                             NULL,
@@ -568,6 +603,8 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
                                             manager,
                                             NULL);
 
+        scp_handler (manager, TRUE);
+
         gnome_settings_profile_end (NULL);
 
         return TRUE;
@@ -598,12 +635,14 @@ gsd_print_notifications_manager_stop (GsdPrintNotificationsManager *manager)
                 ippDelete(cupsDoRequest(http, request, "/"));
         }
 
-        manager->priv->bus_connection = NULL;
+        manager->priv->cups_bus_connection = NULL;
 
         if (manager->priv->cups_proxy != NULL) {
                 g_object_unref (manager->priv->cups_proxy);
                 manager->priv->cups_proxy = NULL;
         }
+
+        scp_handler (manager, FALSE);
 }
 
 static void
diff --git a/plugins/print-notifications/gsd-printer.c b/plugins/print-notifications/gsd-printer.c
new file mode 100644
index 0000000..80b6048
--- /dev/null
+++ b/plugins/print-notifications/gsd-printer.c
@@ -0,0 +1,314 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <libnotify/notify.h>
+#include <glib/gi18n.h>
+
+static GDBusNodeInfo *npn_introspection_data = NULL;
+static GDBusNodeInfo *pdi_introspection_data = NULL;
+
+#define SCP_DBUS_NPN_NAME      "com.redhat.NewPrinterNotification"
+#define SCP_DBUS_NPN_PATH      "/com/redhat/NewPrinterNotification"
+#define SCP_DBUS_NPN_INTERFACE "com.redhat.NewPrinterNotification"
+
+#define SCP_DBUS_PDI_NAME      "com.redhat.PrinterDriversInstaller"
+#define SCP_DBUS_PDI_PATH      "/com/redhat/PrinterDriversInstaller"
+#define SCP_DBUS_PDI_INTERFACE "com.redhat.PrinterDriversInstaller"
+
+#define PACKAGE_KIT_BUS "org.freedesktop.PackageKit"
+#define PACKAGE_KIT_PATH "/org/freedesktop/PackageKit"
+#define PACKAGE_KIT_IFACE "org.freedesktop.PackageKit.Modify"
+
+static const gchar npn_introspection_xml[] =
+  "<node name='/com/redhat/NewPrinterNotification'>"
+  "  <interface name='com.redhat.NewPrinterNotification'>"
+  "    <method name='GetReady'>"
+  "    </method>"
+  "    <method name='NewPrinter'>"
+  "      <arg type='i' name='status' direction='in'/>"
+  "      <arg type='s' name='name' direction='in'/>"
+  "      <arg type='s' name='mfg' direction='in'/>"
+  "      <arg type='s' name='mdl' direction='in'/>"
+  "      <arg type='s' name='des' direction='in'/>"
+  "      <arg type='s' name='cmd' direction='in'/>"
+  "    </method>"
+  "  </interface>"
+  "</node>";
+
+static const gchar pdi_introspection_xml[] =
+  "<node name='/com/redhat/PrinterDriversInstaller'>"
+  "  <interface name='com.redhat.PrinterDriversInstaller'>"
+  "    <method name='InstallDrivers'>"
+  "      <arg type='s' name='mfg' direction='in'/>"
+  "      <arg type='s' name='mdl' direction='in'/>"
+  "      <arg type='s' name='cmd' direction='in'/>"
+  "    </method>"
+  "  </interface>"
+  "</node>";
+
+static void
+handle_method_call (GDBusConnection       *connection,
+                    const gchar           *sender,
+                    const gchar           *object_path,
+                    const gchar           *interface_name,
+                    const gchar           *method_name,
+                    GVariant              *parameters,
+                    GDBusMethodInvocation *invocation,
+                    gpointer               user_data)
+{
+        gchar *primary_text = NULL;
+        gchar *secondary_text = NULL;
+        gchar *name = NULL;
+        gchar *mfg = NULL;
+        gchar *mdl = NULL;
+        gchar *des = NULL;
+        gchar *cmd = NULL;
+        gchar *device = NULL;
+        gint   status = 0;
+
+        if (g_strcmp0 (method_name, "GetReady") == 0) {
+                /* Translators: We are configuring new printer */
+                primary_text = g_strdup (_("Configuring new printer"));
+                /* Translators: Just wait */
+                secondary_text = g_strdup (_("Please wait..."));
+
+                g_dbus_method_invocation_return_value (invocation,
+                                                       NULL);
+        }
+        else if (g_strcmp0 (method_name, "NewPrinter") == 0) {
+                if (g_variant_n_children (parameters) == 6) {
+                        g_variant_get (parameters, "(i&s&s&s&s&s)",
+                               &status,
+                               &name,
+                               &mfg,
+                               &mdl,
+                               &des,
+                               &cmd);
+                }
+
+                if (g_strrstr (name, "/")) {
+                        /* name is a URI, no queue was generated, because no suitable
+                         * driver was found
+                         */
+                        /* Translators: We have no driver installed for this printer */
+                        primary_text = g_strdup (_("Missing printer driver"));
+
+                        if ((mfg && mdl) || des) {
+                                if (mfg && mdl)
+                                        device = g_strdup_printf ("%s %s", mfg, mdl);
+                                else
+                                        device = g_strdup (des);
+
+                                /* Translators: We have no driver installed for the device */
+                                secondary_text = g_strdup_printf (_("No printer driver for %s."), device);
+                                g_free (device);
+                        }
+                        else
+                                /* Translators: We have no driver installed for this printer */
+                                secondary_text = g_strdup (_("No driver for this printer."));
+                }
+                else {
+                        /* name is the name of the queue which hal_lpadmin has set up
+                         * automatically.
+                         */
+
+                        /* TODO: handle missing packages as system-config-printer does
+                         */
+                }
+
+                g_dbus_method_invocation_return_value (invocation,
+                                                       NULL);
+        }
+        else if (g_strcmp0 (method_name, "InstallDrivers") == 0) {
+                GDBusProxy *proxy;
+                GError     *error = NULL;
+
+                if (g_variant_n_children (parameters) == 3) {
+                        g_variant_get (parameters, "(&s&s&s)",
+                               &mfg,
+                               &mdl,
+                               &cmd);
+                }
+
+                if (mfg && mdl)
+                        device = g_strdup_printf ("MFG:%s;MDL:%s;", mfg, mdl);
+
+                proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                       G_DBUS_PROXY_FLAGS_NONE,
+                                                       NULL,
+                                                       PACKAGE_KIT_BUS,
+                                                       PACKAGE_KIT_PATH,
+                                                       PACKAGE_KIT_IFACE,
+                                                       NULL,
+                                                       &error);
+
+                if (proxy && device) {
+                        GVariantBuilder *builder = NULL;
+                        GVariant        *ipd_parameters = NULL;
+
+                        builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+                        g_variant_builder_add (builder, "s", device);
+
+                        ipd_parameters = g_variant_new ("(uass)",
+                                                        0,
+                                                        builder,
+                                                        "hide-finished");
+
+                        g_dbus_proxy_call_sync (proxy,
+                                                "InstallPrinterDrivers",
+                                                ipd_parameters,
+                                                G_DBUS_CALL_FLAGS_NONE,
+                                                3600000,
+                                                NULL,
+                                                &error);
+
+                        if (error)
+                                g_warning ("%s", error->message);
+
+                        g_variant_unref (ipd_parameters);
+                        g_variant_builder_unref (builder);
+                        g_object_unref (proxy);
+                        g_clear_error (&error);
+                }
+
+                g_dbus_method_invocation_return_value (invocation,
+                                                       NULL);
+        }
+
+        if (primary_text) {
+                NotifyNotification *notification;
+                notification = notify_notification_new (primary_text,
+                                                        secondary_text,
+                                                        "printer-symbolic");
+                notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
+
+                notify_notification_show (notification, NULL);
+                g_object_unref (notification);
+                g_free (primary_text);
+                g_free (secondary_text);
+        }
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+  handle_method_call,
+  NULL,
+  NULL
+};
+
+static void
+on_npn_bus_acquired (GDBusConnection *connection,
+                     const gchar     *name,
+                     gpointer         user_data)
+{
+  guint registration_id;
+
+  registration_id = g_dbus_connection_register_object (connection,
+                                                       SCP_DBUS_NPN_PATH,
+                                                       npn_introspection_data->interfaces[0],
+                                                       &interface_vtable,
+                                                       NULL,
+                                                       NULL,
+                                                       NULL);
+  g_assert (registration_id > 0);
+}
+
+static void
+on_pdi_bus_acquired (GDBusConnection *connection,
+                     const gchar     *name,
+                     gpointer         user_data)
+{
+  guint registration_id;
+
+  registration_id = g_dbus_connection_register_object (connection,
+                                                       SCP_DBUS_PDI_PATH,
+                                                       pdi_introspection_data->interfaces[0],
+                                                       &interface_vtable,
+                                                       NULL,
+                                                       NULL,
+                                                       NULL);
+  g_assert (registration_id > 0);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  exit (1);
+}
+
+int
+main (int argc, char *argv[])
+{
+  guint npn_owner_id;
+  guint pdi_owner_id;
+  GMainLoop *loop;
+
+  g_type_init ();
+
+  notify_init ("gnome-settings-daemon-printer");
+
+  npn_introspection_data =
+          g_dbus_node_info_new_for_xml (npn_introspection_xml, NULL);
+  g_assert (npn_introspection_data != NULL);
+
+  pdi_introspection_data =
+          g_dbus_node_info_new_for_xml (pdi_introspection_xml, NULL);
+  g_assert (pdi_introspection_data != NULL);
+
+  npn_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
+                                 SCP_DBUS_NPN_NAME,
+                                 G_BUS_NAME_OWNER_FLAGS_NONE,
+                                 on_npn_bus_acquired,
+                                 on_name_acquired,
+                                 on_name_lost,
+                                 NULL,
+                                 NULL);
+
+  pdi_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
+                                 SCP_DBUS_PDI_NAME,
+                                 G_BUS_NAME_OWNER_FLAGS_NONE,
+                                 on_pdi_bus_acquired,
+                                 on_name_acquired,
+                                 on_name_lost,
+                                 NULL,
+                                 NULL);
+
+  loop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (loop);
+
+  g_bus_unown_name (npn_owner_id);
+  g_bus_unown_name (pdi_owner_id);
+
+  g_dbus_node_info_unref (npn_introspection_data);
+  g_dbus_node_info_unref (pdi_introspection_data);
+
+  return 0;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]