[gnome-color-manager] Use libsane to get our scanners, which means remote devices are now supported



commit cb1454576fe83de635c4f60924eeaff76270dfea
Author: Richard Hughes <richard hughsie com>
Date:   Tue Mar 23 20:00:26 2010 +0000

    Use libsane to get our scanners, which means remote devices are now supported

 configure.ac                        |    4 +
 contrib/gnome-color-manager.spec.in |    2 +
 rules/95-gcm-devices.rules          |    3 -
 src/Makefile.am                     |   10 +++
 src/gcm-client.c                    |   96 +++++++++++++++++++++++++++-
 src/gcm-device-sane.c               |  121 ++++++++++++++++++++++++++++++++++-
 src/gcm-device-sane.h               |   10 ++-
 7 files changed, 238 insertions(+), 8 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 762e8c7..c8cf3c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,10 @@ PKG_CHECK_MODULES(X11, x11)
 AC_SUBST(X11_CFLAGS)
 AC_SUBST(X11_LIBS)
 
+PKG_CHECK_MODULES(SANE, sane-backends)
+AC_SUBST(SANE_CFLAGS)
+AC_SUBST(SANE_LIBS)
+
 PKG_CHECK_MODULES(CANBERRA, libcanberra-gtk >= $CANBERRA_REQUIRED)
 AC_SUBST(CANBERRA_CFLAGS)
 AC_SUBST(CANBERRA_LIBS)
diff --git a/contrib/gnome-color-manager.spec.in b/contrib/gnome-color-manager.spec.in
index 8e34422..f22416b 100644
--- a/contrib/gnome-color-manager.spec.in
+++ b/contrib/gnome-color-manager.spec.in
@@ -25,6 +25,7 @@ Requires:  udev
 Requires:  vte
 Requires:  lcms
 Requires:  cups
+Requires:  sane-backends-libs
 Requires:  polkit
 Requires:  PackageKit
 Requires:  shared-color-profiles
@@ -52,6 +53,7 @@ BuildRequires: libXrandr-devel
 BuildRequires: gnome-desktop-devel
 BuildRequires: lcms-devel
 BuildRequires: cups-devel
+BuildRequires: sane-backends-devel
 BuildRequires: libtiff-devel
 BuildRequires: libcanberra-devel >= %{libcanberra_version}
 
diff --git a/rules/95-gcm-devices.rules b/rules/95-gcm-devices.rules
index e1ee7fd..857fbf5 100644
--- a/rules/95-gcm-devices.rules
+++ b/rules/95-gcm-devices.rules
@@ -14,9 +14,6 @@
 #  GCM_DEVICE		(Can be assinged a profile)
 #  GCM_TYPE		(The type of device)
 
-# USB SANE scanners
-SUBSYSTEM=="usb", ENV{libsane_matched}!="", ENV{GCM_DEVICE}="1", ENV{GCM_TYPE}="scanner"
-
 # Cameras with gphoto drivers
 SUBSYSTEM=="usb", ENV{ID_GPHOTO2}!="", ENV{GCM_DEVICE}="1", ENV{GCM_TYPE}="camera"
 
diff --git a/src/Makefile.am b/src/Makefile.am
index bece432..72c5f56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ INCLUDES =						\
 	$(LCMS_CFLAGS)					\
 	$(XORG_CFLAGS)					\
 	$(CUPS_CFLAGS)					\
+	$(SANE_CFLAGS)					\
 	$(TIFF_CFLAGS)					\
 	$(CANBERRA_CFLAGS)				\
 	$(DBUS_GLIB_CFLAGS)				\
@@ -117,6 +118,7 @@ gcm_dump_edid_LDADD =					\
 	$(XORG_LIBS)					\
 	$(DBUS_GLIB_LIBS)				\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -137,6 +139,7 @@ gcm_dump_profile_LDADD =				\
 	$(XORG_LIBS)					\
 	$(DBUS_GLIB_LIBS)				\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -151,6 +154,7 @@ gcm_fix_profile_LDADD =					\
 	$(X11_LIBS)					\
 	$(LCMS_LIBS)					\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -171,6 +175,7 @@ gcm_inspect_LDADD =					\
 	$(XORG_LIBS)					\
 	$(DBUS_GLIB_LIBS)				\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -191,6 +196,7 @@ gcm_apply_LDADD =					\
 	$(XORG_LIBS)					\
 	$(DBUS_GLIB_LIBS)				\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -211,6 +217,7 @@ gcm_import_LDADD =					\
 	$(XORG_LIBS)					\
 	$(DBUS_GLIB_LIBS)				\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -243,6 +250,7 @@ gcm_prefs_LDADD =					\
 	$(DBUS_GLIB_LIBS)				\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	$(TIFF_LIBS)					\
 	$(CANBERRA_LIBS)				\
@@ -268,6 +276,7 @@ gcm_session_LDADD =					\
 	$(DBUS_GLIB_LIBS)				\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	-lm
 
@@ -315,6 +324,7 @@ gcm_self_test_LDADD =					\
 	$(DBUS_GLIB_LIBS)				\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
+	$(SANE_LIBS)					\
 	$(CUPS_LIBS)					\
 	$(TIFF_LIBS)					\
 	-lm
diff --git a/src/gcm-client.c b/src/gcm-client.c
index 306e96a..040a806 100644
--- a/src/gcm-client.c
+++ b/src/gcm-client.c
@@ -34,6 +34,7 @@
 #include <gudev/gudev.h>
 #include <libgnomeui/gnome-rr.h>
 #include <cups/cups.h>
+#include <sane/sane.h>
 
 #include "gcm-client.h"
 #include "gcm-device-xrandr.h"
@@ -629,6 +630,81 @@ gcm_client_add_connected_devices_cups_thrd (GcmClient *client)
 }
 
 /**
+ * gcm_client_sane_add:
+ **/
+static void
+gcm_client_sane_add (GcmClient *client, const SANE_Device *sane_device)
+{
+	gboolean ret;
+	GError *error = NULL;
+	GcmDevice *device = NULL;
+	GcmClientPrivate *priv = client->priv;
+
+	/* create new device */
+	device = gcm_device_sane_new ();
+	ret = gcm_device_sane_set_from_device (device, sane_device, &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_sane:
+ **/
+static gboolean
+gcm_client_add_connected_devices_sane (GcmClient *client, GError **error)
+{
+	gint i;
+	SANE_Status status;
+	const SANE_Device **device_list;
+
+	/* get scanners on the local server */
+	status = sane_get_devices (&device_list, FALSE);
+	if (status != SANE_STATUS_GOOD) {
+		egg_warning ("failed to get devices from SANE: %s", sane_strstatus (status));
+		goto out;
+	}
+
+	/* add them */
+	for (i=0; device_list[i] != NULL; i++)
+		gcm_client_sane_add (client, device_list[i]);
+out:
+	/* inform the UI */
+	gcm_client_done_loading (client);
+	return TRUE;
+}
+
+/**
+ * gcm_client_add_connected_devices_sane_thrd:
+ **/
+static gpointer
+gcm_client_add_connected_devices_sane_thrd (GcmClient *client)
+{
+	gcm_client_add_connected_devices_sane (client, NULL);
+	return NULL;
+}
+
+/**
  * gcm_client_add_unconnected_device:
  **/
 static void
@@ -782,7 +858,7 @@ gcm_client_add_connected (GcmClient *client, GError **error)
 		goto out;
 
 	/* inform UI if we are loading devces still */
-	client->priv->loading_refcount = 2;
+	client->priv->loading_refcount = 3;
 	gcm_client_set_loading (client, TRUE);
 
 	/* UDEV */
@@ -806,6 +882,17 @@ gcm_client_add_connected (GcmClient *client, GError **error)
 		if (!ret)
 			goto out;
 	}
+
+	/* SANE */
+	if (client->priv->use_threads) {
+		thread = g_thread_create ((GThreadFunc) gcm_client_add_connected_devices_sane_thrd, client, FALSE, error);
+		if (thread == NULL)
+			goto out;
+	} else {
+		ret = gcm_client_add_connected_devices_sane (client, error);
+		if (!ret)
+			goto out;
+	}
 out:
 	return ret;
 }
@@ -1071,6 +1158,7 @@ static void
 gcm_client_init (GcmClient *client)
 {
 	const gchar *subsystems[] = {"usb", "video4linux", NULL};
+	SANE_Status status;
 
 	client->priv = GCM_CLIENT_GET_PRIVATE (client);
 	client->priv->display_name = NULL;
@@ -1089,6 +1177,11 @@ gcm_client_init (GcmClient *client)
 	/* for CUPS */
 	httpInitialize();
 
+	/* for SANE */
+	status = sane_init (NULL, NULL);
+	if (status != SANE_STATUS_GOOD)
+		egg_warning ("failed to init SANE: %s", sane_strstatus (status));
+
 	/* should be okay for localhost */
 	client->priv->http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
 }
@@ -1107,6 +1200,7 @@ gcm_client_finalize (GObject *object)
 	g_object_unref (priv->gudev_client);
 	g_object_unref (priv->screen);
 	httpClose (priv->http);
+	sane_exit ();
 
 	G_OBJECT_CLASS (gcm_client_parent_class)->finalize (object);
 }
diff --git a/src/gcm-device-sane.c b/src/gcm-device-sane.c
index 1942b44..5deb1aa 100644
--- a/src/gcm-device-sane.c
+++ b/src/gcm-device-sane.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include <glib-object.h>
+#include <sane/sane.h>
 
 #include "gcm-device-sane.h"
 #include "gcm-enum.h"
@@ -29,6 +30,8 @@
 
 #include "egg-debug.h"
 
+static void     gcm_device_sane_finalize	(GObject     *object);
+
 #define GCM_DEVICE_SANE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_DEVICE_SANE, GcmDeviceSanePrivate))
 
 /**
@@ -43,10 +46,11 @@ struct _GcmDeviceSanePrivate
 
 enum {
 	PROP_0,
+	PROP_NATIVE_DEVICE,
 	PROP_LAST
 };
 
-G_DEFINE_TYPE (GcmDeviceSane, gcm_device_sane, GCM_TYPE_DEVICE_UDEV)
+G_DEFINE_TYPE (GcmDeviceSane, gcm_device_sane, GCM_TYPE_DEVICE)
 
 typedef struct {
 	gchar	*key;
@@ -158,6 +162,51 @@ out:
 }
 
 /**
+ * gcm_device_sane_set_from_device:
+ **/
+gboolean
+gcm_device_sane_set_from_device (GcmDevice *device, const SANE_Device *sane_device, GError **error)
+{
+	gchar *id = NULL;
+	gchar *manufacturer = NULL;
+	gchar *model = NULL;
+	gchar *title = NULL;
+
+	egg_debug ("name=%s", sane_device->name);
+	egg_debug ("vendor=%s", sane_device->vendor);
+	egg_debug ("model=%s", sane_device->model);
+	egg_debug ("type=%s", sane_device->type);
+
+	/* convert device_id 'plustek:libusb:004:002' to suitable id */
+	id = g_strdup_printf ("sane_%s", sane_device->name);
+	gcm_utils_alphanum_lcase (id);
+
+	/* make safe strings */
+	manufacturer = g_strdup (sane_device->vendor);
+	model = g_strdup (sane_device->model);
+	title = g_strdup_printf ("%s - %s", manufacturer, model);
+
+	/* set properties on device */
+	g_object_set (device,
+		      "type", GCM_DEVICE_TYPE_ENUM_SCANNER,
+		      "colorspace", GCM_COLORSPACE_ENUM_RGB,
+		      "id", id,
+		      "connected", TRUE,
+//		      "serial", serial,
+		      "model", model,
+		      "manufacturer", manufacturer,
+		      "title", title,
+		      "native-device", sane_device->name,
+		      NULL);
+
+	g_free (manufacturer);
+	g_free (model);
+	g_free (id);
+	g_free (title);
+	return TRUE;
+}
+
+/**
  * gcm_device_sane_apply_global:
  *
  * Return value: %TRUE for success;
@@ -299,13 +348,68 @@ out:
 }
 
 /**
+ * gcm_device_sane_get_property:
+ **/
+static void
+gcm_device_sane_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	GcmDeviceSane *device_sane = GCM_DEVICE_SANE (object);
+	GcmDeviceSanePrivate *priv = device_sane->priv;
+
+	switch (prop_id) {
+	case PROP_NATIVE_DEVICE:
+		g_value_set_string (value, priv->native_device);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_device_sane_set_property:
+ **/
+static void
+gcm_device_sane_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	GcmDeviceSane *device_sane = GCM_DEVICE_SANE (object);
+	GcmDeviceSanePrivate *priv = device_sane->priv;
+
+	switch (prop_id) {
+	case PROP_NATIVE_DEVICE:
+		g_free (priv->native_device);
+		priv->native_device = g_strdup (g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
  * gcm_device_sane_class_init:
  **/
 static void
 gcm_device_sane_class_init (GcmDeviceSaneClass *klass)
 {
+	GParamSpec *pspec;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GcmDeviceClass *device_class = GCM_DEVICE_CLASS (klass);
+
+	object_class->finalize = gcm_device_sane_finalize;
+	object_class->get_property = gcm_device_sane_get_property;
+	object_class->set_property = gcm_device_sane_set_property;
+
 	device_class->apply = gcm_device_sane_apply;
+
+	/**
+	 * GcmDeviceSane:native-device:
+	 */
+	pspec = g_param_spec_string ("native-device", NULL, NULL,
+				     NULL,
+				     G_PARAM_READWRITE);
+	g_object_class_install_property (object_class, PROP_NATIVE_DEVICE, pspec);
+
 	g_type_class_add_private (klass, sizeof (GcmDeviceSanePrivate));
 }
 
@@ -316,6 +420,21 @@ static void
 gcm_device_sane_init (GcmDeviceSane *device_sane)
 {
 	device_sane->priv = GCM_DEVICE_SANE_GET_PRIVATE (device_sane);
+	device_sane->priv->native_device = NULL;
+}
+
+/**
+ * gcm_device_sane_finalize:
+ **/
+static void
+gcm_device_sane_finalize (GObject *object)
+{
+	GcmDeviceSane *device_sane = GCM_DEVICE_SANE (object);
+	GcmDeviceSanePrivate *priv = device_sane->priv;
+
+	g_free (priv->native_device);
+
+	G_OBJECT_CLASS (gcm_device_sane_parent_class)->finalize (object);
 }
 
 /**
diff --git a/src/gcm-device-sane.h b/src/gcm-device-sane.h
index b92fc5f..6f7f28d 100644
--- a/src/gcm-device-sane.h
+++ b/src/gcm-device-sane.h
@@ -23,8 +23,9 @@
 #define __GCM_DEVICE_SANE_H
 
 #include <glib-object.h>
+#include <sane/sane.h>
 
-#include "gcm-device-udev.h"
+#include "gcm-device.h"
 
 G_BEGIN_DECLS
 
@@ -38,17 +39,20 @@ typedef struct _GcmDeviceSaneClass	GcmDeviceSaneClass;
 
 struct _GcmDeviceSane
 {
-	 GcmDeviceUdev			 parent;
+	 GcmDevice			 parent;
 	 GcmDeviceSanePrivate		*priv;
 };
 
 struct _GcmDeviceSaneClass
 {
-	GcmDeviceUdevClass		 parent_class;
+	GcmDeviceClass			 parent_class;
 };
 
 GType		 gcm_device_sane_get_type		  	(void);
 GcmDevice	*gcm_device_sane_new				(void);
+gboolean	 gcm_device_sane_set_from_device		(GcmDevice	*device,
+								 const SANE_Device *sane_device,
+								 GError		**error);
 
 G_END_DECLS
 



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