[brasero] Remove use of HAL from the medium monitor



commit 995880a3fac606eb14e829c8b6fc2471a2de507c
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Thu Jul 9 21:13:02 2009 +0200

    Remove use of HAL from the medium monitor
    Implement INQUIRY (MMC command) to retrieve the drive category

 libbrasero-media/Makefile.am              |    3 +-
 libbrasero-media/brasero-drive.c          |    3 +-
 libbrasero-media/brasero-medium-monitor.c |  212 +++++++++++------------------
 libbrasero-media/scsi-inquiry.c           |  109 +++++++++++++++
 libbrasero-media/scsi-spc1.h              |    4 +
 5 files changed, 198 insertions(+), 133 deletions(-)
---
diff --git a/libbrasero-media/Makefile.am b/libbrasero-media/Makefile.am
index c83996e..be5baa5 100644
--- a/libbrasero-media/Makefile.am
+++ b/libbrasero-media/Makefile.am
@@ -128,7 +128,8 @@ libbrasero_media_la_SOURCES =		\
 	brasero-media-private.h         \
 	brasero-medium-selection-priv.h         \
 	brasero-gio-operation.h         \
-	brasero-gio-operation.c
+	brasero-gio-operation.c         \
+	scsi-inquiry.c
 
 # FreeBSD's SCSI CAM interface
 if HAVE_CAM_LIB_H
diff --git a/libbrasero-media/brasero-drive.c b/libbrasero-media/brasero-drive.c
index 379937e..4dd7de2 100644
--- a/libbrasero-media/brasero-drive.c
+++ b/libbrasero-media/brasero-drive.c
@@ -479,7 +479,7 @@ brasero_drive_get_device (BraseroDrive *drive)
 	g_return_val_if_fail (BRASERO_IS_DRIVE (drive), NULL);
 
 	priv = BRASERO_DRIVE_PRIVATE (drive);
-	return priv->path;
+	return priv->path? priv->path:priv->block_path;
 }
 
 /**
@@ -512,6 +512,7 @@ brasero_drive_get_block_device (BraseroDrive *drive)
  * to uniquely identify the drive.
  *
  * Return value: a string holding the HAL udi. Not to be freed
+ * Deprecated since 2.27.3
  **/
 const gchar *
 brasero_drive_get_udi (BraseroDrive *drive)
diff --git a/libbrasero-media/brasero-medium-monitor.c b/libbrasero-media/brasero-medium-monitor.c
index 3cbb16c..9c826e3 100644
--- a/libbrasero-media/brasero-medium-monitor.c
+++ b/libbrasero-media/brasero-medium-monitor.c
@@ -47,9 +47,12 @@
 
 #include "brasero-media-private.h"
 
+#include "scsi-device.h"
+#include "scsi-utils.h"
+#include "scsi-spc1.h"
+
 #include "brasero-drive.h"
 #include "brasero-medium.h"
-#include "burn-hal-watch.h"
 #include "brasero-medium-monitor.h"
 
 typedef struct _BraseroMediumMonitorPrivate BraseroMediumMonitorPrivate;
@@ -286,49 +289,6 @@ brasero_medium_monitor_get_media (BraseroMediumMonitor *monitor,
 	return list;
 }
 
-static GDrive *
-brasero_medium_monitor_get_gdrive (BraseroMediumMonitor *monitor,
-                                   const gchar *volume_path)
-{
-	BraseroMediumMonitorPrivate *priv;
-	GDrive *gdrive = NULL;
-	GList *drives;
-	GList *iter;
-
-	g_return_val_if_fail (volume_path != NULL, NULL);
-
-	priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
-
-	/* NOTE: medium-monitor already holds a reference for GVolumeMonitor */
-	drives = g_volume_monitor_get_connected_drives (priv->gmonitor);
-	for (iter = drives; iter; iter = iter->next) {
-		gchar *device_path;
-		GDrive *tmp;
-
-		tmp = iter->data;
-		device_path = g_drive_get_identifier (tmp, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
-		if (!device_path)
-			continue;
-
-		BRASERO_MEDIA_LOG ("Found drive %s", device_path);
-		if (!strcmp (device_path, volume_path)) {
-			gdrive = tmp;
-			g_free (device_path);
-			g_object_ref (gdrive);
-			break;
-		}
-
-		g_free (device_path);
-	}
-	g_list_foreach (drives, (GFunc) g_object_unref, NULL);
-	g_list_free (drives);
-
-	if (!gdrive)
-		BRASERO_MEDIA_LOG ("No drive found for medium");
-
-	return gdrive;
-}
-
 static void
 brasero_medium_monitor_medium_added_cb (BraseroDrive *drive,
 					BraseroMedium *medium,
@@ -351,35 +311,50 @@ brasero_medium_monitor_medium_removed_cb (BraseroDrive *drive,
 		       medium);
 }
 
+static gboolean
+brasero_medium_monitor_is_drive (BraseroMediumMonitor *monitor,
+                                 GDrive *gdrive)
+{
+	BraseroMediumMonitorPrivate *priv;
+	BraseroDeviceHandle *handle;
+	BraseroScsiErrCode code;
+	gboolean result;
+	gchar *device;
+
+	priv = BRASERO_MEDIUM_MONITOR_PRIVATE (monitor);
+
+	device = g_drive_get_identifier (gdrive, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
+	BRASERO_MEDIA_LOG ("Testing drive %s", device);
+
+	handle = brasero_device_handle_open (device, FALSE, &code);
+	g_free (device);
+
+	if (!handle)
+		return FALSE;
+
+	result = (brasero_spc1_inquiry_is_optical_drive (handle, &code) == BRASERO_SCSI_OK);
+	brasero_device_handle_close (handle);
+
+	BRASERO_MEDIA_LOG ("Drive %s", result? "is optical":"is not optical");
+
+	return result;
+}
+
 static void
-brasero_medium_monitor_inserted_cb (BraseroHALWatch *watch,
-				    const char *udi,
-				    BraseroMediumMonitor *self)
+brasero_medium_monitor_connected_cb (GVolumeMonitor *monitor,
+                                     GDrive *gdrive,
+                                     BraseroMediumMonitor *self)
 {
 	BraseroMediumMonitorPrivate *priv;
 	BraseroDrive *drive = NULL;
-	gchar *device_path;
-	LibHalContext *ctx;
-	GDrive *gdrive;
 
-	ctx = brasero_hal_watch_get_ctx (watch);
-	if (!libhal_device_query_capability (ctx, udi, "storage.cdrom", NULL))
+	if (!brasero_medium_monitor_is_drive (self, gdrive))
 		return;
 
 	BRASERO_MEDIA_LOG ("New drive added");
 
 	priv = BRASERO_MEDIUM_MONITOR_PRIVATE (self);
-
-	/* Get the gdrive */
-	device_path = libhal_device_get_property_string (ctx,
-	                                                 udi,
-	                                                 "block.device",
-	                                                 NULL);
-	gdrive = brasero_medium_monitor_get_gdrive (self, device_path);
-	g_free (device_path);
-
 	drive = g_object_new (BRASERO_TYPE_DRIVE,
-	                      "udi", udi,
 	                      "gdrive", gdrive,
 	                      NULL);
 	priv->drives = g_slist_prepend (priv->drives, drive);
@@ -409,32 +384,27 @@ brasero_medium_monitor_inserted_cb (BraseroHALWatch *watch,
 }
 
 static void
-brasero_medium_monitor_removed_cb (BraseroHALWatch *watch,
-				   const char *udi,
-				   BraseroMediumMonitor *self)
+brasero_medium_monitor_disconnected_cb (GVolumeMonitor *monitor,
+                                        GDrive *gdrive,
+                                        BraseroMediumMonitor *self)
 {
 	BraseroMediumMonitorPrivate *priv;
-	LibHalContext *ctx;
-	GSList *iter;
 	GSList *next;
+	GSList *iter;
 
-	ctx = brasero_hal_watch_get_ctx (watch);
 	priv = BRASERO_MEDIUM_MONITOR_PRIVATE (self);
 
 	BRASERO_MEDIA_LOG ("HAL signal device removed");
 
 	for (iter = priv->drives; iter; iter = next) {
-		const gchar *device_udi;
+		GDrive *gdrive_iter;
 		BraseroDrive *drive;
 
 		drive = iter->data;
 		next = iter->next;
 
-		device_udi = brasero_drive_get_udi (drive);
-		if (!device_udi)
-			continue;
-
-		if (!strcmp (device_udi, udi)) {
+		gdrive_iter = brasero_drive_get_gdrive (drive);
+		if (gdrive == gdrive_iter) {
 			BraseroMedium *medium;
 
 			BRASERO_MEDIA_LOG ("Drive removed");
@@ -458,12 +428,9 @@ brasero_medium_monitor_removed_cb (BraseroHALWatch *watch,
 static void
 brasero_medium_monitor_init (BraseroMediumMonitor *object)
 {
-	DBusError error;
-	int nb_devices, i;
-	LibHalContext *ctx;
+	GList *iter;
+	GList *drives;
 	BraseroDrive *drive;
-	char **devices = NULL;
-	BraseroHALWatch *watch;
 	BraseroMediumMonitorPrivate *priv;
 
 	priv = BRASERO_MEDIUM_MONITOR_PRIVATE (object);
@@ -473,61 +440,38 @@ brasero_medium_monitor_init (BraseroMediumMonitor *object)
 	 * connect to HAL before us. */
 	priv->gmonitor = g_volume_monitor_get ();
 
-	watch = brasero_hal_watch_get_default ();
-	ctx = brasero_hal_watch_get_ctx (watch);
-
-	g_signal_connect (watch,
-			  "device-added",
-			  G_CALLBACK (brasero_medium_monitor_inserted_cb),
-			  object);
-	g_signal_connect (watch,
-			  "device-removed",
-			  G_CALLBACK (brasero_medium_monitor_removed_cb),
-			  object);
+	drives = g_volume_monitor_get_connected_drives (priv->gmonitor);
+	for (iter = drives; iter; iter = iter->next) {
+		GDrive *gdrive;
 
-	/* Now we get the list and cache it */
-	dbus_error_init (&error);
-	BRASERO_MEDIA_LOG ("Polling for drives");
-	devices = libhal_find_device_by_capability (ctx,
-						    "storage.cdrom", &nb_devices,
-						    &error);
-	if (dbus_error_is_set (&error)) {
-		BRASERO_MEDIA_LOG ("Hal is not running : %s\n", error.message);
-		dbus_error_free (&error);
-		return;
+		gdrive = iter->data;
+		if (brasero_medium_monitor_is_drive (object, gdrive)) {
+			drive = g_object_new (BRASERO_TYPE_DRIVE,
+					      "gdrive", gdrive,
+					      NULL);
+			priv->drives = g_slist_prepend (priv->drives, drive);
+
+			g_signal_connect (drive,
+					  "medium-added",
+					  G_CALLBACK (brasero_medium_monitor_medium_added_cb),
+					  object);
+			g_signal_connect (drive,
+					  "medium-removed",
+					  G_CALLBACK (brasero_medium_monitor_medium_removed_cb),
+					  object);
+		}
 	}
+	g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+	g_list_free (drives);
 
-	BRASERO_MEDIA_LOG ("Found %d drives", nb_devices);
-	for (i = 0; i < nb_devices; i++) {
-		GDrive *gdrive;
-		gchar *device_path;
-
-		/* create the drive */
-		BRASERO_MEDIA_LOG ("Probing %s", devices [i]);
-
-		device_path = libhal_device_get_property_string (ctx,
-								 devices [i],
-								 "block.device",
-								 NULL);
-		gdrive = brasero_medium_monitor_get_gdrive (object, device_path);
-		g_free (device_path);
-
-		drive = g_object_new (BRASERO_TYPE_DRIVE,
-		                      "udi", devices [i],
-		                      "gdrive", gdrive,
-		                      NULL);
-		priv->drives = g_slist_prepend (priv->drives, drive);
-
-		g_signal_connect (drive,
-				  "medium-added",
-				  G_CALLBACK (brasero_medium_monitor_medium_added_cb),
-				  object);
-		g_signal_connect (drive,
-				  "medium-removed",
-				  G_CALLBACK (brasero_medium_monitor_medium_removed_cb),
-				  object);
-	}
-	libhal_free_string_array (devices);
+	g_signal_connect (priv->gmonitor,
+			  "drive-connected",
+			  G_CALLBACK (brasero_medium_monitor_connected_cb),
+			  object);
+	g_signal_connect (priv->gmonitor,
+			  "drive-disconnected",
+			  G_CALLBACK (brasero_medium_monitor_disconnected_cb),
+			  object);
 
 	/* add fake/file drive */
 	drive = g_object_new (BRASERO_TYPE_DRIVE, NULL);
@@ -550,6 +494,12 @@ brasero_medium_monitor_finalize (GObject *object)
 	}
 
 	if (priv->gmonitor) {
+		g_signal_handlers_disconnect_by_func (priv->gmonitor,
+		                                      brasero_medium_monitor_connected_cb,
+		                                      object);
+		g_signal_handlers_disconnect_by_func (priv->gmonitor,
+		                                      brasero_medium_monitor_disconnected_cb,
+		                                      object);
 		g_object_unref (priv->gmonitor);
 		priv->gmonitor = NULL;
 	}
diff --git a/libbrasero-media/scsi-inquiry.c b/libbrasero-media/scsi-inquiry.c
new file mode 100644
index 0000000..8a8fb64
--- /dev/null
+++ b/libbrasero-media/scsi-inquiry.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-media
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-media 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.
+ *
+ * The Libbrasero-media authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-media. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-media is covered. If you modify this code
+ * you may extend this exception to your version of the code, but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
+ * 
+ * Libbrasero-media 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 Library 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.,
+ * 	51 Franklin Street, Fifth Floor
+ * 	Boston, MA  02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "scsi-error.h"
+#include "scsi-utils.h"
+#include "scsi-base.h"
+#include "scsi-command.h"
+#include "scsi-opcodes.h"
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+
+struct _BraseroInquiryCDB {
+	uchar opcode;
+
+	uchar evpd			:1;
+	uchar cmd_dt			:1;
+	uchar reserved0		:6;
+
+	uchar op_code;
+
+	uchar reserved1;
+
+	uchar alloc_len;
+
+	uchar ctl;
+};
+
+#else
+
+struct _BraseroInquiryCDB {
+	uchar opcode;
+
+	uchar reserved0		:6;
+	uchar cmd_dt			:1;
+	uchar evpd			:1;
+
+	uchar op_code;
+
+	uchar reserved1;
+
+	uchar alloc_len;
+
+	uchar ctl;
+};
+
+#endif
+
+typedef struct _BraseroInquiryCDB BraseroInquiryCDB;
+
+BRASERO_SCSI_COMMAND_DEFINE (BraseroInquiryCDB,
+			     INQUIRY,
+			     BRASERO_SCSI_READ);
+
+BraseroScsiResult
+brasero_spc1_inquiry_is_optical_drive (BraseroDeviceHandle *handle,
+                                       BraseroScsiErrCode *error)
+{
+	BraseroInquiryCDB *cdb;
+	uchar data [36] = {0, };
+	BraseroScsiResult res;
+
+	cdb = brasero_scsi_command_new (&info, handle);
+	cdb->alloc_len = sizeof (data);
+
+	res = brasero_scsi_command_issue_sync (cdb,
+					       data,
+					       sizeof (data),
+					       error);
+	brasero_scsi_command_free (cdb);
+
+	if (res != BRASERO_SCSI_OK)
+		return res;
+
+	/* NOTE: 0x05 is for CD/DVD players */
+	return (data [0] & 0x1F) == 0x05? BRASERO_SCSI_OK:BRASERO_SCSI_RECOVERABLE;
+}
+
+ 
diff --git a/libbrasero-media/scsi-spc1.h b/libbrasero-media/scsi-spc1.h
index a12d2d5..6d139ea 100644
--- a/libbrasero-media/scsi-spc1.h
+++ b/libbrasero-media/scsi-spc1.h
@@ -57,6 +57,10 @@ brasero_spc1_mode_select (BraseroDeviceHandle *handle,
 			  int size,
 			  BraseroScsiErrCode *error);
 
+BraseroScsiResult
+brasero_spc1_inquiry_is_optical_drive (BraseroDeviceHandle *handle,
+                                       BraseroScsiErrCode *error);
+
 G_END_DECLS
 
 #endif /* _BURN_SPC1_H */



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