brasero r1382 - in trunk: . src



Author: philippr
Date: Wed Oct 15 18:23:12 2008
New Revision: 1382
URL: http://svn.gnome.org/viewvc/brasero?rev=1382&view=rev

Log:
	Probe for medium asynchronously and avoid blocking sometimes

	* src/burn-drive.c (brasero_drive_get_medium),
	(brasero_drive_medium_probed), (brasero_drive_reprobe),
	(brasero_drive_check_medium_inside):
	* src/burn-drive.h:
	* src/burn-medium.c (brasero_medium_get_sessions_info),
	(brasero_medium_init_real), (brasero_medium_probed),
	(brasero_medium_probe_thread), (brasero_medium_probe),
	(brasero_medium_finalize), (brasero_medium_set_property),
	(brasero_medium_class_init):
	* src/burn-medium.h:
	* src/burn.c (brasero_burn_record_session):


Modified:
   trunk/ChangeLog
   trunk/src/burn-drive.c
   trunk/src/burn-drive.h
   trunk/src/burn-medium.c
   trunk/src/burn-medium.h
   trunk/src/burn.c

Modified: trunk/src/burn-drive.c
==============================================================================
--- trunk/src/burn-drive.c	(original)
+++ trunk/src/burn-drive.c	Wed Oct 15 18:23:12 2008
@@ -65,6 +65,8 @@
 	gint lun;
 
 	gulong hal_sig;
+
+	guint probed:1;
 };
 
 #define BRASERO_DRIVE_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_DRIVE, BraseroDrivePrivate))
@@ -288,6 +290,10 @@
 		return NULL;
 
 	priv = BRASERO_DRIVE_PRIVATE (self);
+
+	if (!priv->probed && priv->udi)
+		return NULL;
+
 	return priv->medium;
 }
 
@@ -365,6 +371,56 @@
 }
 
 static void
+brasero_drive_medium_probed (BraseroMedium *medium,
+			     BraseroDrive *self)
+{
+	BraseroDrivePrivate *priv;
+
+	priv = BRASERO_DRIVE_PRIVATE (self);
+
+	/* only when it is probed */
+	priv->probed = TRUE;
+	g_signal_emit (self,
+		       drive_signals [MEDIUM_INSERTED],
+		       0,
+		       priv->medium);
+}
+
+void
+brasero_drive_reprobe (BraseroDrive *self)
+{
+	BraseroDrivePrivate *priv;
+	BraseroMedium *medium;
+
+	priv = BRASERO_DRIVE_PRIVATE (self);
+
+	if (!priv->medium)
+		return;
+
+	BRASERO_BURN_LOG ("Reprobing inserted medium");
+
+	/* remove current medium */
+	medium = priv->medium;
+	priv->medium = NULL;
+
+	g_signal_emit (self,
+		       drive_signals [MEDIUM_REMOVED],
+		       0,
+		       medium);
+	g_object_unref (medium);
+	priv->probed = FALSE;
+
+	/* try to get a new one */
+	priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
+				     "drive", self,
+				     NULL);
+	g_signal_connect (priv->medium,
+			  "probed",
+			  G_CALLBACK (brasero_drive_medium_probed),
+			  self);
+}
+
+static void
 brasero_drive_check_medium_inside (BraseroDrive *self)
 {
 	BraseroDrivePrivate *priv;
@@ -393,16 +449,17 @@
 	}
 
 	if (has_medium) {
-		BRASERO_BURN_LOG ("New medium inserted");
+		BRASERO_BURN_LOG ("Medium inserted");
 
+		priv->probed = FALSE;
 		priv->medium = g_object_new (BRASERO_TYPE_VOLUME,
 					     "drive", self,
 					     NULL);
-		if (priv->medium)
-			g_signal_emit (self,
-				       drive_signals [MEDIUM_INSERTED],
-				       0,
-				       priv->medium);
+
+		g_signal_connect (priv->medium,
+				  "probed",
+				  G_CALLBACK (brasero_drive_medium_probed),
+				  self);
 	}
 	else if (priv->medium) {
 		BraseroMedium *medium;
@@ -417,6 +474,7 @@
 			       0,
 			       medium);
 		g_object_unref (medium);
+		priv->probed = FALSE;
 	}
 }
 

Modified: trunk/src/burn-drive.h
==============================================================================
--- trunk/src/burn-drive.h	(original)
+++ trunk/src/burn-drive.h	Wed Oct 15 18:23:12 2008
@@ -68,6 +68,9 @@
 BraseroDrive *
 brasero_drive_new (const gchar *udi);
 
+void
+brasero_drive_reprobe (BraseroDrive *drive);
+
 BraseroMedium *
 brasero_drive_get_medium (BraseroDrive *drive);
 

Modified: trunk/src/burn-medium.c
==============================================================================
--- trunk/src/burn-medium.c	(original)
+++ trunk/src/burn-medium.c	Wed Oct 15 18:23:12 2008
@@ -28,6 +28,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <unistd.h>
 
 #include <glib.h>
 #include <glib/gi18n-lib.h>
@@ -88,7 +89,8 @@
 typedef struct _BraseroMediumPrivate BraseroMediumPrivate;
 struct _BraseroMediumPrivate
 {
-	gint retry_id;
+	GThread *probe;
+	gint probe_id;
 
 	GSList *tracks;
 
@@ -118,6 +120,8 @@
 	guint dummy_sao:2;
 	guint dummy_tao:2;
 	guint burnfree:2;
+
+	guint probe_cancelled:1;
 };
 
 #define BRASERO_MEDIUM_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM, BraseroMediumPrivate))
@@ -137,6 +141,14 @@
 	PROP_DRIVE,
 };
 
+enum {
+	PROBED,
+	LAST_SIGNAL
+};
+static gulong medium_signals [LAST_SIGNAL] = {0, };
+
+#define BRASERO_MEDIUM_OPEN_ATTEMPTS			5
+
 static GObjectClass* parent_class = NULL;
 
 gchar *
@@ -1750,6 +1762,11 @@
 			continue;
 		}
 
+		if (priv->probe_cancelled) {
+			g_free (toc);
+			return BRASERO_BURN_CANCEL;
+		}
+
 		brasero_medium_track_get_info (self,
 					       multisession,
 					       track,
@@ -1758,6 +1775,11 @@
 					       code);
 	}
 
+	if (priv->probe_cancelled) {
+		g_free (toc);
+		return BRASERO_BURN_CANCEL;
+	}
+
 	/* put the tracks in the right order */
 	priv->tracks = g_slist_reverse (priv->tracks);
 
@@ -2815,27 +2837,45 @@
 	BRASERO_BURN_LOG ("Initializing information for medium in %s", name);
 	g_free (name);
 
+	if (priv->probe_cancelled)
+		return;
+
 	result = brasero_medium_get_medium_type (object, handle, &code);
 	if (result != BRASERO_BURN_OK)
 		return;
 
+	if (priv->probe_cancelled)
+		return;
+
 	brasero_medium_get_capacity_by_type (object, handle, &code);
 
 	result = brasero_medium_get_contents (object, handle, &code);
 	if (result != BRASERO_BURN_OK)
 		return;
 
+	if (priv->probe_cancelled)
+		return;
+
 	/* assume that css feature is only for DVD-ROM which might be wrong but
 	 * some drives wrongly reports that css is enabled for blank DVD+R/W */
 	if (BRASERO_MEDIUM_IS (priv->info, (BRASERO_MEDIUM_DVD|BRASERO_MEDIUM_ROM)))
 		brasero_medium_get_css_feature (object, handle, &code);
 
+	if (priv->probe_cancelled)
+		return;
+
 	brasero_medium_init_caps (object, handle, &code);
 
+	if (priv->probe_cancelled)
+		return;
+
 	/* read CD-TEXT title */
 	if (priv->info & BRASERO_MEDIUM_HAS_AUDIO)
 		brasero_medium_read_CD_TEXT (object, handle, &code);
 
+	if (priv->probe_cancelled)
+		return;
+
 	BRASERO_BURN_LOG_DISC_TYPE (priv->info, "media is ");
 
 	if (!priv->wr_speeds)
@@ -2858,48 +2898,25 @@
 }
 
 static gboolean
-brasero_medium_retry_open (gpointer object)
+brasero_medium_probed (gpointer data)
 {
-	const gchar *path;
-	BraseroMedium *self;
-	BraseroScsiErrCode code;
 	BraseroMediumPrivate *priv;
-	BraseroDeviceHandle *handle;
 
-	self = BRASERO_MEDIUM (object);
-	priv = BRASERO_MEDIUM_PRIVATE (object);
-	path = brasero_drive_get_device (priv->drive);
+	priv = BRASERO_MEDIUM_PRIVATE (data);
 
-	BRASERO_BURN_LOG ("Retrying to open device %s", path);
-	handle = brasero_device_handle_open (path, &code);
-	if (!handle) {
-		if (code == BRASERO_SCSI_NOT_READY) {
-			BRASERO_BURN_LOG ("Device busy");
-			/* we'll retry in a second */
-			return TRUE;
-		}
-
-		BRASERO_BURN_LOG ("Open () failed");
-		priv->info = BRASERO_MEDIUM_UNSUPPORTED;
-		priv->retry_id = 0;
-		return FALSE;
-	}
-
-	BRASERO_BURN_LOG ("Open () succeeded\n");
-	priv->info = BRASERO_MEDIUM_NONE;
-	priv->icon = icons [0];
-
-	priv->retry_id = 0;
-
-	brasero_medium_init_real (self, handle);
-	brasero_device_handle_close (handle);
+	/* This signal must be emitted in the main thread */
+	g_signal_emit (data,
+		       medium_signals [PROBED],
+		       0);
 
+	priv->probe_id = 0;
 	return FALSE;
 }
 
-static void
-brasero_medium_try_open (BraseroMedium *self)
+static gpointer
+brasero_medium_probe_thread (gpointer self)
 {
+	gint counter = 0;
 	const gchar *path;
 	BraseroScsiErrCode code;
 	BraseroMediumPrivate *priv;
@@ -2908,75 +2925,60 @@
 	priv = BRASERO_MEDIUM_PRIVATE (self);
 	path = brasero_drive_get_device (priv->drive);
 
+	priv->info = BRASERO_MEDIUM_BUSY;
+	priv->icon = icons [0];
+
 	/* the drive might be busy (a burning is going on) so we don't block
 	 * but we re-try to open it every second */
 	BRASERO_BURN_LOG ("Trying to open device %s", path);
+
 	handle = brasero_device_handle_open (path, &code);
+	while (!handle && counter <= BRASERO_MEDIUM_OPEN_ATTEMPTS) {
+		sleep (1);
 
-	if (!handle) {
-		if (code == BRASERO_SCSI_NOT_READY) {
-			BRASERO_BURN_LOG ("Device busy");
-			priv->info = BRASERO_MEDIUM_BUSY;
-			priv->icon = icons [0];
-
-			priv->retry_id = g_timeout_add (BUSY_RETRY_TIME,
-							brasero_medium_retry_open,
-							self);
+		if (priv->probe_cancelled) {
+			priv->probe = NULL;
+			return NULL;
 		}
 
-		BRASERO_BURN_LOG ("Open () failed");
-		return;
+		counter ++;
+		handle = brasero_device_handle_open (path, &code);
 	}
 
-	BRASERO_BURN_LOG ("Open () succeeded");
-	brasero_medium_init_real (self, handle);
-	brasero_device_handle_close (handle);
-}
-
-void
-brasero_medium_reload_info (BraseroMedium *self)
-{
-	BraseroMediumPrivate *priv;
-
-	g_return_if_fail (BRASERO_IS_MEDIUM (self));
-
-	priv = BRASERO_MEDIUM_PRIVATE (self);
-
-	priv->max_rd = 0;
-	priv->max_wrt = 0;
-	priv->block_num = 0;
-	priv->block_size = 0;
-	priv->next_wr_add = -1;
-	priv->type = NULL;
-	priv->icon = NULL;
-	priv->info = BRASERO_MEDIUM_NONE;
-
-	if (priv->retry_id) {
-		g_source_remove (priv->retry_id);
-		priv->retry_id = 0;
+	if (priv->probe_cancelled) {
+		priv->probe = NULL;
+		return NULL;
 	}
 
-	if (priv->id) {
-		g_free (priv->id);
-		priv->id = NULL;
-	}
-
-	if (priv->CD_TEXT_title) {
-		g_free (priv->CD_TEXT_title);
-		priv->CD_TEXT_title = NULL;
+	if (handle) {
+		BRASERO_BURN_LOG ("Open () succeeded");
+		brasero_medium_init_real (BRASERO_MEDIUM (self), handle);
+		brasero_device_handle_close (handle);
 	}
+	else
+		BRASERO_BURN_LOG ("Open () failed: medium busy");
 
-	g_free (priv->rd_speeds);
-	priv->rd_speeds = NULL;
+	priv->probe_id = g_idle_add (brasero_medium_probed, self);
+	priv->probe = NULL;
+	return NULL;
+}
 
-	g_free (priv->wr_speeds);
-	priv->wr_speeds = NULL;
+static void
+brasero_medium_probe (BraseroMedium *self)
+{
+	BraseroMediumPrivate *priv;
 
-	g_slist_foreach (priv->tracks, (GFunc) g_free, NULL);
-	g_slist_free (priv->tracks);
-	priv->tracks = NULL;
+	priv = BRASERO_MEDIUM_PRIVATE (self);
 
-	brasero_medium_try_open (self);
+	/* NOTE: why a thread? Because in case of a damaged medium, brasero can
+	 * block on some functions until timeout and if we do this in the main
+	 * thread then our whole UI blocks. This medium won't be exported by the
+	 * BraseroDrive that exported until it returns PROBED signal.
+	 * One (good) side effect is that it also improves start time. */
+	priv->probe = g_thread_create (brasero_medium_probe_thread,
+				       self,
+				       TRUE,
+				       NULL);
 }
 
 static void
@@ -3009,9 +3011,15 @@
 
 	priv = BRASERO_MEDIUM_PRIVATE (object);
 
-	if (priv->retry_id) {
-		g_source_remove (priv->retry_id);
-		priv->retry_id = 0;
+	if (priv->probe) {
+		priv->probe_cancelled = TRUE;
+		g_thread_join (priv->probe);
+		priv->probe = 0;
+	}
+
+	if (priv->probe_id) {
+		g_source_remove (priv->probe_id);
+		priv->probe_id = 0;
 	}
 
 	if (priv->id) {
@@ -3061,7 +3069,7 @@
 			break;
 		}
 
-		brasero_medium_try_open (BRASERO_MEDIUM (object));
+		brasero_medium_probe (BRASERO_MEDIUM (object));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -3101,6 +3109,16 @@
 	object_class->set_property = brasero_medium_set_property;
 	object_class->get_property = brasero_medium_get_property;
 
+	medium_signals[PROBED] =
+		g_signal_new ("probed",
+		              G_OBJECT_CLASS_TYPE (klass),
+		              G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
+		              0,
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0,
+		              G_TYPE_NONE);
+
 	g_object_class_install_property (object_class,
 	                                 PROP_DRIVE,
 	                                 g_param_spec_object ("drive",

Modified: trunk/src/burn-medium.h
==============================================================================
--- trunk/src/burn-medium.h	(original)
+++ trunk/src/burn-medium.h	Wed Oct 15 18:23:12 2008
@@ -91,8 +91,6 @@
 };
 typedef struct _BraseroMediumTrack BraseroMediumTrack;
 
-void
-brasero_medium_reload_info (BraseroMedium *self);
 
 BraseroMedia
 brasero_medium_get_status (BraseroMedium *medium);

Modified: trunk/src/burn.c
==============================================================================
--- trunk/src/burn.c	(original)
+++ trunk/src/burn.c	Wed Oct 15 18:23:12 2008
@@ -2114,21 +2114,19 @@
 	if (result != BRASERO_BURN_OK)
 		return result;
 
-	medium = brasero_drive_get_medium (priv->dest);
-	brasero_medium_reload_info (medium);
+	/* reprobe the medium and wait for it to be probed */
+	brasero_drive_reprobe (priv->dest);
+	while (!(medium = brasero_drive_get_medium (priv->dest)))
+		brasero_burn_sleep (burn, 1000);
 
 	if (type == BRASERO_CHECKSUM_MD5
 	||  type == BRASERO_CHECKSUM_SHA1
 	||  type == BRASERO_CHECKSUM_SHA256) {
 		BraseroMedia media;
-		BraseroDrive *drive;
-		BraseroMedium *medium;
 
 		/* get the last written track address in case of DVD+RW/DVD-RW
 		 * restricted overwrite since there is no such thing as track
 		 * number for these drives. */
-		drive = brasero_burn_session_get_burner (priv->session);
-		medium = brasero_drive_get_medium (drive);
 		media = brasero_medium_get_status (medium);
 
 		if (!BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW_PLUS)



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