Logo Search packages:      
Sourcecode: eggcups version File versions  Download package

ec-driver-prompt.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2004 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 of the
 * License, 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 "ec-driver-prompt.h"
#include "ec-driver-prompt-dialog.h"
#include "rb-debug.h"
#include <string.h>
#include <gconf/gconf-client.h>
#include <hal/libhal.h>

G_DEFINE_TYPE(ECDriverPrompt, ec_driver_prompt, G_TYPE_OBJECT)
static void ec_driver_prompt_finalize                           (GObject *object);
static gboolean ec_driver_prompt_dbus_init                  (ECDriverPrompt *self);
static void ec_driver_prompt_set_property             (GObject *object,
                                                guint prop_id,
                                                const GValue *value,
                                                GParamSpec *pspec);

static void ec_driver_prompt_get_property             (GObject *object,
                                                guint prop_id,
                                                GValue *value,
                                                GParamSpec *pspec);

static void on_driver_dialog_destroy                        (GtkWidget *dialog,
                                                gpointer user_data);

static ECDriverPromptDialog *ec_driver_prompt_create_dialog (ECDriverPrompt *self);

 
static void ec_driver_prompt_config_user_printers           (ECDriverPrompt *self);

static gboolean find_user_driver                      (const gchar *make, 
                                                 const gchar *model, 
                                                 gchar **return_make, 
                                                 gchar **return_model);


enum {
      PROP_NONE,
      PROP_BUS
};

00059 struct ECDriverPromptPrivate
{
      DBusConnection *bus;
      GList *dialog_list;
};

static void 
ec_driver_prompt_init (ECDriverPrompt *dp)
{
      dp->priv = G_TYPE_INSTANCE_GET_PRIVATE (dp, EC_TYPE_DRIVER_PROMPT, 
                                    ECDriverPromptPrivate);

      dp->priv->dialog_list = NULL;
      dp->priv->bus = NULL;
}

static void 
ec_driver_prompt_class_init (ECDriverPromptClass *klass)
{
      GObjectClass *gobject_class;
      GParamSpec *dbus_bus_param;
      
      gobject_class = G_OBJECT_CLASS (klass);

      gobject_class->finalize = ec_driver_prompt_finalize;
      gobject_class->set_property = ec_driver_prompt_set_property;
      gobject_class->get_property = ec_driver_prompt_get_property;

      dbus_bus_param = g_param_spec_pointer ("bus",
                                               "dbus bus",
                                       "dbus connection we have our service on",
                                               G_PARAM_READWRITE |
                                     G_PARAM_CONSTRUCT);
      g_object_class_install_property (gobject_class, PROP_BUS,
                               dbus_bus_param);

      g_type_class_add_private (gobject_class, 
                          sizeof (ECDriverPromptPrivate));
}


static void 
ec_driver_prompt_finalize (GObject *object) 
{ 
       ECDriverPrompt *dp = EC_DRIVER_PROMPT (object); 
 
       g_return_if_fail (dp->priv != NULL); 
 
       rb_debug ("finalizing"); 
 
       g_free (dp->priv); 
}

static void 
ec_driver_prompt_set_property (GObject *object,
                            guint prop_id,
                            const GValue *value,
                            GParamSpec *pspec)
{
      ECDriverPrompt *dp;

      dp = EC_DRIVER_PROMPT (object);

      switch (prop_id)
      {
            case PROP_BUS:
                  dp->priv->bus = (DBusConnection *) g_value_get_pointer (value);
                  ec_driver_prompt_dbus_init (dp);
                  break;
            default:
                  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                  break;
      }
}

static void ec_driver_prompt_get_property    (GObject *object,
                                           guint prop_id,
                                           GValue *value,
                                           GParamSpec *pspec)
{
      ECDriverPrompt *dp;

      dp = EC_DRIVER_PROMPT (object);

      switch (prop_id)
      {
            case PROP_BUS:
                  g_value_set_pointer (value, dp->priv->bus);
                  break;
            default:
                  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                  break;
      }

}

ECDriverPrompt *
ec_driver_prompt_new (DBusConnection *bus)
{
      return g_object_new (EC_TYPE_DRIVER_PROMPT, "bus", bus, NULL);
}

static gchar *
gconf_generate_user_driver_path (const gchar *make, const gchar *model)
{
      gchar *path;
      gchar *lc_make, *lc_model;
      
      lc_make = g_ascii_strdown (make, -1);
      lc_model = g_ascii_strdown (model, -1);

      g_strcanon (lc_make, EC_GCONF_ALLOWED_CHARS, '_');
      g_strcanon (lc_model, EC_GCONF_ALLOWED_CHARS, '_');

      path = g_strconcat (EC_GCONF_PRINTER_PATH, "/", lc_make, "_", lc_model, NULL);

      g_free (lc_make);
      g_free (lc_model);

      return path;
}

static gboolean
find_user_driver (const gchar *make, 
              const gchar *model, 
              gchar **return_make, 
              gchar **return_model)
{
      gchar *path, *make_key, *model_key;
      GConfClient *gconf_client;
      
      path = gconf_generate_user_driver_path (make, model);
      make_key = g_build_path ("/", path, "make", NULL);
      model_key = g_build_path ("/", path, "model", NULL);

      gconf_client = gconf_client_get_default ();
      *return_make = gconf_client_get_string (gconf_client, make_key, NULL);
      *return_model = gconf_client_get_string (gconf_client, model_key, NULL);

      g_object_unref (gconf_client);
      g_free (path);
      g_free (make_key);
      g_free (model_key);

      if (*return_make == NULL || *return_model == NULL)
            return FALSE;
      else
            return TRUE;
}

static void
get_user_driver (DBusConnection *connection, 
             DBusMessage *message)
{
      DBusError error;
      const gchar *make, *model, *printer_udi, *printer_name;
      gchar *return_make, *return_model;
      DBusMessage *return_message;
      gboolean has_user_drivers;

      rb_debug ("Getting user driver...");

      dbus_error_init (&error);     

      if (!dbus_message_get_args (message, &error,
                                    DBUS_TYPE_STRING, &make,
                                    DBUS_TYPE_STRING, &model,
                                    DBUS_TYPE_STRING, &printer_udi,
                                    DBUS_TYPE_STRING, &printer_name,
                                    DBUS_TYPE_INVALID)) {
            g_error ("Error getting message aguments %s\n", error.message);
            return;
      }

      has_user_drivers = find_user_driver (make, model, &return_make, &return_model);

      return_message = dbus_message_new_method_return (message);

      if (return_message == NULL)
            goto out;

      if (has_user_drivers) {
            DBusMessageIter iter;
            dbus_message_iter_init_append (return_message, &iter);
            
            dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &return_make);
            dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &return_model);
      }
      
      dbus_connection_send (connection, return_message, NULL);
      dbus_message_unref (return_message);

out:
      g_free (return_make);
      g_free (return_model);
}

static void
on_driver_dialog_destroy (GtkWidget *dialog,
                    gpointer user_data)
{
      ECDriverPrompt *self;
      self = EC_DRIVER_PROMPT (user_data);

      rb_debug ("Removing dialog from list in on_driver_dialog_destroy");

      self->priv->dialog_list = g_list_remove (self->priv->dialog_list, dialog);
}

static ECDriverPromptDialog *
ec_driver_prompt_create_dialog (ECDriverPrompt *self)
{
      ECDriverPromptDialog *dialog;

      dialog = ec_driver_prompt_dialog_new ();
      gtk_window_set_title (GTK_WINDOW (dialog), "");
      gtk_widget_show_all (GTK_WIDGET (dialog));
      g_signal_connect (dialog, "destroy", 
                          (GCallback) on_driver_dialog_destroy, self);

      self->priv->dialog_list = g_list_append (self->priv->dialog_list, dialog);

      return dialog;
}

/*
 * ec_driver_prompt_dbus_message_handler
 *
 * Responds to requests for our services
 *
 */
static DBusHandlerResult 
ec_driver_prompt_dbus_message_handler (DBusConnection *connection, 
                               DBusMessage *message, 
                               void *user_data)
{
      const char *method;
      const char *path;
      ECDriverPrompt *self;
      DBusHandlerResult res;

      res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

      self = EC_DRIVER_PROMPT (user_data);

      method = dbus_message_get_member (message);
      path = dbus_message_get_path (message);

      rb_debug ("method %s, path %s called", method, path);

      if (strcmp ("PromptPrintDriver", method) == 0) {
            ECDriverPromptDialog *dialog;
            dialog = ec_driver_prompt_create_dialog (self);
            ec_driver_prompt_dialog_parse_message (dialog, message);

            res = DBUS_HANDLER_RESULT_HANDLED;
      } else if (strcmp ("GetUserDriver", method) == 0) {
            get_user_driver (connection, message);
      
            res = DBUS_HANDLER_RESULT_HANDLED;
      }

      return (res);
}


/*
 * ec_driver_prompt_dbus_unregister_handler 
 *
 * Nothing happens here.
 *
 */
static void
ec_driver_prompt_dbus_unregister_handler (DBusConnection *connection, void *user_data)
{
      /* do nothing */
}

/*
 * 'construct_printer_name()' -  creates a name by taking the product name
 *                               and appending it with the usb port number 
 *                    
 */
static gchar *
construct_printer_name(const char *product, int usb_port_num)
{
      GString *printer;
      gchar *lc_product;
      gchar *result;

      printer = g_string_new ("");

      lc_product = g_ascii_strdown (product, -1);
      g_strcanon (lc_product, EC_GCONF_ALLOWED_CHARS, '-');

      g_string_printf (printer, "%s-%i", lc_product, usb_port_num);

      result = printer->str;

      g_free (lc_product);
      g_string_free (printer, FALSE);

      return result;
}

static void
ec_driver_prompt_get_printer_info_from_udi (LibHalContext *ctx,
                                            const gchar *udi,
                                            gchar **make,
                                            gchar **model)
{
      gchar *device_udi;

      device_udi = NULL;

      if (make) {
            *make = libhal_device_get_property_string (ctx, udi, 
                                               "printer.vendor",
                                               NULL);
            if (*make == NULL) {
                  device_udi = libhal_device_get_property_string (ctx, 
                                                      udi,
                                          "printer.physical_device",
                                                      NULL);
                  *make = libhal_device_get_property_string (ctx,
                                                     device_udi,
                                                   "usb.vendor",
                                                     NULL);
                  if (*make == NULL)
                        *make = g_strdup ("Unknown");
            }
      }

      if (model) {
            *model = libhal_device_get_property_string (ctx, udi, 
                                               "printer.product",
                                               NULL);
            if ((*model == NULL) &&
                (device_udi == NULL)) {
                  device_udi = libhal_device_get_property_string (ctx, 
                                                      udi,
                                          "printer.physical_device",
                                                      NULL);
                  *model = libhal_device_get_property_string (ctx,
                                                     device_udi,
                                                  "usb.product",
                                                     NULL);
                  if (*model == NULL)
                        *model = g_strdup ("Unknown");
            }
      }

      g_free (device_udi);
}

static void
ec_driver_prompt_config_hal_printer (ECDriverPrompt *self,
                             LibHalContext *ctx,
                             const gchar *udi)
{
      gchar *make, *model;
      gchar *return_make;
      gchar *return_model;
      gchar *printer_name;    
      int usb_port;

      rb_debug ("Searching for printer %s in user's configuration.", udi);

      ec_driver_prompt_get_printer_info_from_udi (ctx, udi, &make, &model);

      usb_port = libhal_device_get_property_int (ctx, udi, "usb.port_number",
                                                   NULL);

      printer_name = construct_printer_name (model, usb_port);

      if (find_user_driver (make, model, &return_make, &return_model)) {
            rb_debug ("Printer configuration found.  Configuring printer.");
            dbus_set_printer_driver (return_make, return_model, udi, printer_name, NULL);
      } else {
            ECDriverPromptDialog *dlg;    
            dlg = ec_driver_prompt_create_dialog (self);
            ec_driver_prompt_dialog_set_and_show (dlg, make, model, udi, printer_name);
        }

      libhal_free_string (make);
      libhal_free_string (model); 
      g_free (return_make);
      g_free (return_model);
      g_free (printer_name);
}

static void
ec_driver_prompt_config_user_printers (ECDriverPrompt *self)
{
      gchar **printer_list;
      int num_of_printers = 0;
      int i;
      LibHalContext *ctx;

      rb_debug ("Configuring user defined printers");

        ctx = libhal_ctx_new ();

        if (self->priv->bus != NULL)
        libhal_ctx_set_dbus_connection (ctx, self->priv->bus);

      if (!libhal_ctx_init (ctx, NULL)) {
            g_warning ("Hal failed to initialize");
      } else {
            printer_list = libhal_find_device_by_capability (ctx, "printer", &num_of_printers, NULL);

            for (i = 0; i < num_of_printers; i++) {
                  ec_driver_prompt_config_hal_printer (self, ctx, printer_list[i]);
            }

            libhal_free_string_array (printer_list);
            libhal_ctx_shutdown (ctx, NULL);
                libhal_ctx_free (ctx);
      }
}

static gboolean
ec_driver_prompt_dbus_init (ECDriverPrompt *self)
{
      DBusError dbus_error;
      DBusConnection *bus;
      DBusObjectPathVTable ec_driver_prompt_vtable = { &ec_driver_prompt_dbus_unregister_handler, 
                                           &ec_driver_prompt_dbus_message_handler, 
                                           NULL, NULL, NULL, NULL};

      bus = self->priv->bus;

      dbus_error_init (&dbus_error);
      rb_debug ("acquiring service: %s", EC_DRIVER_PROMPT_NAMESPACE);
      dbus_bus_request_name (bus, EC_DRIVER_PROMPT_NAMESPACE, 0, &dbus_error);
      if (dbus_error_is_set (&dbus_error)) {
            rb_debug ("couldn't acquire service: %s", dbus_error.message);

            dbus_error_free (&dbus_error);
            return FALSE;
      }

      if (!dbus_connection_register_object_path (bus, EC_DRIVER_PROMPT_PATH, &ec_driver_prompt_vtable, self)) {
            rb_debug ("could not register a handler for PrintDriverSelection");
            return FALSE;
      }


      return TRUE;
}

void
ec_driver_prompt_set_connection (ECDriverPrompt *dp, DBusConnection *bus)
{
      g_object_set (G_OBJECT (dp), "dbus", bus, NULL);
}

Generated by  Doxygen 1.6.0   Back to index