[gnome-color-manager] Detect printers by connecting to CUPS rather than scraping the HPLIP properties



commit 510d92de0fc5f031fc839a67a7988f5551228a52
Author: Richard Hughes <richard hughsie com>
Date:   Thu Feb 4 16:12:34 2010 +0000

    Detect printers by connecting to CUPS rather than scraping the HPLIP properties

 po/POTFILES.in                     |    1 +
 rules/95-gnome-color-manager.rules |    3 -
 src/gcm-client.c                   |   84 +++++++++++++++++++++++++++++++++--
 src/gcm-device-cups.c              |   86 +++++++++++++++++++++++++++++++++++-
 src/gcm-device-cups.h              |    6 ++-
 5 files changed, 168 insertions(+), 12 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 921d13c..d58b084 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,7 @@ src/gcm-calibrate-manual.c
 src/gcm-client.c
 src/gcm-dump-edid.c
 src/gcm-dump-profile.c
+src/gcm-device-xrandr.c
 src/gcm-fix-profile.c
 src/gcm-install-system-wide.c
 src/gcm-import.c
diff --git a/rules/95-gnome-color-manager.rules b/rules/95-gnome-color-manager.rules
index f844c4c..14c8ee5 100644
--- a/rules/95-gnome-color-manager.rules
+++ b/rules/95-gnome-color-manager.rules
@@ -7,9 +7,6 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.
 
-# HP Printers
-SUBSYSTEM=="usb", ENV{ID_HPLIP}!="", ENV{GCM_DEVICE}="1", ENV{GCM_TYPE}="printer"
-
 # USB SANE scanners
 SUBSYSTEM=="usb", ENV{libsane_matched}!="", ENV{GCM_DEVICE}="1", ENV{GCM_TYPE}="scanner"
 
diff --git a/src/gcm-client.c b/src/gcm-client.c
index 38c89f6..471e7c9 100644
--- a/src/gcm-client.c
+++ b/src/gcm-client.c
@@ -33,6 +33,7 @@
 #include <glib-object.h>
 #include <gudev/gudev.h>
 #include <libgnomeui/gnome-rr.h>
+#include <cups/cups.h>
 
 #include "gcm-client.h"
 #include "gcm-device-xrandr.h"
@@ -60,6 +61,7 @@ struct _GcmClientPrivate
 	GPtrArray			*array;
 	GUdevClient			*gudev_client;
 	GcmScreen			*screen;
+	http_t				*http;
 };
 
 enum {
@@ -255,10 +257,10 @@ gcm_client_uevent_cb (GUdevClient *gudev_client, const gchar *action, GUdevDevic
 }
 
 /**
- * gcm_client_add_connected_devices_usb:
+ * gcm_client_add_connected_devices_udev:
  **/
 static gboolean
-gcm_client_add_connected_devices_usb (GcmClient *client, GError **error)
+gcm_client_add_connected_devices_udev (GcmClient *client, GError **error)
 {
 	GList *devices;
 	GList *l;
@@ -497,6 +499,66 @@ gcm_client_add_connected_devices_xrandr (GcmClient *client, GError **error)
 }
 
 /**
+ * gcm_client_cups_add:
+ **/
+static void
+gcm_client_cups_add (GcmClient *client, cups_dest_t dest)
+{
+	gboolean ret;
+	GError *error = NULL;
+	GcmDevice *device = NULL;
+	GcmClientPrivate *priv = client->priv;
+
+	/* create new device */
+	device = gcm_device_xrandr_new ();
+	ret = gcm_device_cups_set_from_dest (device, priv->http, dest, &error);
+	if (!ret) {
+		egg_debug ("failed to set for output: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* load the device */
+	ret = gcm_device_load (device, &error);
+	if (!ret) {
+		egg_warning ("failed to load: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* add to the array */
+	g_ptr_array_add (priv->array, g_object_ref (device));
+
+	/* signal the addition */
+	egg_debug ("emit: added %s to device list", gcm_device_get_id (device));
+	g_signal_emit (client, signals[SIGNAL_ADDED], 0, device);
+out:
+	if (device != NULL)
+		g_object_unref (device);
+}
+
+/**
+ * gcm_client_add_connected_devices_cups:
+ **/
+static gboolean
+gcm_client_add_connected_devices_cups (GcmClient *client, GError **error)
+{
+	gint num_dests;
+	cups_dest_t *dests;
+	gint i;
+	GcmClientPrivate *priv = client->priv;
+
+	num_dests = cupsGetDests2 (priv->http, &dests);
+	egg_debug ("got %i printers", num_dests);
+
+	/* get printers on the local server */
+	for (i = 0; i < num_dests; i++)
+		gcm_client_cups_add (client, dests[i]);
+	cupsFreeDests (num_dests, dests);
+	return TRUE;
+}
+
+/**
  * gcm_client_add_unconnected_device:
  **/
 static void
@@ -609,15 +671,20 @@ gcm_client_add_connected (GcmClient *client, GError **error)
 
 	g_return_val_if_fail (GCM_IS_CLIENT (client), FALSE);
 
-	/* usb */
-	ret = gcm_client_add_connected_devices_usb (client, error);
+	/* udev */
+	ret = gcm_client_add_connected_devices_udev (client, error);
 	if (!ret)
 		goto out;
 
-	/* xorg */
+	/* xrandr */
 	ret = gcm_client_add_connected_devices_xrandr (client, error);
 	if (!ret)
 		goto out;
+
+	/* cups */
+	ret = gcm_client_add_connected_devices_cups (client, error);
+	if (!ret)
+		goto out;
 out:
 	return ret;
 }
@@ -817,6 +884,12 @@ gcm_client_init (GcmClient *client)
 	client->priv->gudev_client = g_udev_client_new (subsystems);
 	g_signal_connect (client->priv->gudev_client, "uevent",
 			  G_CALLBACK (gcm_client_uevent_cb), client);
+
+	/* for CUPS */
+	httpInitialize();
+
+	/* should be okay for localhost */
+	client->priv->http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
 }
 
 /**
@@ -832,6 +905,7 @@ gcm_client_finalize (GObject *object)
 	g_ptr_array_unref (priv->array);
 	g_object_unref (priv->gudev_client);
 	g_object_unref (priv->screen);
+	httpClose (priv->http);
 
 	G_OBJECT_CLASS (gcm_client_parent_class)->finalize (object);
 }
diff --git a/src/gcm-device-cups.c b/src/gcm-device-cups.c
index bcf3fa8..e7f5042 100644
--- a/src/gcm-device-cups.c
+++ b/src/gcm-device-cups.c
@@ -26,6 +26,8 @@
 #include <cups/ppd.h>
 
 #include "gcm-device-cups.h"
+#include "gcm-enum.h"
+#include "gcm-utils.h"
 
 #include "egg-debug.h"
 
@@ -52,11 +54,91 @@ enum {
 G_DEFINE_TYPE (GcmDeviceCups, gcm_device_cups, GCM_TYPE_DEVICE)
 
 /**
- * gcm_device_cups_set_from_instance:
+ * gcm_device_cups_set_from_dest:
  **/
 gboolean
-gcm_device_cups_set_from_instance (GcmDevice *device, gpointer instance, GError **error)
+gcm_device_cups_set_from_dest (GcmDevice *device, http_t *http, cups_dest_t dest, GError **error)
 {
+	gint i;
+	ppd_file_t *ppd_file;
+	const gchar *ppd_file_location;
+	gchar *id = NULL;
+	gchar *device_id = NULL;
+	gchar *title = NULL;
+	gchar *serial = NULL;
+	gchar *manufacturer = NULL;
+	gchar *model = NULL;
+	GcmColorspaceEnum colorspace = GCM_COLORSPACE_ENUM_UNKNOWN;
+
+	egg_debug ("name: %s", dest.name);
+	egg_debug ("instance: %s", dest.instance);
+	egg_debug ("num_options: %i", dest.num_options);
+
+	ppd_file_location = cupsGetPPD2 (http, dest.name);
+	ppd_file = ppdOpenFile (ppd_file_location);
+
+	egg_debug ("ppd_file_location=%s", ppd_file_location);
+
+	for (i = 0; i < ppd_file->num_attrs; i++) {
+		const gchar *keyword;
+		const gchar *value;
+
+		/* get the keyword and value */
+		keyword = ppd_file->attrs[i]->name;
+		value = ppd_file->attrs[i]->value;
+
+		/* ignore some */
+		if (g_strcmp0 (keyword, "Font") == 0)
+			continue;
+		if (g_strcmp0 (keyword, "Product") == 0)
+			continue;
+		if (g_strcmp0 (keyword, "ParamCustomPageSize") == 0)
+			continue;
+
+		/* check to see if there is anything interesting */
+		if (g_strcmp0 (keyword, "Manufacturer") == 0) {
+			manufacturer = g_strdup (value);
+		} else if (g_strcmp0 (keyword, "ModelName") == 0) {
+			model = g_strdup (value);
+		} else if (g_strcmp0 (keyword, "ShortNickName") == 0) {
+			title = g_strdup (value);
+		} else if (g_strcmp0 (keyword, "1284DeviceID") == 0) {
+			device_id = g_strdup (value);
+		} else if (g_strcmp0 (keyword, "DefaultColorSpace") == 0) {
+			if (g_strcmp0 (value, "RGB") == 0)
+				colorspace = GCM_COLORSPACE_ENUM_RGB;
+			else if (g_strcmp0 (value, "CMYK") == 0)
+				colorspace = GCM_COLORSPACE_ENUM_CMYK;
+			else
+				egg_warning ("colorspace not recognised: %s", value);
+		}
+
+		egg_debug ("keyword: %s, value: %s, spec: %s", keyword, value, ppd_file->attrs[i]->spec);
+	}
+
+	/* convert device_id 'MFG:HP;MDL:deskjet d1300 series;DES:deskjet d1300 series;' to suitable id */
+	id = g_strdup_printf ("cups_%s", device_id);
+	gcm_utils_alphanum_lcase (id);
+
+	g_object_set (device,
+		      "type", GCM_DEVICE_TYPE_ENUM_PRINTER,
+		      "colorspace", colorspace,
+		      "id", id,
+		      "connected", TRUE,
+//		      "serial", serial,
+		      "model", model,
+		      "manufacturer", manufacturer,
+		      "title", title,
+		      "native-device", device_id,
+		      NULL);
+
+	g_free (serial);
+	g_free (manufacturer);
+	g_free (model);
+	g_free (id);
+	g_free (device_id);
+	g_free (title);
+	ppdClose (ppd_file);
 	return TRUE;
 }
 
diff --git a/src/gcm-device-cups.h b/src/gcm-device-cups.h
index 573d19b..5cd7c19 100644
--- a/src/gcm-device-cups.h
+++ b/src/gcm-device-cups.h
@@ -23,6 +23,7 @@
 #define __GCM_DEVICE_CUPS_H
 
 #include <glib-object.h>
+#include <cups/cups.h>
 
 #include "gcm-device.h"
 
@@ -49,8 +50,9 @@ struct _GcmDeviceCupsClass
 
 GType		 gcm_device_cups_get_type		  	(void);
 GcmDevice	*gcm_device_cups_new				(void);
-gboolean	 gcm_device_cups_set_from_instance		(GcmDevice	*device,
-								 gpointer	 instance,
+gboolean	 gcm_device_cups_set_from_dest			(GcmDevice	*device,
+								 http_t		*http,
+								 cups_dest_t	 dest,
 								 GError		**error);
 
 G_END_DECLS



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