brasero r1317 - in trunk: . src



Author: philippr
Date: Sun Sep 28 18:48:39 2008
New Revision: 1317
URL: http://svn.gnome.org/viewvc/brasero?rev=1317&view=rev

Log:
	Fix #549852 â Data DVD+RW detected badly as multisession
	Greatly improved performance when loading session (now it\'s done async)
	and save memory by not loading all nodes

	* src/brasero-burn-options.c (brasero_burn_options_valid_media_cb):
	* src/brasero-data-project.c
	(brasero_data_project_add_imported_session_file):
	* src/brasero-data-project.h:
	* src/brasero-data-session.c
	(brasero_data_session_load_dir_destroy),
	(brasero_data_session_load_dir_result),
	(brasero_data_session_load_directory_contents_real),
	(brasero_data_session_load_directory_contents),
	(brasero_data_session_add_last), (brasero_data_session_stop_io),
	(brasero_data_session_reset), (brasero_data_session_finalize),
	(brasero_data_session_class_init):
	* src/brasero-data-session.h:
	* src/brasero-data-tree-model.c
	(brasero_data_tree_model_node_shown):
	* src/brasero-dest-selection.c (brasero_dest_selection_finalize):
	* src/brasero-file-node.c
	(brasero_file_node_new_imported_session_file):
	* src/brasero-file-node.h:
	* src/brasero-io.c (brasero_io_image_directory_contents_destroy),
	(brasero_io_image_directory_contents_thread),
	(brasero_io_load_image_directory):
	* src/brasero-io.h:
	* src/brasero-tool-dialog.c (brasero_tool_dialog_init):
	* src/burn-iso9660.c (brasero_iso9660_get_first_directory_record),
	(brasero_iso9660_read_directory_record),
	(brasero_iso9660_load_directory_records),
	(brasero_iso9660_check_SUSP_RR_use), (brasero_iso9660_ctx_init),
	(brasero_iso9660_get_contents), (brasero_iso9660_get_file),
	(brasero_iso9660_get_directory_contents):
	* src/burn-iso9660.h:
	* src/burn-volume.c (brasero_volume_file_free),
	(brasero_volume_get_files),
	(brasero_volume_load_directory_contents):
	* src/burn-volume.h:

Modified:
   trunk/ChangeLog
   trunk/src/brasero-burn-options.c
   trunk/src/brasero-data-project.c
   trunk/src/brasero-data-project.h
   trunk/src/brasero-data-session.c
   trunk/src/brasero-data-session.h
   trunk/src/brasero-data-tree-model.c
   trunk/src/brasero-dest-selection.c
   trunk/src/brasero-file-node.c
   trunk/src/brasero-file-node.h
   trunk/src/brasero-io.c
   trunk/src/brasero-io.h
   trunk/src/brasero-tool-dialog.c
   trunk/src/burn-iso9660.c
   trunk/src/burn-iso9660.h
   trunk/src/burn-volume.c
   trunk/src/burn-volume.h

Modified: trunk/src/brasero-burn-options.c
==============================================================================
--- trunk/src/brasero-burn-options.c	(original)
+++ trunk/src/brasero-burn-options.c	Sun Sep 28 18:48:39 2008
@@ -305,13 +305,7 @@
 				  G_CALLBACK (brasero_burn_options_message_response_cb),
 				  self);
 	}
-/*	else if (valid == BRASERO_SESSION_BLANKING) {
-		
-	}
-	else if (valid == BRASERO_SESSION_APPENDING) {
-		
-	}
-*/
+
 	gtk_window_resize (GTK_WINDOW (self), 10, 10);
 }
 

Modified: trunk/src/brasero-data-project.c
==============================================================================
--- trunk/src/brasero-data-project.c	(original)
+++ trunk/src/brasero-data-project.c	Sun Sep 28 18:48:39 2008
@@ -1584,7 +1584,7 @@
 
 BraseroFileNode *
 brasero_data_project_add_imported_session_file (BraseroDataProject *self,
-						BraseroVolFile *file,
+						GFileInfo *info,
 						BraseroFileNode *parent)
 {
 	BraseroFileNode *node;
@@ -1592,14 +1592,14 @@
 	BraseroDataProjectPrivate *priv;
 
 	g_return_val_if_fail (BRASERO_IS_DATA_PROJECT (self), NULL);
-	g_return_val_if_fail (file != NULL, NULL);
+	g_return_val_if_fail (info != NULL, NULL);
 
 	priv = BRASERO_DATA_PROJECT_PRIVATE (self);
 
 	if (!parent)
 		parent = priv->root;
 
-	node = brasero_file_node_check_name_existence (parent, BRASERO_VOLUME_FILE_NAME (file));
+	node = brasero_file_node_check_name_existence (parent, g_file_info_get_name (info));
 	if (node) {
 		/* The node exists but it may be that we've loaded the project
 		 * before. Then the necessary directories to hold the grafted
@@ -1642,7 +1642,7 @@
 		brasero_data_project_remove_real (self, node);
 	}
 
-	node = brasero_file_node_new_imported_session_file (file, parent, priv->sort_func);
+	node = brasero_file_node_new_imported_session_file (info, parent, priv->sort_func);
 
 	/* In this case, there can be no graft, and furthermore the
 	 * lengths of the names are not our problem. Just signal that

Modified: trunk/src/brasero-data-project.h
==============================================================================
--- trunk/src/brasero-data-project.h	(original)
+++ trunk/src/brasero-data-project.h	Sun Sep 28 18:48:39 2008
@@ -154,7 +154,7 @@
 					  BraseroFileNode *parent);
 BraseroFileNode *
 brasero_data_project_add_imported_session_file (BraseroDataProject *project,
-						BraseroVolFile *file,
+						GFileInfo *info,
 						BraseroFileNode *parent);
 
 void

Modified: trunk/src/brasero-data-session.c
==============================================================================
--- trunk/src/brasero-data-session.c	(original)
+++ trunk/src/brasero-data-session.c	Sun Sep 28 18:48:39 2008
@@ -39,12 +39,16 @@
 #include "brasero-data-session.h"
 #include "brasero-data-project.h"
 #include "brasero-file-node.h"
+#include "brasero-io.h"
 
 #include "brasero-marshal.h"
 
 typedef struct _BraseroDataSessionPrivate BraseroDataSessionPrivate;
 struct _BraseroDataSessionPrivate
 {
+	BraseroIO *io;
+	BraseroIOJobBase *load_dir;
+
 	/* Multisession drives that are inserted */
 	GSList *media;
 
@@ -187,154 +191,155 @@
 }
 
 static void
-brasero_data_session_add_children_files (BraseroDataSession *self,
-					 BraseroFileNode *parent,
-					 GList *children)
-{
-	for (; children; children = children->next) {
-		BraseroFileNode *node;
-		BraseroVolFile *child;
+brasero_data_session_load_dir_destroy (GObject *object,
+				       gboolean cancelled,
+				       gpointer data)
+{
+	gint reference;
+	BraseroFileNode *parent;
+
+	/* reference */
+	reference = GPOINTER_TO_INT (data);
+	if (reference <= 0)
+		return;
 
-		child = children->data;
-		node = brasero_data_project_add_imported_session_file (BRASERO_DATA_PROJECT (self),
-								       child,
-								       parent);
-
-		/* There is little chance that a NULL node will be returned and
-		 * logically that shouldn't be the case. But who knows bugs
-		 * happen, let's try not to crash. ;) */
-		if (node && !node->is_file)
-			brasero_data_session_add_children_files (self,
-								 node,
-								 child->specific.dir.children);
-	}
+	parent = brasero_data_project_reference_get (BRASERO_DATA_PROJECT (object), reference);
+	if (parent)
+		parent->is_exploring = FALSE;
+
+	brasero_data_project_reference_free (BRASERO_DATA_PROJECT (object), reference);
 }
 
-gboolean
-brasero_data_session_add_last (BraseroDataSession *self,
-			       BraseroMedium *medium,
-			       GError **error)
+static void
+brasero_data_session_load_dir_result (GObject *owner,
+				      GError *error,
+				      const gchar *dev_image,
+				      GFileInfo *info,
+				      gpointer data)
 {
 	BraseroDataSessionPrivate *priv;
-	BraseroDeviceHandle *handle;
-	BraseroVolFile *volume;
-	BraseroScsiErrCode err;
-	BraseroDrive *drive;
-	const gchar *device;
-	BraseroVolSrc *vol;
-	gint64 block;
-	GList *iter;
+	BraseroFileNode *parent;
+	BraseroFileNode *node;
+	gint reference;
+
+	priv = BRASERO_DATA_SESSION_PRIVATE (owner);
+
+	if (!info) {
+		g_signal_emit (owner,
+			       brasero_data_session_signals [LOADED_SIGNAL],
+			       0,
+			       priv->loaded,
+			       FALSE);
+/*		error = g_error_new (BRASERO_BURN_ERROR,
+				     BRASERO_BURN_ERROR_GENERAL,
+				     _("unknown volume type"));
+*/		return;
+	}
+
+	reference = GPOINTER_TO_INT (data);
+	if (reference > 0)
+		parent = brasero_data_project_reference_get (BRASERO_DATA_PROJECT (owner),
+							     reference);
+	else
+		parent = NULL;
 
-	priv = BRASERO_DATA_SESSION_PRIVATE (self);
+	/* add all the files/folders at the root of the session */
+	node = brasero_data_project_add_imported_session_file (BRASERO_DATA_PROJECT (owner),
+							       info,
+							       parent);
+	if (!node) {
+		/* a problem ? */
+		g_signal_emit (owner,
+			       brasero_data_session_signals [LOADED_SIGNAL],
+			       0,
+			       priv->loaded,
+			       FALSE);
+		return;
+ 	}
 
-	if (!g_slist_find (priv->media, medium)) {
-		g_set_error (error,
-			     BRASERO_BURN_ERROR,
-			     BRASERO_BURN_ERROR_GENERAL,
-			     _("there isn't any available session on the disc"));
-		return FALSE;
-	}
+	/* Only if we're exploring root directory */
+	if (!parent)
+		priv->nodes = g_slist_prepend (priv->nodes, node);
 
-	if (priv->loaded == medium)
-		return TRUE;
+	g_signal_emit (owner,
+		       brasero_data_session_signals [LOADED_SIGNAL],
+		       0,
+		       priv->loaded,
+		       TRUE);
+}
 
-	/* Remove the old imported session if any */
-	if (priv->nodes)
-		brasero_data_session_remove_last (self);
+static gboolean
+brasero_data_session_load_directory_contents_real (BraseroDataSession *self,
+						   BraseroFileNode *node,
+						   GError **error)
+{
+	BraseroDataSessionPrivate *priv;
+	gint64 session_block;
+	const gchar *device;
+	gint reference = -1;
 
-	if (priv->loaded) {
-		g_object_unref (priv->loaded);
-		priv->loaded = NULL;
-	}
-	
-	/* get the address for the last track and retrieve the file list */
-	brasero_medium_get_last_data_track_address (medium,
+	if (node && !node->is_fake)
+		return TRUE;
+
+	priv = BRASERO_DATA_SESSION_PRIVATE (self);
+	device = brasero_drive_get_device (brasero_medium_get_drive (priv->loaded));
+	brasero_medium_get_last_data_track_address (priv->loaded,
 						    NULL,
-						    &block);
-	if (block == -1) {
-		g_set_error (error,
-			     BRASERO_BURN_ERROR,
-			     BRASERO_BURN_ERROR_GENERAL,
-			     _("there isn't any available session on the disc"));
-		return FALSE;
-	}
-
-	drive = brasero_medium_get_drive (medium);
- 	device = brasero_drive_get_device (drive);
-	handle = brasero_device_handle_open (device, &err);
-	if (!handle) {
-		g_set_error (error,
-			     BRASERO_BURN_ERROR,
-			     BRASERO_BURN_ERROR_GENERAL,
-			     brasero_scsi_strerror (err));
-		return FALSE;
-	}
-
-	vol = brasero_volume_source_open_device_handle (handle, error);
-	volume = brasero_volume_get_files (vol,
-					   block,
-					   NULL,
-					   NULL,
-					   NULL,
-					   error);
-	brasero_device_handle_close (handle);
-	brasero_volume_source_close (vol);
-	if (*error) {
-		if (volume)
-			brasero_volume_file_free (volume);
-		return FALSE;
-	}
-
-	if (!volume) {
-		g_set_error (error,
-			     BRASERO_BURN_ERROR,
-			     BRASERO_BURN_ERROR_GENERAL,
-			     _("unknown volume type"));
-		return FALSE;
-	}
+						    &session_block);
+	if (!priv->io)
+		priv->io = brasero_io_get_default ();
+
+	if (!priv->load_dir)
+		priv->load_dir = brasero_io_register (G_OBJECT (self),
+						      brasero_data_session_load_dir_result,
+						      brasero_data_session_load_dir_destroy,
+						      NULL);
+
+	/* If there aren't any node then that's root */
+	if (node) {
+		reference = brasero_data_project_reference_new (BRASERO_DATA_PROJECT (self), node);
+		node->is_exploring = TRUE;
+	}
+
+	brasero_io_load_image_directory (priv->io,
+					 device,
+					 session_block,
+					 BRASERO_FILE_NODE_IMPORTED_ADDRESS (node),
+					 priv->load_dir,
+					 BRASERO_IO_INFO_URGENT,
+					 GINT_TO_POINTER (reference));
 
-	/* add all the files/folders at the root of the session */
-	for (iter = volume->specific.dir.children; iter; iter = iter->next) {
-		BraseroVolFile *file;
-		BraseroFileNode *node;
+	if (node)
+		node->is_fake = FALSE;
 
-		file = iter->data;
-		node = brasero_data_project_add_imported_session_file (BRASERO_DATA_PROJECT (self),
-								       file,
-								       NULL);
-		if (!node)
-			continue;
-
-		if (!node->is_file)
-			brasero_data_session_add_children_files (self,
-								 node,
-								 file->specific.dir.children);
+	return TRUE;
+}
 
-		priv->nodes = g_slist_prepend (priv->nodes, node);
-	}
+gboolean
+brasero_data_session_load_directory_contents (BraseroDataSession *self,
+					      BraseroFileNode *node,
+					      GError **error)
+{
+	return brasero_data_session_load_directory_contents_real (self, node, error);
+}
+
+gboolean
+brasero_data_session_add_last (BraseroDataSession *self,
+			       BraseroMedium *medium,
+			       GError **error)
+{
+	BraseroDataSessionPrivate *priv;
 
+	priv = BRASERO_DATA_SESSION_PRIVATE (self);
 	priv->loaded = medium;
 	g_object_ref (medium);
 
-	brasero_volume_file_free (volume);
-
-	g_signal_emit (self,
-		       brasero_data_session_signals [LOADED_SIGNAL],
-		       0,
-		       priv->loaded,
-		       TRUE);
-
-	/* check the size of the selection to see if it fits the current 
-	 * selected disc and listen for signal "size-changed" */
-	priv->is_oversized = FALSE;
-	priv->is_overburn = FALSE;
-	brasero_data_session_check_size (self);
-
 	priv->size_changed_sig = g_signal_connect (self,
 						   "size-changed",
 						   G_CALLBACK (brasero_data_session_size_changed),
 						   NULL);
-	return TRUE;
+
+	return brasero_data_session_load_directory_contents_real (self, NULL, error);
 }
 
 gboolean
@@ -487,6 +492,32 @@
 }
 
 static void
+brasero_data_session_stop_io (BraseroDataSession *self)
+{
+	BraseroDataSessionPrivate *priv;
+
+	priv = BRASERO_DATA_SESSION_PRIVATE (self);
+
+	if (priv->io) {
+		brasero_io_cancel_by_base (priv->io, priv->load_dir);
+
+		g_free (priv->load_dir);
+		priv->load_dir = NULL;
+	}
+}
+
+static void
+brasero_data_session_reset (BraseroDataProject *project,
+			    guint num_nodes)
+{
+	brasero_data_session_stop_io (BRASERO_DATA_SESSION (project));
+
+	/* chain up this function except if we invalidated the node */
+	if (BRASERO_DATA_PROJECT_CLASS (brasero_data_session_parent_class)->reset)
+		BRASERO_DATA_PROJECT_CLASS (brasero_data_session_parent_class)->reset (project, num_nodes);
+}
+
+static void
 brasero_data_session_finalize (GObject *object)
 {
 	BraseroDataSessionPrivate *priv;
@@ -511,6 +542,8 @@
 	/* NOTE no need to clean up size_changed_sig since it's connected to 
 	 * ourselves. It disappears with use. */
 
+	brasero_data_session_stop_io (BRASERO_DATA_SESSION (object));
+
 	/* don't care about the nodes since they will be automatically
 	 * destroyed */
 
@@ -522,11 +555,14 @@
 brasero_data_session_class_init (BraseroDataSessionClass *klass)
 {
 	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+	BraseroDataProjectClass *project_class = BRASERO_DATA_PROJECT_CLASS (klass);
 
 	g_type_class_add_private (klass, sizeof (BraseroDataSessionPrivate));
 
 	object_class->finalize = brasero_data_session_finalize;
 
+	project_class->reset = brasero_data_session_reset;
+
 	brasero_data_session_signals [AVAILABLE_SIGNAL] = 
 	    g_signal_new ("session_available",
 			  G_TYPE_FROM_CLASS (klass),

Modified: trunk/src/brasero-data-session.h
==============================================================================
--- trunk/src/brasero-data-session.h	(original)
+++ trunk/src/brasero-data-session.h	Sun Sep 28 18:48:39 2008
@@ -62,6 +62,11 @@
 BraseroMedium *
 brasero_data_session_get_loaded_medium (BraseroDataSession *session);
 
+gboolean
+brasero_data_session_load_directory_contents (BraseroDataSession *session,
+					      BraseroFileNode *node,
+					      GError **error);
+
 GSList *
 brasero_data_session_get_available_media (BraseroDataSession *session);
 

Modified: trunk/src/brasero-data-tree-model.c
==============================================================================
--- trunk/src/brasero-data-tree-model.c	(original)
+++ trunk/src/brasero-data-tree-model.c	Sun Sep 28 18:48:39 2008
@@ -344,8 +344,14 @@
 
 	node->is_visible ++;
 
-	if (node->is_imported)
+	if (node->is_imported) {
+		if (node->is_fake && !node->is_file) {
+			/* we don't load all nodes when importing a session do it now */
+			brasero_data_session_load_directory_contents (BRASERO_DATA_SESSION (model), node, NULL);
+		}
+
 		return;
+	}
 
 	if (node->is_visible > 1)
 		return;

Modified: trunk/src/brasero-dest-selection.c
==============================================================================
--- trunk/src/brasero-dest-selection.c	(original)
+++ trunk/src/brasero-dest-selection.c	Sun Sep 28 18:48:39 2008
@@ -207,6 +207,11 @@
 		priv->session = NULL;
 	}
 
+	if (priv->locked_drive) {
+		brasero_drive_unlock (priv->locked_drive);
+		g_object_unref (priv->locked_drive);
+	}
+
 	G_OBJECT_CLASS (brasero_dest_selection_parent_class)->finalize (object);
 }
 

Modified: trunk/src/brasero-file-node.c
==============================================================================
--- trunk/src/brasero-file-node.c	(original)
+++ trunk/src/brasero-file-node.c	Sun Sep 28 18:48:39 2008
@@ -34,6 +34,7 @@
 
 #include "brasero-file-node.h"
 #include "brasero-utils.h"
+#include "brasero-io.h"
 
 BraseroFileNode *
 brasero_file_node_root_new (void)
@@ -838,7 +839,7 @@
 }
 
 BraseroFileNode *
-brasero_file_node_new_imported_session_file (BraseroVolFile *file,
+brasero_file_node_new_imported_session_file (GFileInfo *info,
 					     BraseroFileNode *parent,
 					     GCompareFunc sort_func)
 {
@@ -846,12 +847,16 @@
 
 	/* Create the node information */
 	node = g_new0 (BraseroFileNode, 1);
-	node->union1.name = g_strdup (BRASERO_VOLUME_FILE_NAME (file));
-	node->is_file = (file->isdir == FALSE);
+	node->union1.name = g_strdup (g_file_info_get_name (info));
+	node->is_file = (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY);
 	node->is_imported = TRUE;
 
-	if (node->is_file)
-		node->union3.sectors = BRASERO_SIZE_TO_SECTORS (BRASERO_VOLUME_FILE_SIZE (file), 2048);
+	if (!node->is_file) {
+		node->is_fake = TRUE;
+		node->union3.imported_address = g_file_info_get_attribute_int64 (info, BRASERO_IO_DIR_CONTENTS_ADDR);
+	}
+	else
+		node->union3.sectors = BRASERO_SIZE_TO_SECTORS (g_file_info_get_size (info), 2048);
 
 	/* Add it (we must add a graft) */
 	brasero_file_node_add (parent, node, sort_func);

Modified: trunk/src/brasero-file-node.h
==============================================================================
--- trunk/src/brasero-file-node.h	(original)
+++ trunk/src/brasero-file-node.h	Sun Sep 28 18:48:39 2008
@@ -108,6 +108,9 @@
 	 * discs. */
 	union {
 		guint sectors;
+
+		/* stores the address of the children records in image */
+		guint imported_address;
 		BraseroFileTreeStats *stats;
 	} union3;
 
@@ -169,6 +172,9 @@
 #define BRASERO_FILE_NODE_STATS(MACRO_root)					\
 	((MACRO_root)->is_root?(MACRO_root)->union3.stats:NULL)
 
+#define BRASERO_FILE_NODE_IMPORTED_ADDRESS(MACRO_node)				\
+	((MACRO_node) && (MACRO_node)->is_imported && (MACRO_node)->is_fake?(MACRO_node)->union3.imported_address:-1)
+
 #define BRASERO_FILE_2G_LIMIT		1048576
 
 BraseroFileNode *
@@ -229,7 +235,7 @@
 				    BraseroFileNode *parent,
 				    GCompareFunc sort_func);
 BraseroFileNode *
-brasero_file_node_new_imported_session_file (BraseroVolFile *file,
+brasero_file_node_new_imported_session_file (GFileInfo *info,
 					     BraseroFileNode *parent,
 					     GCompareFunc sort_func);
 

Modified: trunk/src/brasero-io.c
==============================================================================
--- trunk/src/brasero-io.c	(original)
+++ trunk/src/brasero-io.c	Sun Sep 28 18:48:39 2008
@@ -40,8 +40,9 @@
 
 #include "burn-basics.h"
 #include "burn-debug.h"
-#include "brasero-utils.h"
+#include "burn-volume.h"
 
+#include "brasero-utils.h"
 #include "brasero-io.h"
 #include "brasero-metadata.h"
 #include "brasero-async-task-manager.h"
@@ -1857,6 +1858,129 @@
 }
 
 /**
+ * to evaluate the contents of a medium or image async
+ */
+struct _BraseroIOImageContentsData {
+	BraseroIOJob job;
+	gchar *dev_image;
+
+	gint64 session_block;
+	gint64 block;
+};
+typedef struct _BraseroIOImageContentsData BraseroIOImageContentsData;
+
+static void
+brasero_io_image_directory_contents_destroy (BraseroAsyncTaskManager *manager,
+					     gboolean cancelled,
+					     gpointer callback_data)
+{
+	BraseroIOImageContentsData *data = callback_data;
+
+	g_free (data->dev_image);
+	brasero_io_job_free (BRASERO_IO (manager), cancelled, BRASERO_IO_JOB (data));
+}
+
+static BraseroAsyncTaskResult
+brasero_io_image_directory_contents_thread (BraseroAsyncTaskManager *manager,
+					    GCancellable *cancel,
+					    gpointer callback_data)
+{
+	BraseroIOImageContentsData *data = callback_data;
+	BraseroDeviceHandle *handle;
+	GList *children, *iter;
+	GError *error = NULL;
+	BraseroVolSrc *vol;
+
+	handle = brasero_device_handle_open (data->job.uri, NULL);
+	vol = brasero_volume_source_open_device_handle (handle, &error);
+	if (!vol) {
+		brasero_device_handle_close (handle);
+		brasero_io_return_result (BRASERO_IO (manager),
+					  data->job.base,
+					  data->job.uri,
+					  NULL,
+					  error,
+					  data->job.callback_data);
+		return BRASERO_ASYNC_TASK_FINISHED;
+	}
+
+	children = brasero_volume_load_directory_contents (vol,
+							   data->session_block,
+							   data->block,
+							   &error);
+	brasero_volume_source_close (vol);
+	brasero_device_handle_close (handle);
+
+	for (iter = children; iter; iter = iter->next) {
+		BraseroVolFile *file;
+		GFileInfo *info;
+
+		file = iter->data;
+
+		info = g_file_info_new ();
+		g_file_info_set_file_type (info, file->isdir? G_FILE_TYPE_DIRECTORY:G_FILE_TYPE_REGULAR);
+		g_file_info_set_name (info, BRASERO_VOLUME_FILE_NAME (file));
+
+		if (file->isdir)
+			g_file_info_set_attribute_int64 (info,
+							 BRASERO_IO_DIR_CONTENTS_ADDR,
+							 file->specific.dir.address);
+		else
+			g_file_info_set_size (info, BRASERO_VOLUME_FILE_SIZE (file));
+
+		brasero_io_return_result (BRASERO_IO (manager),
+					  data->job.base,
+					  data->job.uri,
+					  info,
+					  NULL,
+					  data->job.callback_data);
+	}
+
+	g_list_foreach (children, (GFunc) brasero_volume_file_free, NULL);
+	g_list_free (children);
+
+	return BRASERO_ASYNC_TASK_FINISHED;
+}
+
+static const BraseroAsyncTaskType image_contents_type = {
+	brasero_io_image_directory_contents_thread,
+	brasero_io_image_directory_contents_destroy
+};
+
+void
+brasero_io_load_image_directory (BraseroIO *self,
+				 const gchar *dev_image,
+				 gint64 session_block,
+				 gint64 block,
+				 const BraseroIOJobBase *base,
+				 BraseroIOFlags options,
+				 gpointer user_data)
+{
+	BraseroIOImageContentsData *data;
+	BraseroIOResultCallbackData *callback_data = NULL;
+
+	if (user_data) {
+		callback_data = g_new0 (BraseroIOResultCallbackData, 1);
+		callback_data->callback_data = user_data;
+	}
+
+	data = g_new0 (BraseroIOImageContentsData, 1);
+	data->block = block;
+	data->session_block = session_block;
+
+	brasero_io_set_job (BRASERO_IO_JOB (data),
+			    base,
+			    dev_image,
+			    options,
+			    callback_data);
+
+	brasero_io_push_job (self,
+			     BRASERO_IO_JOB (data),
+			     &image_contents_type);
+
+}
+					 
+/**
  * That's for file transfer
  */
 

Modified: trunk/src/brasero-io.h
==============================================================================
--- trunk/src/brasero-io.h	(original)
+++ trunk/src/brasero-io.h	Sun Sep 28 18:48:39 2008
@@ -95,6 +95,8 @@
 #define BRASERO_IO_HAS_VIDEO		"metadata::has_video"
 #define BRASERO_IO_IS_SEEKABLE		"metadata::is_seekable"
 
+#define BRASERO_IO_DIR_CONTENTS_ADDR	"image::directory::address"
+
 typedef struct _BraseroIOJobProgress BraseroIOJobProgress;
 
 typedef void		(*BraseroIOResultCallback)	(GObject *object,
@@ -147,6 +149,15 @@
 			gpointer callback_data);			
 
 void
+brasero_io_load_image_directory (BraseroIO *self,
+				 const gchar *dev_image,
+				 gint64 session_block,
+				 gint64 block,
+				 const BraseroIOJobBase *base,
+				 BraseroIOFlags options,
+				 gpointer user_data);
+
+void
 brasero_io_load_directory (BraseroIO *self,
 			   const gchar *uri,
 			   const BraseroIOJobBase *base,

Modified: trunk/src/brasero-tool-dialog.c
==============================================================================
--- trunk/src/brasero-tool-dialog.c	(original)
+++ trunk/src/brasero-tool-dialog.c	Sun Sep 28 18:48:39 2008
@@ -487,7 +487,6 @@
 	gchar *title_str;
 
 	obj->priv = g_new0 (BraseroToolDialogPrivate, 1);
-	gtk_window_set_default_size (GTK_WINDOW (obj), 500, 300);
 	gtk_dialog_set_has_separator (GTK_DIALOG (obj), FALSE);
 
 	/* upper part */
@@ -570,4 +569,6 @@
 			  "changed",
 			  G_CALLBACK (brasero_tool_dialog_drive_changed_cb),
 			  obj);
+
+	gtk_window_resize (GTK_WINDOW (obj), 10, 10);
 }

Modified: trunk/src/burn-iso9660.c
==============================================================================
--- trunk/src/burn-iso9660.c	(original)
+++ trunk/src/burn-iso9660.c	Sun Sep 28 18:48:39 2008
@@ -126,8 +126,11 @@
 
 #define ISO9660_BYTES_TO_BLOCKS(size)			BRASERO_SIZE_TO_SECTORS ((size), ISO9660_BLOCK_SIZE)
 
-static BraseroVolFile *
-brasero_iso9660_read_directory_records (BraseroIsoCtx *ctx, gint address);
+static GList *
+brasero_iso9660_load_directory_records (BraseroIsoCtx *ctx,
+					BraseroVolFile *parent,
+					BraseroIsoDirRec *record,
+					gboolean recursive);
 
 static BraseroVolFile *
 brasero_iso9660_lookup_directory_records (BraseroIsoCtx *ctx,
@@ -394,6 +397,27 @@
 	return BRASERO_ISO_ERROR;
 }
 
+static BraseroIsoResult
+brasero_iso9660_get_first_directory_record (BraseroIsoCtx *ctx,
+					    BraseroIsoDirRec **record,
+					    gint address)
+{
+	BraseroIsoResult result;
+
+	BRASERO_BURN_LOG ("Reading directory record");
+
+	result = brasero_iso9660_seek (ctx, address);
+	if (result != BRASERO_ISO_OK)
+		return BRASERO_ISO_ERROR;
+
+	/* load "." */
+	result = brasero_iso9660_next_record (ctx, record);
+	if (result != BRASERO_ISO_OK)
+		return BRASERO_ISO_ERROR;
+
+	return BRASERO_ISO_OK;
+}
+
 static BraseroVolFile *
 brasero_iso9660_read_file_record (BraseroIsoCtx *ctx,
 				  BraseroIsoDirRec *record,
@@ -441,7 +465,8 @@
 
 static BraseroVolFile *
 brasero_iso9660_read_directory_record (BraseroIsoCtx *ctx,
-				       BraseroIsoDirRec *record)
+				       BraseroIsoDirRec *record,
+				       gboolean recursive)
 {
 	gchar *susp;
 	gint address;
@@ -456,6 +481,13 @@
 		return NULL;
 	}
 
+	/* create the directory and set information */
+	directory = g_new0 (BraseroVolFile, 1);
+	directory->isdir = TRUE;
+	directory->isdir_loaded = FALSE;
+	directory->name = g_new0 (gchar, record->id_size + 1);
+	memcpy (directory->name, record->id, record->id_size);
+
 	if (ctx->has_susp && ctx->has_RR) {
 		/* See if we've got a susp area. Do it now to see if it has a CL
 		 * entry. The rest will be checked later after reading contents.
@@ -463,6 +495,7 @@
 		susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
 		if (!brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len)) {
 			BRASERO_BURN_LOG ("Could not read susp area");
+			brasero_volume_file_free (directory);
 			return NULL;
 		}
 
@@ -473,90 +506,70 @@
 		}
 		else
 			address = brasero_iso9660_get_733_val (record->address);
-	}
-	else
-		address = brasero_iso9660_get_733_val (record->address);
 
-	directory = brasero_iso9660_read_directory_records (ctx, address);
-	if (!directory) {
-		if (ctx->has_susp && ctx->has_RR)
-			brasero_susp_ctx_clean (&susp_ctx);
+		BRASERO_BURN_LOG ("New directory %s with susp area", directory->name);
 
-		return NULL;
-	}
+		/* if this directory has a "RE" susp entry then drop it; it's 
+		 * not at the right place in the Rock Ridge file hierarchy. It
+		 * will probably be skipped */
+		if (susp_ctx.has_RE) {
+			BRASERO_BURN_LOG ("Rock Ridge relocated directory. Skipping entry.");
+			directory->relocated = TRUE;
+		}
 
-	directory->name = g_new0 (gchar, record->id_size + 1);
-	memcpy (directory->name, record->id, record->id_size);
+		if (susp_ctx.rr_name) {
+			BRASERO_BURN_LOG ("Got a susp (RR) %s", susp_ctx.rr_name);
+			directory->rr_name = susp_ctx.rr_name;
+			susp_ctx.rr_name = NULL;
+		}
 
-	if (!ctx->has_susp || !ctx->has_RR) {
-		BRASERO_BURN_LOG ("New directory %s", directory->name);
-		return directory;
+		brasero_susp_ctx_clean (&susp_ctx);
 	}
+	else
+		address = brasero_iso9660_get_733_val (record->address);
 
-	BRASERO_BURN_LOG ("New directory %s with susp area", directory->name);
+	/* load contents if recursive */
+	if (recursive) {
+		GList *children;
+
+		brasero_iso9660_get_first_directory_record (ctx,
+							    &record,
+							    address);
+		children = brasero_iso9660_load_directory_records (ctx,
+								   directory,
+								   record,
+								   TRUE);
+		if (!children && ctx->error) {
+			brasero_volume_file_free (directory);
+			if (ctx->has_susp && ctx->has_RR)
+				brasero_susp_ctx_clean (&susp_ctx);
 
-	/* if this directory has a "RE" susp entry then drop it; it's not at the
-	 * right place in the Rock Ridge file hierarchy. */
-	if (susp_ctx.has_RE) {
-		BRASERO_BURN_LOG ("Rock Ridge relocated directory. Skipping entry.");
-		directory->relocated = TRUE;
-	}
+			return NULL;
+		}
 
-	if (susp_ctx.rr_name) {
-		BRASERO_BURN_LOG ("Got a susp (RR) %s", susp_ctx.rr_name);
-		directory->rr_name = susp_ctx.rr_name;
-		susp_ctx.rr_name = NULL;
+		directory->isdir_loaded = TRUE;
+		directory->specific.dir.children = children;
 	}
+	else	/* store the address of contents for later use */
+		directory->specific.dir.address = address;
 
-	brasero_susp_ctx_clean (&susp_ctx);
+	BRASERO_BURN_LOG ("New directory %s", directory->name);
 	return directory;
 }
 
-static BraseroVolFile *
-brasero_iso9660_read_directory_records (BraseroIsoCtx *ctx, gint address)
+static GList *
+brasero_iso9660_load_directory_records (BraseroIsoCtx *ctx,
+					BraseroVolFile *parent,
+					BraseroIsoDirRec *record,
+					gboolean recursive)
 {
 	GSList *iter;
 	gint max_block;
 	gint max_record_size;
 	BraseroVolFile *entry;
+	GList *children = NULL;
 	BraseroIsoResult result;
-	BraseroIsoDirRec *record;
 	GSList *directories = NULL;
-	BraseroVolFile *parent = NULL;
-
-	BRASERO_BURN_LOG ("Reading directory record");
-
-	result = brasero_iso9660_seek (ctx, address);
-	if (result != BRASERO_ISO_OK)
-		return NULL;
-
-	/* "." */
-	result = brasero_iso9660_next_record (ctx, &record);
-	if (result != BRASERO_ISO_OK)
-		return NULL;
-
-	/* look for "SP" SUSP if it's root directory */
-	if (ctx->is_root) {
-		BraseroSuspCtx susp_ctx;
-		guint susp_len = 0;
-		gchar *susp;
-
-		susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
-		brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len);
-
-		ctx->has_susp = susp_ctx.has_SP;
-		ctx->has_RR = susp_ctx.has_RockRidge;
-		ctx->susp_skip = susp_ctx.skip;
-		ctx->is_root = FALSE;
-
-		if (ctx->has_susp)
-			BRASERO_BURN_LOG ("File system supports system use sharing protocol");
-
-		if (ctx->has_RR)
-			BRASERO_BURN_LOG ("File system has Rock Ridge extension");
-
-		brasero_susp_ctx_clean (&susp_ctx);
-	}
 
 	max_record_size = brasero_iso9660_get_733_val (record->file_size);
 	max_block = ISO9660_BYTES_TO_BLOCKS (max_record_size);
@@ -568,8 +581,6 @@
 		return NULL;
 
 	BRASERO_BURN_LOG ("Skipped '.' and '..'");
-	parent = g_new0 (BraseroVolFile, 1);
-	parent->isdir = 1;
 
 	while (1) {
 		BraseroIsoResult result;
@@ -647,10 +658,10 @@
 		/* check that we don't have another file record for the
 		 * same file (usually files > 4G). It always follows
 		 * its sibling */
-		if (parent->specific.dir.children) {
+		if (children) {
 			BraseroVolFile *last;
 
-			last = parent->specific.dir.children->data;
+			last = children->data;
 			if (!last->isdir && !strcmp (BRASERO_VOLUME_FILE_NAME (last), BRASERO_VOLUME_FILE_NAME (entry))) {
 				/* add size and addresses */
 				ctx->data_blocks += ISO9660_BYTES_TO_BLOCKS (entry->specific.file.size_bytes);
@@ -660,7 +671,7 @@
 			}
 		}
 
-		parent->specific.dir.children = g_list_prepend (parent->specific.dir.children, entry);
+		children = g_list_prepend (children, entry);
 		ctx->data_blocks += ISO9660_BYTES_TO_BLOCKS (entry->specific.file.size_bytes);
 	}
 
@@ -669,7 +680,7 @@
 	for (iter = directories; iter; iter = iter->next) {
 		record = iter->data;
 
-		entry = brasero_iso9660_read_directory_record (ctx, record);
+		entry = brasero_iso9660_read_directory_record (ctx, record, recursive);
 		if (!entry)
 			goto error;
 
@@ -679,22 +690,50 @@
 		}
 
 		entry->parent = parent;
-		parent->specific.dir.children = g_list_prepend (parent->specific.dir.children, entry);
+		children = g_list_prepend (children, entry);
 	}
 	g_slist_foreach (directories, (GFunc) g_free, NULL);
 	g_slist_free (directories);
 
-	return parent;
+	return children;
 
 error:
 
+	g_list_foreach (children, (GFunc) brasero_volume_file_free, NULL);
+	g_list_free (children);
+
 	g_slist_foreach (directories, (GFunc) g_free, NULL);
 	g_slist_free (directories);
 
-	brasero_volume_file_free (parent);
 	return NULL;
 }
 
+static gboolean
+brasero_iso9660_check_SUSP_RR_use (BraseroIsoCtx *ctx,
+				   BraseroIsoDirRec *record)
+{
+	BraseroSuspCtx susp_ctx;
+	guint susp_len = 0;
+	gchar *susp;
+
+	susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
+	brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len);
+
+	ctx->has_susp = susp_ctx.has_SP;
+	ctx->has_RR = susp_ctx.has_RockRidge;
+	ctx->susp_skip = susp_ctx.skip;
+	ctx->is_root = FALSE;
+
+	if (ctx->has_susp)
+		BRASERO_BURN_LOG ("File system supports system use sharing protocol");
+
+	if (ctx->has_RR)
+		BRASERO_BURN_LOG ("File system has Rock Ridge extension");
+
+	brasero_susp_ctx_clean (&susp_ctx);
+	return TRUE;
+}
+
 static void
 brasero_iso9660_ctx_init (BraseroIsoCtx *ctx, BraseroVolSrc *vol)
 {
@@ -703,6 +742,8 @@
 	ctx->is_root = TRUE;
 	ctx->vol = vol;
 	ctx->offset = 0;
+
+	/* to fully initialize the context we need the root directory record */
 }
 
 BraseroVolFile *
@@ -712,20 +753,32 @@
 			      GError **error)
 {
 	BraseroIsoPrimary *primary;
+	BraseroIsoDirRec *record;
 	BraseroVolFile *volfile;
 	BraseroIsoDirRec *root;
 	BraseroIsoCtx ctx;
+	GList *children;
 	gint address;
 
 	primary = (BraseroIsoPrimary *) block;
 	root = primary->root_rec;
 
-	brasero_iso9660_ctx_init (&ctx, vol);
-
+	/* check settings */
 	address = brasero_iso9660_get_733_val (root->address);
+	brasero_iso9660_ctx_init (&ctx, vol);
+	brasero_iso9660_get_first_directory_record (&ctx, &record, address);
+	brasero_iso9660_check_SUSP_RR_use (&ctx, record);
 
-	BRASERO_BURN_LOG ("Reading root directory record at %i", address);
-	volfile = brasero_iso9660_read_directory_records (&ctx, address);
+	/* create volume file */
+	volfile = g_new0 (BraseroVolFile, 1);
+	volfile->isdir = TRUE;
+	volfile->isdir_loaded = FALSE;
+
+	children = brasero_iso9660_load_directory_records (&ctx,
+							   volfile,
+							   record,
+							   TRUE);
+	volfile->specific.dir.children = children;
 
 	if (ctx.spare_record)
 		g_free (ctx.spare_record);
@@ -733,8 +786,13 @@
 	if (data_blocks)
 		*data_blocks = ctx.data_blocks;
 
-	if (error && ctx.error)
-		g_propagate_error (error, ctx.error);
+	if (!children && ctx.error) {
+		if (error)
+			g_propagate_error (error, ctx.error);
+
+		brasero_volume_file_free (volfile);
+		volfile = NULL;
+	}
 
 	return volfile;
 }
@@ -835,8 +893,8 @@
 
 static BraseroVolFile *
 brasero_iso9660_lookup_directory_records (BraseroIsoCtx *ctx,
-					 const gchar *path,
-					 gint address)
+					  const gchar *path,
+					  gint address)
 {
 	guint len;
 	gchar *end;
@@ -970,13 +1028,15 @@
 
 	primary = (BraseroIsoPrimary *) block;
 	root = primary->root_rec;
-	address = brasero_iso9660_get_733_val (root->address);
 
+	address = brasero_iso9660_get_733_val (root->address);
 	brasero_iso9660_ctx_init (&ctx, vol);
 
 	/* now that we have root block address, skip first "/" and go. */
 	path ++;
-	entry = brasero_iso9660_lookup_directory_records (&ctx, path, address);
+	entry = brasero_iso9660_lookup_directory_records (&ctx,
+							  path,
+							  address);
 
 	/* clean context */
 	if (ctx.spare_record)
@@ -987,3 +1047,42 @@
 
 	return entry;
 }
+
+GList *
+brasero_iso9660_get_directory_contents (BraseroVolSrc *vol,
+					const gchar *vol_desc,
+					gint address,
+					GError **error)
+{
+	BraseroIsoDirRec *record = NULL;
+	BraseroIsoPrimary *primary;
+	BraseroIsoDirRec *root;
+	BraseroIsoCtx ctx;
+	GList *children;
+
+	/* Check root "." for use of RR and things like that */
+	primary = (BraseroIsoPrimary *) vol_desc;
+	root = primary->root_rec;
+
+	brasero_iso9660_ctx_init (&ctx, vol);
+	brasero_iso9660_get_first_directory_record (&ctx,
+						    &record,
+						    brasero_iso9660_get_733_val (root->address));
+	brasero_iso9660_check_SUSP_RR_use (&ctx, record);
+
+	/* Seek up to the contents of the directory */
+	if (address > 0)
+		brasero_iso9660_get_first_directory_record (&ctx,
+							    &record,
+							    address);
+
+	/* load */
+	children = brasero_iso9660_load_directory_records (&ctx,
+							   NULL,
+							   record,
+							   FALSE);
+	if (ctx.error && error)
+		g_propagate_error (error, ctx.error);
+
+	return children;
+}

Modified: trunk/src/burn-iso9660.h
==============================================================================
--- trunk/src/burn-iso9660.h	(original)
+++ trunk/src/burn-iso9660.h	Sun Sep 28 18:48:39 2008
@@ -40,6 +40,11 @@
 
 #define ISO9660_BLOCK_SIZE 2048
 
+typedef enum {
+	BRASERO_ISO_FLAG_NONE	= 0,
+	BRASERO_ISO_FLAG_RR	= 1
+} BraseroIsoFlag;
+
 gboolean
 brasero_iso9660_is_primary_descriptor (const gchar *buffer,
 				       GError **error);
@@ -60,6 +65,15 @@
 			      gint64 *nb_blocks,
 			      GError **error);
 
+/**
+ * Address to -1 for root
+ */
+GList *
+brasero_iso9660_get_directory_contents (BraseroVolSrc *vol,
+					const gchar *vol_desc,
+					gint address,
+					GError **error);
+
 BraseroVolFile *
 brasero_iso9660_get_file (BraseroVolSrc *src,
 			  const gchar *path,

Modified: trunk/src/burn-volume.c
==============================================================================
--- trunk/src/burn-volume.c	(original)
+++ trunk/src/burn-volume.c	Sun Sep 28 18:48:39 2008
@@ -75,10 +75,12 @@
 	if (file->isdir) {
 		GList *iter;
 
-		for (iter = file->specific.dir.children; iter; iter = iter->next)
-			brasero_volume_file_free (iter->data);
+		if (file->isdir_loaded) {
+			for (iter = file->specific.dir.children; iter; iter = iter->next)
+				brasero_volume_file_free (iter->data);
 
-		g_list_free (file->specific.dir.children);
+			g_list_free (file->specific.dir.children);
+		}
 	}
 	else {
 		g_slist_foreach (file->specific.file.extents,
@@ -175,7 +177,33 @@
 	&& !brasero_iso9660_get_size (buffer, nb_blocks, error))
 		return NULL;
 
-	return brasero_iso9660_get_contents (vol, buffer, data_blocks, error);
+	return brasero_iso9660_get_contents (vol,
+					     buffer,
+					     data_blocks,
+					     error);
+}
+
+GList *
+brasero_volume_load_directory_contents (BraseroVolSrc *vol,
+					gint64 session_block,
+					gint64 block,
+					GError **error)
+{
+	gchar buffer [ISO9660_BLOCK_SIZE];
+
+	if (BRASERO_VOL_SRC_SEEK (vol, session_block, SEEK_SET, error) == -1)
+		return FALSE;
+
+	if (!brasero_volume_get_primary_from_file (vol, buffer, error))
+		return NULL;
+
+	if (!brasero_iso9660_is_primary_descriptor (buffer, error))
+		return NULL;
+
+	return brasero_iso9660_get_directory_contents (vol,
+						       buffer,
+						       block,
+						       error);
 }
 
 BraseroVolFile *

Modified: trunk/src/burn-volume.h
==============================================================================
--- trunk/src/burn-volume.h	(original)
+++ trunk/src/burn-volume.h	Sun Sep 28 18:48:39 2008
@@ -62,13 +62,16 @@
 
 	struct {
 		GList *children;
+		guint address;
 	} dir;
 
 	} specific;
 
 	guint isdir:1;
+	guint isdir_loaded:1;
 
 	/* mainly used internally */
+	guint has_RR:1;
 	guint relocated:1;
 };
 
@@ -96,6 +99,12 @@
 			 gint64 volume_start_block,
 			 GError **error);
 
+GList *
+brasero_volume_load_directory_contents (BraseroVolSrc *vol,
+					gint64 session_block,
+					gint64 block,
+					GError **error);
+
 
 #define BRASERO_VOLUME_FILE_NAME(file)			((file)->rr_name?(file)->rr_name:(file)->name)
 #define BRASERO_VOLUME_FILE_SIZE(file)			((file)->isdir?0:(file)->specific.file.size_bytes)



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