[brasero/gnome-2-28] Allow a job to delay its start (when a drive is busy for example)



commit 29c9e29f63bd6b7c9d8a97ac805e390c3d0befe6
Author: Philippe Rouquier <bonfire-app wanadoo fr>
Date:   Fri Oct 2 11:40:25 2009 +0200

    Allow a job to delay its start (when a drive is busy for example)
    This allows libburn to wait for the drive to be ready sometimes

 libbrasero-burn/burn-job.h       |   14 ++++---
 libbrasero-burn/burn-task.c      |   74 +++++++++++++++++++++++++++++++++++++-
 plugins/libburnia/burn-libburn.c |   28 ++++++++++++--
 3 files changed, 105 insertions(+), 11 deletions(-)
---
diff --git a/libbrasero-burn/burn-job.h b/libbrasero-burn/burn-job.h
index de19bdd..25b417d 100644
--- a/libbrasero-burn/burn-job.h
+++ b/libbrasero-burn/burn-job.h
@@ -80,12 +80,14 @@ typedef struct {
 	/**
 	 * This function is compulsory.
 	 * returns 	BRASERO_BURN_OK if a loop should be run afterward
-	 *		The job can return BRASERO_BURN_NOT_RUNNING if it can't
-	 *		or already completed successfully the task then ::start
-	 * 		won't be called
-	 *		NOT_SUPPORTED if it can't do the action required. It
-	 *		must be noted that jobs can be required to do a SIZE 
-	 * 		action.
+	 *		The job can return BRASERO_BURN_NOT_RUNNING if it already
+	 *		completed successfully the task or don't need to be run. In this
+	 *		case, it's the whole task that will be skipped.
+	 *		NOT_SUPPORTED if it can't do the action required. When running
+	 *		in fake mode (to get size mostly), the job will be "forgiven" and
+	 *		deactivated.
+	 *		RETRY if the job is not able to start at the moment but should
+	 *		be given another chance later.
 	 * 		ERR otherwise
 	 */
 	BraseroBurnResult	(*start)		(BraseroJob *job,
diff --git a/libbrasero-burn/burn-task.c b/libbrasero-burn/burn-task.c
index 98fd7e6..a3bf84a 100644
--- a/libbrasero-burn/burn-task.c
+++ b/libbrasero-burn/burn-task.c
@@ -74,6 +74,9 @@ G_DEFINE_TYPE (BraseroTask, brasero_task, BRASERO_TYPE_TASK_CTX);
 
 static GObjectClass *parent_class = NULL;
 
+#define MAX_JOB_START_ATTEMPTS			5
+#define JOB_ATTEMPTS_WAIT_TIME			1
+
 void
 brasero_task_add_item (BraseroTask *task, BraseroTaskItem *item)
 {
@@ -230,12 +233,58 @@ brasero_task_send_stop_signal (BraseroTask *task,
 	return (result == BRASERO_BURN_OK? retval:result);
 }
 
+static gboolean
+brasero_task_wakeup (gpointer user_data)
+{
+	BraseroTaskPrivate *priv;
+
+	priv = BRASERO_TASK_PRIVATE (user_data);
+
+	if (priv->loop)
+		g_main_loop_quit (priv->loop);
+
+	priv->clock_id = 0;
+	priv->retval = BRASERO_BURN_OK;
+	return FALSE;
+}
+
+static BraseroBurnResult
+brasero_task_sleep (BraseroTask *self, guint sec)
+{
+	BraseroTaskPrivate *priv;
+
+	priv = BRASERO_TASK_PRIVATE (self);
+
+	BRASERO_BURN_LOG ("wait loop");
+
+	priv->loop = g_main_loop_new (NULL, FALSE);
+	priv->clock_id = g_timeout_add_seconds (sec,
+	                                        brasero_task_wakeup,
+	                                        self);
+
+	GDK_THREADS_LEAVE ();  
+	g_main_loop_run (priv->loop);
+	GDK_THREADS_ENTER ();
+
+	g_main_loop_unref (priv->loop);
+	priv->loop = NULL;
+
+	if (priv->clock_id) {
+		g_source_remove (priv->clock_id);
+		priv->clock_id = 0;
+	}
+
+	return priv->retval;
+}
+
 static BraseroBurnResult
 brasero_task_start_item (BraseroTask *task,
 			 BraseroTaskItem *item,
 			 GError **error)
 {
+	guint attempts = 0;
 	BraseroBurnResult result;
+	GError *ret_error = NULL;
 	BraseroTaskItemIFace *klass;
 
 	klass = BRASERO_TASK_ITEM_GET_CLASS (item);
@@ -244,7 +293,29 @@ brasero_task_start_item (BraseroTask *task,
 
 	BRASERO_BURN_LOG ("::start method %s", G_OBJECT_TYPE_NAME (item));
 
-	result = klass->start (item, error);
+	result = klass->start (item, &ret_error);
+	while (result == BRASERO_BURN_RETRY) {
+		/* FIXME: a GError?? */
+		if (attempts >= MAX_JOB_START_ATTEMPTS) {
+			if (ret_error)
+				g_propagate_error (error, ret_error);
+
+			return BRASERO_BURN_ERR;
+		}
+
+		if (ret_error) {
+			g_error_free (ret_error);
+			ret_error = NULL;
+		}
+
+		result = brasero_task_sleep (task, 1);
+		if (result != BRASERO_BURN_OK)
+			return result;
+
+		attempts ++;
+		result = klass->start (item, &ret_error);
+	}
+
 	return result;
 }
 
@@ -364,6 +435,7 @@ brasero_task_run_loop (BraseroTask *self,
 					self);
 
 	priv->loop = g_main_loop_new (NULL, FALSE);
+
 	BRASERO_BURN_LOG ("entering loop");
 
 	GDK_THREADS_LEAVE ();  
diff --git a/plugins/libburnia/burn-libburn.c b/plugins/libburnia/burn-libburn.c
index 68a1440..fa1ff67 100644
--- a/plugins/libburnia/burn-libburn.c
+++ b/plugins/libburnia/burn-libburn.c
@@ -731,9 +731,19 @@ brasero_libburn_start (BraseroJob *job,
 
 	brasero_job_get_action (job, &action);
 	if (action == BRASERO_JOB_ACTION_RECORD) {
-		priv->ctx = brasero_libburn_common_ctx_new (job, error);
-		if (!priv->ctx)
+		GError *ret_error = NULL;
+
+		priv->ctx = brasero_libburn_common_ctx_new (job, &ret_error);
+		if (!priv->ctx) {
+			if (ret_error && ret_error->code == BRASERO_BURN_ERROR_DRIVE_BUSY) {
+				g_propagate_error (error, ret_error);
+				return BRASERO_BURN_RETRY;
+			}
+
+			if (error)
+				g_propagate_error (error, ret_error);
 			return BRASERO_BURN_ERR;
+		}
 
 		result = brasero_libburn_start_record (self, error);
 		if (result != BRASERO_BURN_OK)
@@ -745,9 +755,19 @@ brasero_libburn_start (BraseroJob *job,
 						FALSE);
 	}
 	else if (action == BRASERO_JOB_ACTION_ERASE) {
-		priv->ctx = brasero_libburn_common_ctx_new (job, error);
-		if (!priv->ctx)
+		GError *ret_error = NULL;
+
+		priv->ctx = brasero_libburn_common_ctx_new (job, &ret_error);
+		if (!priv->ctx) {
+			if (ret_error && ret_error->code == BRASERO_BURN_ERROR_DRIVE_BUSY) {
+				g_propagate_error (error, ret_error);
+				return BRASERO_BURN_RETRY;
+			}
+
+			if (error)
+				g_propagate_error (error, ret_error);
 			return BRASERO_BURN_ERR;
+		}
 
 		result = brasero_libburn_start_erase (self, error);
 		if (result != BRASERO_BURN_OK)



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