brasero r2209 - in trunk: . libbrasero-burn libbrasero-burn/plugins/cdrdao libbrasero-burn/plugins/transcode libbrasero-media po src



Author: philippr
Date: Sun Apr  5 08:45:48 2009
New Revision: 2209
URL: http://svn.gnome.org/viewvc/brasero?rev=2209&view=rev

Log:
2009-04-05  Philippe Rouquier  <bonfire-app wanadoo fr>

	Split burn-caps.c file in three smaller parts

	* libbrasero-burn/Makefile.am:
	* libbrasero-burn/brasero-burn-lib.h.in:
	* libbrasero-burn/brasero-burn.c:
	* libbrasero-burn/brasero-caps-burn.c
	(brasero_burn_caps_job_error_cb), (brasero_caps_link_find_plugin),
	(brasero_caps_link_list_insert), (brasero_caps_find_best_link),
	(brasero_burn_caps_sort_modifiers),
	(brasero_caps_add_processing_plugins_to_task),
	(brasero_burn_caps_new_task),
	(brasero_burn_caps_new_checksuming_task),
	(brasero_burn_caps_new_blanking_task):
	* libbrasero-burn/brasero-caps-burn.h:
	* libbrasero-burn/brasero-caps-plugin.c
	(brasero_caps_find_link_for_input), (brasero_burn_caps_sort),
	(brasero_caps_link_copy), (brasero_caps_link_list_duplicate),
	(brasero_caps_duplicate), (brasero_caps_replicate_modifiers),
	(brasero_caps_replicate_links), (brasero_caps_replicate_tests),
	(brasero_caps_copy_deep), (brasero_caps_duplicate_deep),
	(brasero_caps_list_check_io), (brasero_caps_image_new),
	(brasero_caps_audio_new), (brasero_caps_data_new),
	(brasero_caps_disc_lookup_or_create), (brasero_caps_disc_new),
	(brasero_caps_create_links), (brasero_plugin_link_caps),
	(brasero_plugin_blank_caps), (brasero_plugin_process_caps),
	(brasero_plugin_check_caps), (brasero_plugin_register_group),
	(brasero_plugin_can_burn), (brasero_plugin_can_image),
	(brasero_plugin_can_convert):
	* libbrasero-burn/brasero-caps-session.c
	(brasero_burn_caps_get_blanking_flags_real),
	(brasero_burn_session_get_blank_flags),
	(brasero_burn_caps_can_blank_real),
	(brasero_burn_session_can_blank),
	(brasero_caps_link_get_record_flags),
	(brasero_caps_link_get_data_flags),
	(brasero_caps_link_check_data_flags),
	(brasero_caps_link_check_record_flags),
	(brasero_caps_link_check_media_restrictions),
	(brasero_caps_find_link), (brasero_caps_try_output),
	(brasero_caps_try_output_with_blanking),
	(brasero_burn_session_input_supported),
	(brasero_burn_session_output_supported),
	(brasero_burn_caps_is_session_supported_same_src_dest),
	(brasero_burn_session_can_burn),
	(brasero_burn_session_get_required_media_type),
	(brasero_burn_session_get_default_output_format),
	(brasero_caps_get_flags), (brasero_medium_supported_flags),
	(brasero_burn_caps_flags_update_for_drive),
	(brasero_caps_get_flags_for_disc),
	(brasero_burn_caps_get_flags_for_medium),
	(brasero_burn_caps_get_flags_same_src_dest),
	(brasero_burn_session_get_burn_flags):
	* libbrasero-burn/brasero-track.c
	(brasero_track_type_is_supported):
	* libbrasero-burn/burn-basics.c (brasero_check_flags_for_drive),
	(brasero_caps_list_dump), (brasero_burn_library_can_checksum),
	(brasero_burn_library_get_media_capabilities):
	* libbrasero-burn/burn-basics.h:
	* libbrasero-burn/burn-caps.c (brasero_caps_link_active),
	(brasero_caps_free), (brasero_caps_has_active_input),
	(brasero_burn_caps_is_input), (brasero_burn_caps_find_start_caps),
	(brasero_burn_caps_finalize), (brasero_burn_caps_class_init),
	(brasero_burn_caps_init), (brasero_burn_caps_get_default):
	* libbrasero-burn/burn-caps.h:
	* libbrasero-burn/burn-debug.c:
	* libbrasero-burn/burn-job.h:
	* libbrasero-burn/burn-process.h:
	* libbrasero-burn/plugins/cdrdao/burn-toc2cue.c:
	* libbrasero-burn/plugins/transcode/burn-normalize.c:
	* libbrasero-burn/plugins/transcode/burn-vob.c:
	* libbrasero-media/brasero-media-private.h:
	* libbrasero-media/brasero-media.c:
	* src/brasero-data-session.c (brasero_data_session_is_valid_multi):

Added:
   trunk/libbrasero-burn/brasero-caps-burn.c
   trunk/libbrasero-burn/brasero-caps-burn.h
   trunk/libbrasero-burn/brasero-caps-plugin.c
   trunk/libbrasero-burn/brasero-caps-session.c
Modified:
   trunk/ChangeLog
   trunk/libbrasero-burn/Makefile.am
   trunk/libbrasero-burn/brasero-burn-lib.h.in
   trunk/libbrasero-burn/brasero-burn.c
   trunk/libbrasero-burn/brasero-track.c
   trunk/libbrasero-burn/burn-basics.c
   trunk/libbrasero-burn/burn-basics.h
   trunk/libbrasero-burn/burn-caps.c
   trunk/libbrasero-burn/burn-caps.h
   trunk/libbrasero-burn/burn-debug.c
   trunk/libbrasero-burn/burn-job.h
   trunk/libbrasero-burn/burn-process.h
   trunk/libbrasero-burn/plugins/cdrdao/burn-toc2cue.c
   trunk/libbrasero-burn/plugins/transcode/burn-normalize.c
   trunk/libbrasero-burn/plugins/transcode/burn-vob.c
   trunk/libbrasero-media/brasero-media-private.h
   trunk/libbrasero-media/brasero-media.c
   trunk/po/ChangeLog
   trunk/po/POTFILES.in
   trunk/src/brasero-data-session.c

Modified: trunk/libbrasero-burn/Makefile.am
==============================================================================
--- trunk/libbrasero-burn/Makefile.am	(original)
+++ trunk/libbrasero-burn/Makefile.am	Sun Apr  5 08:45:48 2009
@@ -147,7 +147,11 @@
 	brasero-track-data.h                 \
 	brasero-track-image-cfg.c                 \
 	brasero-track-image-cfg.h                 \
-	brasero-burn-options-private.h
+	brasero-burn-options-private.h                 \
+	brasero-caps-plugin.c                 \
+	brasero-caps-burn.c                 \
+	brasero-caps-session.c                 \
+	brasero-caps-burn.h
 
 EXTRA_DIST =			\
 	libbrasero-marshal.list

Modified: trunk/libbrasero-burn/brasero-burn-lib.h.in
==============================================================================
--- trunk/libbrasero-burn/brasero-burn-lib.h.in	(original)
+++ trunk/libbrasero-burn/brasero-burn-lib.h.in	Sun Apr  5 08:45:48 2009
@@ -78,6 +78,9 @@
 gboolean
 brasero_burn_library_can_checksum (void);
 
+BraseroMedia
+brasero_burn_library_get_media_capabilities (BraseroMedia media);
+
 G_END_DECLS
 
 #endif /* _BRASERO_BURN_LIB_ */

Modified: trunk/libbrasero-burn/brasero-burn.c
==============================================================================
--- trunk/libbrasero-burn/brasero-burn.c	(original)
+++ trunk/libbrasero-burn/brasero-burn.c	Sun Apr  5 08:45:48 2009
@@ -53,7 +53,7 @@
 #include "burn-dbus.h"
 #include "burn-task-ctx.h"
 #include "burn-task.h"
-#include "burn-caps.h"
+#include "brasero-caps-burn.h"
 
 #include "brasero-volume.h"
 #include "brasero-drive.h"

Added: trunk/libbrasero-burn/brasero-caps-burn.c
==============================================================================
--- (empty file)
+++ trunk/libbrasero-burn/brasero-caps-burn.c	Sun Apr  5 08:45:48 2009
@@ -0,0 +1,1037 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn 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-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn 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-burn 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 <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "brasero-caps-burn.h"
+#include "burn-caps.h"
+#include "burn-debug.h"
+#include "burn-plugin-private.h"
+#include "burn-task.h"
+
+/**
+ * This macro is used to determine whether or not blanking could change anything
+ * for the medium so that we can write to it.
+ */
+#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG(session)				\
+{										\
+	brasero_burn_session_log (session, "Unsupported type of task operation"); \
+	BRASERO_BURN_LOG ("Unsupported type of task operation");		\
+	return NULL;								\
+}
+
+#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR(session, error)		\
+{										\
+	if (error)								\
+		g_set_error (error,						\
+			     BRASERO_BURN_ERROR,				\
+			     BRASERO_BURN_ERROR_GENERAL,			\
+			     _("An internal error occured"));	 		\
+	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session);				\
+}
+
+/* That function receives all errors returned by the object and 'learns' from 
+ * these errors what are the safest defaults for a particular system. It should 
+ * also offer fallbacks if an error occurs through a signal */
+static BraseroBurnResult
+brasero_burn_caps_job_error_cb (BraseroJob *job,
+				BraseroBurnError error,
+				BraseroBurnCaps *caps)
+{
+#if 0
+	GError *error = NULL;
+	GConfClient *client;
+
+	/* This was originally to fix a bug in fedora 5 that prevents from
+	 * sending SCSI commands as a normal user through cdrdao. There is a
+	 * fallback fortunately with cdrecord and raw images but no on_the_fly
+	 * burning.
+	 * That could be used as a hook to know how a job runs and give a
+	 * "penalty" to job types being too often faulty. There could also be
+	 * a dialog to ask the user if he wants to use another backend.
+	 */
+
+	/* set it in GConf to remember that next time */
+	client = gconf_client_get_default ();
+	gconf_client_set_bool (client, GCONF_KEY_CDRDAO_DISABLED, TRUE, &error);
+	if (error) {
+		g_warning ("Can't write with GConf: %s", error->message);
+		g_error_free (error);
+	}
+	g_object_unref (client);
+#endif
+	return BRASERO_BURN_ERR;
+}
+
+static BraseroPlugin *
+brasero_caps_link_find_plugin (BraseroCapsLink *link,
+			       gint group_id,
+			       BraseroBurnFlag session_flags,
+			       BraseroTrackType *output,
+			       BraseroMedia media)
+{
+	GSList *iter;
+	BraseroPlugin *candidate;
+
+	/* Go through all plugins for a link and find the best one. It must:
+	 * - be active
+	 * - be part of the group (as much as possible)
+	 * - have the highest priority
+	 * - support the flags */
+	candidate = NULL;
+	for (iter = link->plugins; iter; iter = iter->next) {
+		BraseroPlugin *plugin;
+
+		plugin = iter->data;
+
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		if (output->type == BRASERO_TRACK_TYPE_DISC) {
+			gboolean result;
+
+			result = brasero_plugin_check_record_flags (plugin,
+								    media,
+								    session_flags);
+			if (!result)
+				continue;
+		}
+
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
+			gboolean result;
+
+			result = brasero_plugin_check_image_flags (plugin,
+								   media,
+								   session_flags);
+			if (!result)
+				continue;
+		}
+		else if (!brasero_plugin_check_media_restrictions (plugin, media))
+			continue;
+
+		if (group_id > 0 && candidate) {
+			/* the candidate must be in the favourite group as much as possible */
+			if (brasero_plugin_get_group (candidate) != group_id) {
+				if (brasero_plugin_get_group (plugin) == group_id) {
+					candidate = plugin;
+					continue;
+				}
+			}
+			else if (brasero_plugin_get_group (plugin) != group_id)
+				continue;
+		}
+
+		if (!candidate)
+			candidate = plugin;
+		else if (brasero_plugin_get_priority (plugin) >
+			 brasero_plugin_get_priority (candidate))
+			candidate = plugin;
+	}
+
+	return candidate;
+}
+
+typedef struct _BraseroCapsLinkList BraseroCapsLinkList;
+struct _BraseroCapsLinkList {
+	BraseroCapsLinkList *next;
+	BraseroCapsLink *link;
+	BraseroPlugin *plugin;
+};
+
+static BraseroCapsLinkList *
+brasero_caps_link_list_insert (BraseroCapsLinkList *list,
+			       BraseroCapsLinkList *node,
+			       gboolean fits)
+{
+	BraseroCapsLinkList *iter;
+
+	if (!list)
+		return node;
+
+	if (brasero_plugin_get_priority (node->plugin) >
+	    brasero_plugin_get_priority (list->plugin)) {
+		node->next = list;
+		return node;
+	}
+
+	if (brasero_plugin_get_priority (node->plugin) ==
+	    brasero_plugin_get_priority (list->plugin)) {
+		if (fits) {
+			node->next = list;
+			return node;
+		}
+
+		node->next = list->next;
+		list->next = node;
+		return list;
+	}
+
+	if (!list->next) {
+		node->next = NULL;
+		list->next = node;
+		return list;
+	}
+
+	/* Need a node with at least the same priority. Stop if end is reached */
+	iter = list;
+	while (iter->next &&
+	       brasero_plugin_get_priority (node->plugin) <
+	       brasero_plugin_get_priority (iter->next->plugin))
+		iter = iter->next;
+
+	if (!iter->next) {
+		/* reached the end of the list, put it at the end */
+		iter->next = node;
+		node->next = NULL;
+	}
+	else if (brasero_plugin_get_priority (node->plugin) <
+		 brasero_plugin_get_priority (iter->next->plugin)) {
+		/* Put it at the end of the list */
+		node->next = NULL;
+		iter->next->next = node;
+	}
+	else if (brasero_plugin_get_priority (node->plugin) >
+		 brasero_plugin_get_priority (iter->next->plugin)) {
+		/* insert it before iter->next */
+		node->next = iter->next;
+		iter->next = node;
+	}
+	else if (fits) {
+		/* insert it before the link with the same priority */
+		node->next = iter->next;
+		iter->next = node;
+	}
+	else {
+		/* insert it after the link with the same priority */
+		node->next = iter->next->next;
+		iter->next->next = node;
+	}
+	return list;
+}
+
+static GSList *
+brasero_caps_find_best_link (BraseroCaps *caps,
+			     gint group_id,
+			     GSList *used_caps,
+			     BraseroBurnFlag session_flags,
+			     BraseroMedia media,
+			     BraseroTrackType *input,
+			     BraseroPluginIOFlag io_flags)
+{
+	GSList *iter;
+	GSList *results = NULL;
+	BraseroCapsLinkList *node = NULL;
+	BraseroCapsLinkList *list = NULL;
+
+	BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_best_link");
+
+	/* First, build a list of possible links and sort them out according to
+	 * the priority based on the highest priority among their plugins. In 
+	 * this case, we can't sort links beforehand since according to the
+	 * flags, input, output in the session the plugins will or will not 
+	 * be used. Moreover given the group_id thing the choice of plugin may
+	 * depends. */
+
+	/* This is done to address possible issues namely:
+	 * - growisofs can handle DATA right from the start but has a lower
+	 * priority than libburn. In this case growisofs would be used every 
+	 * time for DATA despite its having a lower priority than libburn if we
+	 * were looking for the best fit first
+	 * - We don't want to follow the long path and have a useless (in this
+	 * case) image converter plugin get included.
+	 * ex: we would have: CDRDAO (input) toc2cue => (CUE) cdrdao => (DISC)
+	 * instead of simply: CDRDAO (input) cdrdao => (DISC) */
+
+	for (iter = caps->links; iter; iter = iter->next) {
+		BraseroPlugin *plugin;
+		BraseroCapsLink *link;
+		gboolean fits;
+
+		link = iter->data;
+
+		/* skip blanking links */
+		if (!link->caps) {
+			BRASERO_BURN_LOG ("Blanking caps");
+			continue;
+		}
+
+		/* the link should not link to an already used caps */
+		if (g_slist_find (used_caps, link->caps)) {
+			BRASERO_BURN_LOG ("Already used caps");
+			continue;
+		}
+
+		/* see if that's a perfect fit;
+		 * - it must have the same caps (type + subtype)
+		 * - it must have the proper IO (file). */
+		fits = (link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) &&
+			brasero_caps_is_compatible_type (link->caps, input);
+
+		if (!fits) {
+			/* if it doesn't fit it must be at least connectable */
+			if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE) {
+				BRASERO_BURN_LOG ("Not connectable");
+				continue;
+			}
+
+			/* we can't go further than a DISC type, no need to keep it */
+			if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC) {
+				BRASERO_BURN_LOG ("Can't go further than DISC caps");
+				continue;
+			}
+		}
+
+		/* See if this link can be used. For a link to be followed it 
+		 * must:
+		 * - have at least an active plugin
+		 * - have at least a plugin accepting the record flags if caps type (output) 
+		 *   is a disc (that means that the link is the recording part) 
+		 * - have at least a plugin accepting the data flags if caps type (input)
+		 *   is DATA. */
+		plugin = brasero_caps_link_find_plugin (link,
+							group_id,
+							session_flags,
+							&caps->type,
+							media);
+		if (!plugin) {
+			BRASERO_BURN_LOG ("No plugin found");
+			continue;
+		}
+
+		BRASERO_BURN_LOG ("Found candidate link");
+
+		/* A plugin could be found which means that link can be used.
+		 * Insert it in the list at the right place.
+		 * The list is sorted according to priorities (starting with the
+		 * highest). If 2 links have the same priority put first the one
+		 * that has the correct input. */
+		node = g_new0 (BraseroCapsLinkList, 1);
+		node->plugin = plugin;
+		node->link = link;
+
+		list = brasero_caps_link_list_insert (list, node, fits);
+	}
+
+	if (!list) {
+		BRASERO_BURN_LOG ("No links found");
+		return NULL;
+	}
+
+	used_caps = g_slist_prepend (used_caps, caps);
+
+	/* Then, go through this list (starting with highest priority links)
+	 * The rule is we prefer the links with the highest priority; if two
+	 * links have the same priority and one of them leads to a caps
+	 * with the correct type then choose this one. */
+	for (node = list; node; node = node->next) {
+		guint search_group_id;
+
+		/* see if that's a perfect fit; if so, then we're good. 
+		 * - it must have the same caps (type + subtype)
+		 * - it must have the proper IO (file) */
+		if ((node->link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
+		&&   brasero_caps_is_compatible_type (node->link->caps, input)) {
+			results = g_slist_prepend (NULL, node->link);
+			break;
+		}
+
+		/* determine the group_id for the search */
+		if (brasero_plugin_get_group (node->plugin) > 0 && group_id <= 0)
+			search_group_id = brasero_plugin_get_group (node->plugin);
+		else
+			search_group_id = group_id;
+
+		/* It's not a perfect fit. First see if a plugin with the same
+		 * priority don't have the right input. Then see if we can reach
+		 * the right input by going through all previous nodes */
+		results = brasero_caps_find_best_link (node->link->caps,
+						       search_group_id,
+						       used_caps,
+						       session_flags,
+						       media,
+						       input,
+						       io_flags);
+		if (results) {
+			results = g_slist_prepend (results, node->link);
+			break;
+		}
+	}
+
+	/* clear up */
+	used_caps = g_slist_remove (used_caps, caps);
+	for (node = list; node; node = list) {
+		list = node->next;
+		g_free (node);
+	}
+
+	return results;
+}
+
+static gboolean
+brasero_burn_caps_sort_modifiers (gconstpointer a,
+				  gconstpointer b)
+{
+	BraseroPlugin *plug_a = BRASERO_PLUGIN (a);
+	BraseroPlugin *plug_b = BRASERO_PLUGIN (b);
+
+	return brasero_plugin_get_priority (plug_a) -
+	       brasero_plugin_get_priority (plug_b);
+}
+
+static GSList *
+brasero_caps_add_processing_plugins_to_task (BraseroBurnSession *session,
+					     BraseroTask *task,
+					     BraseroCaps *caps,
+					     BraseroTrackType *io_type,
+					     BraseroPluginProcessFlag position)
+{
+	GSList *retval = NULL;
+	GSList *modifiers;
+	GSList *iter;
+
+	if (position == BRASERO_PLUGIN_RUN_NEVER
+	||  caps->type.type == BRASERO_TRACK_TYPE_DISC)
+		return NULL;
+
+	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+				    caps->flags,
+				    "Adding modifiers (position %i) (%i modifiers available) for",
+				    position,
+				    g_slist_length (caps->modifiers));
+
+	/* Go through all plugins and add all possible modifiers. They must:
+	 * - be active
+	 * - accept the position flags */
+	modifiers = g_slist_copy (caps->modifiers);
+	modifiers = g_slist_sort (modifiers, brasero_burn_caps_sort_modifiers);
+
+	for (iter = modifiers; iter; iter = iter->next) {
+		BraseroPluginProcessFlag flags;
+		BraseroPlugin *plugin;
+		BraseroJob *job;
+		GType type;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		brasero_plugin_get_process_flags (plugin, &flags);
+		if ((flags & position) != position)
+			continue;
+
+		type = brasero_plugin_get_gtype (plugin);
+		job = BRASERO_JOB (g_object_new (type,
+						 "output", io_type,
+						 NULL));
+		g_signal_connect (job,
+				  "error",
+				  G_CALLBACK (brasero_burn_caps_job_error_cb),
+				  caps);
+
+		if (!task
+		||  !(caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
+		||  !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
+			/* here the action taken is always to create an image */
+			task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
+							   "session", session,
+							   "action", BRASERO_BURN_ACTION_CREATING_IMAGE,
+							   NULL));
+			retval = g_slist_prepend (retval, task);
+		}
+
+		BRASERO_BURN_LOG ("%s (modifier) added to task",
+				  brasero_plugin_get_name (plugin));
+
+		BRASERO_BURN_LOG_TYPE (io_type, "IO type");
+
+		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
+	}
+	g_slist_free (modifiers);
+
+	return retval;
+}
+
+GSList *
+brasero_burn_caps_new_task (BraseroBurnCaps *self,
+			    BraseroBurnSession *session,
+			    GError **error)
+{
+	BraseroPluginProcessFlag position;
+	BraseroBurnFlag session_flags;
+	BraseroTrackType plugin_input;
+	BraseroTask *blanking = NULL;
+	BraseroPluginIOFlag flags;
+	BraseroTask *task = NULL;
+	BraseroTrackType output;
+	BraseroTrackType input;
+	BraseroCaps *last_caps;
+	GSList *retval = NULL;
+	GSList *iter, *list;
+	BraseroMedia media;
+	gint group_id;
+	gboolean res;
+
+	/* determine the output and the flags for this task */
+	if (brasero_burn_session_is_dest_file (session)) {
+		media = BRASERO_MEDIUM_FILE;
+
+		output.type = BRASERO_TRACK_TYPE_IMAGE;
+		output.subtype.img_format = brasero_burn_session_get_output_format (session);
+	}
+	else {
+		media = brasero_burn_session_get_dest_media (session);
+
+		output.type = BRASERO_TRACK_TYPE_DISC;
+		output.subtype.media = media;
+	}
+
+	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
+		flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+	else
+		flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+
+	BRASERO_BURN_LOG_WITH_TYPE (&output,
+				    flags,
+				    "Creating recording/imaging task");
+
+	/* search the start caps and try to get a list of links */
+	last_caps = brasero_burn_caps_find_start_caps (self, &output);
+	if (!last_caps)
+		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_WITH_TYPE (&input,
+				    BRASERO_PLUGIN_IO_NONE,
+				    "Input set =");
+
+	session_flags = brasero_burn_session_get_flags (session);
+	res = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session), session_flags);
+	if (!res)
+		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session);
+
+	list = brasero_caps_find_best_link (last_caps,
+					    self->priv->group_id,
+					    NULL,
+					    session_flags,
+					    media,
+					    &input,
+					    flags);
+	if (!list) {
+		/* we reached this point in two cases:
+		 * - if the disc cannot be handled
+		 * - if some flags are not handled
+		 * It is helpful only if:
+		 * - the disc was closed and no plugin can handle this type of 
+		 * disc once closed (CD-R(W))
+		 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
+		 * handle this flag (means that the plugin should erase and
+		 * then write on its own. Basically that works only with
+		 * overwrite formatted discs, DVD+RW, ...) */
+		if (output.type != BRASERO_TRACK_TYPE_DISC)
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+
+		/* output is a disc try with initial blanking */
+		BRASERO_BURN_LOG ("failed to create proper task. Trying with initial blanking");
+
+		/* apparently nothing can be done to reach our goal. Maybe that
+		 * is because we first have to blank the disc. If so add a blank 
+		 * task to the others as a first step */
+		if (!(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
+		||    brasero_burn_session_can_blank (session) != BRASERO_BURN_OK)
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+
+		/* retry with the same disc type but blank this time */
+		media &= ~(BRASERO_MEDIUM_CLOSED|
+			   BRASERO_MEDIUM_APPENDABLE|
+	   		   BRASERO_MEDIUM_UNFORMATTED|
+			   BRASERO_MEDIUM_HAS_DATA|
+			   BRASERO_MEDIUM_HAS_AUDIO);
+		media |= BRASERO_MEDIUM_BLANK;
+
+		output.subtype.media = media;
+
+		last_caps = brasero_burn_caps_find_start_caps (self, &output);
+		if (!last_caps)
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+
+		/* if the flag BLANK_BEFORE_WRITE was set then remove it since
+		 * we are actually blanking. Simply the record plugin won't have
+		 * to do it. */
+		session_flags &= ~BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
+		list = brasero_caps_find_best_link (last_caps,
+						    self->priv->group_id,
+						    NULL,
+						    session_flags,
+						    media,
+						    &input,
+						    flags);
+		if (!list)
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+
+		BRASERO_BURN_LOG ("initial blank/erase task required")
+
+		blanking = brasero_burn_caps_new_blanking_task (self, session, error);
+		/* The problem here is that we shouldn't always prepend such a 
+		 * task. For example when we copy a disc to another using the 
+		 * same drive. In this case we should insert it before the last.
+		 * Now, that always work so that's what we do in all cases. Once
+		 * the whole list of tasks is created we insert this blanking
+		 * task just before the last one. Another advantage is that the
+		 * blanking of the disc is delayed as late as we can which means
+		 * in case of error we keep it intact as late as we can. */
+	}
+
+	/* reverse the list of links to have them in the right order */
+	list = g_slist_reverse (list);
+	position = BRASERO_PLUGIN_RUN_PREPROCESSING;
+	group_id = self->priv->group_id;
+
+	brasero_burn_session_get_input_type (session, &plugin_input);
+	for (iter = list; iter; iter = iter->next) {
+		BraseroTrackType plugin_output;
+		BraseroCapsLink *link;
+		BraseroPlugin *plugin;
+		BraseroJob *job;
+		GSList *result;
+		GType type;
+
+		link = iter->data;
+
+		/* determine the plugin output */
+		if (iter->next) {
+			BraseroCapsLink *next_link;
+
+			next_link = iter->next->data;
+			if (next_link == link) {
+				/* That's a processing plugin so the output must
+				 * be the exact same as the input, which is not
+				 * necessarily the caps type referred to by the 
+				 * link if the link is amongst the first. In
+				 * that case that's the session input. */
+				memcpy (&plugin_output,
+					&plugin_input,
+					sizeof (BraseroTrackType));
+			}
+			else {
+				memcpy (&plugin_output,
+					&next_link->caps->type,
+					sizeof (BraseroTrackType));
+			}
+		}
+		else
+			memcpy (&plugin_output,
+				&output,
+				sizeof (BraseroTrackType));
+
+		/* first see if there are track processing plugins */
+		result = brasero_caps_add_processing_plugins_to_task (session,
+								      task,
+								      link->caps,
+								      &plugin_input,
+								      position);
+		retval = g_slist_concat (retval, result);
+
+		/* create job from the best plugin in link */
+		plugin = brasero_caps_link_find_plugin (link,
+							group_id,
+							session_flags,
+							&plugin_output,
+							media);
+		if (!plugin) {
+			g_set_error (error,
+				     BRASERO_BURN_ERROR,
+				     BRASERO_BURN_ERROR_GENERAL,
+				     _("An internal error occured"));
+			g_slist_foreach (retval, (GFunc) g_object_unref, NULL);
+			g_slist_free (retval);
+			g_slist_free (list);
+			return NULL;
+		}
+
+		/* This is meant to have plugins in the same group id as much as
+		 * possible */
+		if (brasero_plugin_get_group (plugin) > 0 && group_id <= 0)
+			group_id = brasero_plugin_get_group (plugin);
+
+		type = brasero_plugin_get_gtype (plugin);
+		job = BRASERO_JOB (g_object_new (type,
+						 "output", &plugin_output,
+						 NULL));
+		g_signal_connect (job,
+				  "error",
+				  G_CALLBACK (brasero_burn_caps_job_error_cb),
+				  link);
+
+		if (!task
+		||  !(link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
+		||  !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
+			/* only the last task will be doing the proper action
+			 * all other are only steps to take to reach the final
+			 * action */
+			BRASERO_BURN_LOG ("New task");
+			task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
+							   "session", session,
+							   "action", BRASERO_TASK_ACTION_NORMAL,
+							   NULL));
+			retval = g_slist_append (retval, task);
+		}
+
+		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
+
+		BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (plugin));
+		BRASERO_BURN_LOG_TYPE (&plugin_input, "input");
+		BRASERO_BURN_LOG_TYPE (&plugin_output, "output");
+
+		position = BRASERO_PLUGIN_RUN_BEFORE_TARGET;
+
+		/* the output of the plugin will become the input of the next */
+		memcpy (&plugin_input, &plugin_output, sizeof (BraseroTrackType));
+	}
+	g_slist_free (list);
+
+	/* add the post processing plugins */
+	list = brasero_caps_add_processing_plugins_to_task (session,
+							    NULL,
+							    last_caps,
+							    &output,
+							    BRASERO_PLUGIN_RUN_AFTER_TARGET);
+	retval = g_slist_concat (retval, list);
+
+	if (last_caps->type.type == BRASERO_TRACK_TYPE_DISC && blanking) {
+		retval = g_slist_insert_before (retval,
+						g_slist_last (retval),
+						blanking);
+	}
+
+	return retval;
+}
+
+BraseroTask *
+brasero_burn_caps_new_checksuming_task (BraseroBurnCaps *self,
+					BraseroBurnSession *session,
+					GError **error)
+{
+	BraseroTrackType track_type;
+	BraseroPlugin *candidate;
+	BraseroCaps *last_caps;
+	BraseroTrackType input;
+	guint checksum_type;
+	BraseroTrack *track;
+	BraseroTask *task;
+	BraseroJob *job;
+	GSList *tracks;
+	GSList *links;
+	GSList *list;
+	GSList *iter;
+
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_WITH_TYPE (&input,
+				    BRASERO_PLUGIN_IO_NONE,
+				    "Creating checksuming task with input");
+
+	/* first find a checksuming job that can output the type of required
+	 * checksum. Then go through the caps to see if the input type can be
+	 * found. */
+
+	/* some checks */
+	tracks = brasero_burn_session_get_tracks (session);
+	if (g_slist_length (tracks) != 1) {
+		g_set_error (error,
+			     BRASERO_BURN_ERROR,
+			     BRASERO_BURN_ERROR_GENERAL,
+			     _("Only one track at a time can be checked"));
+		return NULL;
+	}
+
+	/* get the required checksum type */
+	track = tracks->data;
+	checksum_type = brasero_track_get_checksum_type (track);
+
+	links = NULL;
+	for (iter = self->priv->tests; iter; iter = iter->next) {
+		BraseroCapsTest *test;
+
+		test = iter->data;
+		if (!test->links)
+			continue;
+
+		/* check this caps test supports the right checksum type */
+		if (test->type & checksum_type) {
+			links = test->links;
+			break;
+		}
+	}
+
+	if (!links) {
+		/* we failed to find and create a proper task */
+		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+	}
+
+	list = NULL;
+	last_caps = NULL;
+	brasero_track_get_track_type (track, &track_type);
+	for (iter = links; iter; iter = iter->next) {
+		BraseroCapsLink *link;
+		GSList *plugins;
+
+		link = iter->data;
+
+		/* NOTE: that shouldn't happen */
+		if (!link->caps)
+			continue;
+
+		BRASERO_BURN_LOG_TYPE (&link->caps->type, "Trying link to");
+
+		/* Make sure we have a candidate */
+		candidate = NULL;
+		for (plugins = link->plugins; plugins; plugins = plugins->next) {
+			BraseroPlugin *plugin;
+
+			plugin = plugins->data;
+			if (!brasero_plugin_get_active (plugin))
+				continue;
+
+			/* note for checksuming task there is no group possible */
+			if (!candidate)
+				candidate = plugin;
+			else if (brasero_plugin_get_priority (plugin) >
+				 brasero_plugin_get_priority (candidate))
+				candidate = plugin;
+		}
+
+		if (!candidate)
+			continue;
+
+		/* see if it can handle the input or if it can be linked to 
+		 * another plugin that can */
+		if (brasero_caps_is_compatible_type (link->caps, &input)) {
+			/* this is the right caps */
+			last_caps = link->caps;
+			break;
+		}
+
+		/* don't go any further if that's a DISC type */
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		/* the caps itself is not the right one so we try to 
+		 * go through its links to find the right caps. */
+		list = brasero_caps_find_best_link (link->caps,
+						    self->priv->group_id,
+						    NULL,
+						    BRASERO_BURN_FLAG_NONE,
+						    BRASERO_MEDIUM_NONE,
+						    &input,
+						    BRASERO_PLUGIN_IO_ACCEPT_PIPE);
+		if (list) {
+			last_caps = link->caps;
+			break;
+		}
+	}
+
+	if (!last_caps) {
+		/* no link worked failure */
+		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+	}
+
+	/* we made it. Create task */
+	task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
+					   "session", session,
+					   "action", BRASERO_TASK_ACTION_CHECKSUM,
+					   NULL));
+
+	list = g_slist_reverse (list);
+	for (iter = list; iter; iter = iter->next) {
+		GType type;
+		GSList *plugins;
+		BraseroCapsLink *link;
+		BraseroPlugin *candidate_plugin;
+		BraseroTrackType *plugin_output;
+
+		link = iter->data;
+
+		/* determine the plugin output */
+		if (iter->next) {
+			BraseroCapsLink *next_link;
+
+			next_link = iter->next->data;
+			plugin_output = &next_link->caps->type;
+		}
+		else
+			plugin_output = &last_caps->type;
+
+		/* find the best plugin */
+		candidate_plugin = NULL;
+		for (plugins = link->plugins; plugins; plugins = plugins->next) {
+			BraseroPlugin *plugin;
+
+			plugin = plugins->data;
+
+			if (!brasero_plugin_get_active (plugin))
+				continue;
+
+			if (!candidate_plugin)
+				candidate_plugin = plugin;
+			else if (brasero_plugin_get_priority (plugin) >
+				 brasero_plugin_get_priority (candidate_plugin))
+				candidate_plugin = plugin;
+		}
+
+		/* create the object */
+		type = brasero_plugin_get_gtype (candidate_plugin);
+		job = BRASERO_JOB (g_object_new (type,
+						 "output", plugin_output,
+						 NULL));
+		g_signal_connect (job,
+				  "error",
+				  G_CALLBACK (brasero_burn_caps_job_error_cb),
+				  link);
+
+		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
+
+		BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (candidate_plugin));
+	}
+	g_slist_free (list);
+
+	/* Create the candidate */
+	job = BRASERO_JOB (g_object_new (brasero_plugin_get_gtype (candidate),
+					 "output", NULL,
+					 NULL));
+	g_signal_connect (job,
+			  "error",
+			  G_CALLBACK (brasero_burn_caps_job_error_cb),
+			  self);
+	brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
+
+	return task;
+}
+
+BraseroTask *
+brasero_burn_caps_new_blanking_task (BraseroBurnCaps *self,
+				     BraseroBurnSession *session,
+				     GError **error)
+{
+	GSList *iter;
+	BraseroMedia media;
+	BraseroBurnFlag flags;
+	BraseroTask *task = NULL;
+
+	media = brasero_burn_session_get_dest_media (session);
+	flags = brasero_burn_session_get_flags (session);
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if ((media & caps->type.subtype.media) != media)
+			continue;
+
+		for (links = caps->links; links; links = links->next) {
+			GSList *plugins;
+			BraseroCapsLink *link;
+			BraseroPlugin *candidate;
+
+			link = links->data;
+
+			if (link->caps != NULL)
+				continue;
+
+			/* Go through all the plugins and find the best plugin
+			 * for the task. It must :
+			 * - be active
+			 * - have the highest priority
+			 * - accept the flags */
+			candidate = NULL;
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *plugin;
+
+				plugin = plugins->data;
+
+				if (!brasero_plugin_get_active (plugin))
+					continue;
+
+				if (!brasero_plugin_check_blank_flags (plugin, media, flags))
+					continue;
+
+				if (self->priv->group_id > 0 && candidate) {
+					/* the candidate must be in the favourite group as much as possible */
+					if (brasero_plugin_get_group (candidate) != self->priv->group_id) {
+						if (brasero_plugin_get_group (plugin) == self->priv->group_id) {
+							candidate = plugin;
+							continue;
+						}
+					}
+					else if (brasero_plugin_get_group (plugin) != self->priv->group_id)
+						continue;
+				}
+
+				if (!candidate)
+					candidate = plugin;
+				else if (brasero_plugin_get_priority (plugin) >
+					 brasero_plugin_get_priority (candidate))
+					candidate = plugin;
+			}
+
+			if (candidate) {
+				BraseroJob *job;
+				GType type;
+
+				type = brasero_plugin_get_gtype (candidate);
+				job = BRASERO_JOB (g_object_new (type,
+								 "output", NULL,
+								 NULL));
+				g_signal_connect (job,
+						  "error",
+						  G_CALLBACK (brasero_burn_caps_job_error_cb),
+						  caps);
+
+				task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
+								   "session", session,
+								   "action", BRASERO_TASK_ACTION_ERASE,
+								   NULL));
+				brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
+				return task;
+			}
+		}
+	}
+
+	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
+}

Added: trunk/libbrasero-burn/brasero-caps-burn.h
==============================================================================
--- (empty file)
+++ trunk/libbrasero-burn/brasero-caps-burn.h	Sun Apr  5 08:45:48 2009
@@ -0,0 +1,60 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn 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-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn 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-burn 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.
+ */
+
+#ifndef _BRASERO_CAPS_BURN_H_
+#define _BRASERO_CAPS_BURN_H_
+
+#include <glib.h>
+
+#include "burn-caps.h"
+#include "brasero-session.h"
+#include "burn-task.h"
+
+G_BEGIN_DECLS
+
+/**
+ * Returns a GSList * of BraseroTask * for a given session
+ */
+
+GSList *
+brasero_burn_caps_new_task (BraseroBurnCaps *caps,
+			    BraseroBurnSession *session,
+			    GError **error);
+BraseroTask *
+brasero_burn_caps_new_blanking_task (BraseroBurnCaps *caps,
+				     BraseroBurnSession *session,
+				     GError **error);
+BraseroTask *
+brasero_burn_caps_new_checksuming_task (BraseroBurnCaps *caps,
+					BraseroBurnSession *session,
+					GError **error);
+
+
+#endif /* _BRASERO_CAPS_BURN_H_ */

Added: trunk/libbrasero-burn/brasero-caps-plugin.c
==============================================================================
--- (empty file)
+++ trunk/libbrasero-burn/brasero-caps-plugin.c	Sun Apr  5 08:45:48 2009
@@ -0,0 +1,1035 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn 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-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn 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-burn 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 <string.h>
+
+#include <glib.h>
+
+#include "brasero-media.h"
+#include "brasero-media-private.h"
+
+#include "burn-caps.h"
+#include "burn-debug.h"
+
+#define SUBSTRACT(a, b)		((a) &= ~((b)&(a)))
+
+/**
+ * the following functions are used to register new caps
+ */
+
+static BraseroCapsLink *
+brasero_caps_find_link_for_input (BraseroCaps *caps,
+				  BraseroCaps *input)
+{
+	GSList *links;
+
+	for (links = caps->links; links; links = links->next) {
+		BraseroCapsLink *link;
+
+		link = links->data;
+		if (link->caps == input)
+			return link;
+	}
+
+	return NULL;
+}
+
+static gint
+brasero_burn_caps_sort (gconstpointer a, gconstpointer b)
+{
+	const BraseroCaps *caps_a = a;
+	const BraseroCaps *caps_b = b;
+	gint result;
+
+	/* First put DISC (the most used caps) then IMAGE type; these two types
+	 * are the ones that most often searched. At the end of the list we put
+	 * DATA  and AUDIO.
+	 * Another (sub)rule is that for DATA, DISC, AUDIO we put a caps that is
+	 * encompassed by another before.
+	 */
+
+	result = caps_b->type.type - caps_a->type.type;
+	if (result)
+		return result;
+
+	switch (caps_a->type.type) {
+	case BRASERO_TRACK_TYPE_DISC:
+		if (BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) !=
+		    BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media))
+			return ((gint32) BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) -
+			        (gint32) BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media));
+
+		if ((caps_a->type.subtype.media & BRASERO_MEDIUM_DVD)
+		&&  BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) !=
+		    BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media))			
+			return ((gint32) BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) -
+			        (gint32) BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media));
+
+		if (BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) !=
+		    BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media))
+			return BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) -
+			       BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media);
+
+		if (BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) !=
+		    BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media))
+			return BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) -
+			       BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media);
+
+		return (BRASERO_MEDIUM_INFO (caps_a->type.subtype.media) -
+			BRASERO_MEDIUM_INFO (caps_b->type.subtype.media));
+
+	case BRASERO_TRACK_TYPE_IMAGE:
+		/* This way BIN subtype is always sorted at the end */
+		return caps_a->type.subtype.img_format - caps_b->type.subtype.img_format;
+
+	case BRASERO_TRACK_TYPE_STREAM:
+		if (caps_a->type.subtype.audio_format != caps_b->type.subtype.audio_format) {
+			result = (caps_a->type.subtype.audio_format & caps_b->type.subtype.audio_format);
+			if (result == caps_a->type.subtype.audio_format)
+				return -1;
+			else if (result == caps_b->type.subtype.audio_format)
+				return 1;
+
+			return  (gint32) caps_a->type.subtype.audio_format -
+				(gint32) caps_b->type.subtype.audio_format;
+		}
+		break;
+
+	case BRASERO_TRACK_TYPE_DATA:
+		result = (caps_a->type.subtype.fs_type & caps_b->type.subtype.fs_type);
+		if (result == caps_a->type.subtype.fs_type)
+			return -1;
+		else if (result == caps_b->type.subtype.fs_type)
+			return 1;
+
+		return (caps_a->type.subtype.fs_type - caps_b->type.subtype.fs_type);
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static BraseroCapsLink *
+brasero_caps_link_copy (BraseroCapsLink *link)
+{
+	BraseroCapsLink *retval;
+
+	retval = g_new0 (BraseroCapsLink, 1);
+	retval->plugins = g_slist_copy (link->plugins);
+	retval->caps = link->caps;
+
+	return retval;
+}
+
+static void
+brasero_caps_link_list_duplicate (BraseroCaps *dest, BraseroCaps *src)
+{
+	GSList *iter;
+
+	for (iter = src->links; iter; iter = iter->next) {
+		BraseroCapsLink *link;
+
+		link = iter->data;
+		dest->links = g_slist_prepend (dest->links, brasero_caps_link_copy (link));
+	}
+}
+
+static BraseroCaps *
+brasero_caps_duplicate (BraseroCaps *caps)
+{
+	BraseroCaps *retval;
+
+	retval = g_new0 (BraseroCaps, 1);
+	retval->flags = caps->flags;
+	memcpy (&retval->type, &caps->type, sizeof (BraseroTrackType));
+	retval->modifiers = g_slist_copy (caps->modifiers);
+
+	return retval;
+}
+
+static void
+brasero_caps_replicate_modifiers (BraseroCaps *dest, BraseroCaps *src)
+{
+	GSList *iter;
+
+	for (iter = src->modifiers; iter; iter = iter->next) {
+		BraseroPlugin *plugin;
+
+		plugin = iter->data;
+
+		if (g_slist_find (dest->modifiers, plugin))
+			continue;
+
+		dest->modifiers = g_slist_prepend (dest->modifiers, plugin);
+	}
+}
+
+static void
+brasero_caps_replicate_links (BraseroBurnCaps *self,
+			      BraseroCaps *dest,
+			      BraseroCaps *src)
+{
+	GSList *iter;
+
+	brasero_caps_link_list_duplicate (dest, src);
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *iter_caps;
+		GSList *links;
+
+		iter_caps = iter->data;
+		if (iter_caps == src)
+			continue;
+
+		for (links = iter_caps->links; links; links = links->next) {
+			BraseroCapsLink *link;
+
+			link = links->data;
+			if (link->caps == src) {
+				BraseroCapsLink *copy;
+
+				copy = brasero_caps_link_copy (link);
+				copy->caps = dest;
+				iter_caps->links = g_slist_prepend (iter_caps->links, copy);
+			}
+		}
+	}
+}
+
+static void
+brasero_caps_replicate_tests (BraseroBurnCaps *self,
+			      BraseroCaps *dest,
+			      BraseroCaps *src)
+{
+	GSList *iter;
+
+	for (iter = self->priv->tests; iter; iter = iter->next) {
+		BraseroCapsTest *test;
+		GSList *links;
+
+		test = iter->data;
+		for (links = test->links; links; links = links->next) {
+			BraseroCapsLink *link;
+
+			link = links->data;
+			if (link->caps == src) {
+				BraseroCapsLink *copy;
+
+				copy = brasero_caps_link_copy (link);
+				copy->caps = dest;
+				test->links = g_slist_prepend (test->links, copy);
+			}
+		}
+	}
+}
+
+static void
+brasero_caps_copy_deep (BraseroBurnCaps *self,
+			BraseroCaps *dest,
+			BraseroCaps *src)
+{
+	brasero_caps_replicate_links (self, dest, src);
+	brasero_caps_replicate_tests (self, dest, src);
+	brasero_caps_replicate_modifiers (dest,src);
+}
+
+static BraseroCaps *
+brasero_caps_duplicate_deep (BraseroBurnCaps *self,
+			     BraseroCaps *caps)
+{
+	BraseroCaps *retval;
+
+	retval = brasero_caps_duplicate (caps);
+	brasero_caps_copy_deep (self, retval, caps);
+	return retval;
+}
+
+static GSList *
+brasero_caps_list_check_io (BraseroBurnCaps *self,
+			    GSList *list,
+			    BraseroPluginIOFlag flags)
+{
+	GSList *iter;
+
+	/* in this function we create the caps with the missing IO. All in the
+	 * list have something in common with flags. */
+	for (iter = list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		BraseroPluginIOFlag common;
+
+		caps = iter->data;
+		common = caps->flags & flags;
+		if (common != caps->flags) {
+			BraseroCaps *new_caps;
+
+			/* (common == flags) && common != caps->flags
+			 * caps->flags encompasses flags: Split the caps in two
+			 * and only keep the interesting part */
+			caps->flags &= ~common;
+
+			/* this caps has changed and needs to be sorted again */
+			self->priv->caps_list = g_slist_sort (self->priv->caps_list,
+							      brasero_burn_caps_sort);
+
+			new_caps = brasero_caps_duplicate_deep (self, caps);
+			new_caps->flags = common;
+
+			self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+								       new_caps,
+								       brasero_burn_caps_sort);
+
+			list = g_slist_prepend (list, new_caps);
+		}
+		else if (common != flags) {
+			GSList *node, *next;
+			BraseroPluginIOFlag complement = flags;
+
+			complement &= ~common;
+			for (node = list; node; node = next) {
+				BraseroCaps *tmp;
+
+				tmp = node->data;
+				next = node->next;
+
+				if (node == iter)
+					continue;
+
+				if (caps->type.type != tmp->type.type
+				||  caps->type.subtype.media != tmp->type.subtype.media)
+					continue;
+
+				/* substract the flags and relocate them at the
+				 * head of the list since we don't need to look
+				 * them up again */
+				complement &= ~(tmp->flags);
+				list = g_slist_remove (list, tmp);
+				list = g_slist_prepend (list, tmp);
+			}
+
+			if (complement != BRASERO_PLUGIN_IO_NONE) {
+				BraseroCaps *new_caps;
+
+				/* common == caps->flags && common != flags.
+				 * Flags encompasses caps->flags. So we need to
+				 * create a new caps for this type with the
+				 * substraction of flags if the other part isn't
+				 * in the list */
+				new_caps = brasero_caps_duplicate (caps);
+				new_caps->flags = flags & (~common);
+				self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+									       new_caps,
+									       brasero_burn_caps_sort);
+
+				list = g_slist_prepend (list, new_caps);
+			}
+		}
+	}
+
+	return list;
+}
+
+GSList *
+brasero_caps_image_new (BraseroPluginIOFlag flags,
+			BraseroImageFormat format)
+{
+	BraseroImageFormat remaining_format;
+	BraseroBurnCaps *self;
+	GSList *retval = NULL;
+	GSList *iter;
+
+	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_IMAGE,
+					 format,
+					 flags,
+					 "New caps required");
+
+	self = brasero_burn_caps_get_default ();
+
+	remaining_format = format;
+
+	/* We have to search all caps with or related to the format */
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		BraseroImageFormat common;
+		BraseroPluginIOFlag common_io;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE)
+			continue;
+
+		common_io = caps->flags & flags;
+		if (common_io == BRASERO_PLUGIN_IO_NONE)
+			continue;
+
+		common = (caps->type.subtype.img_format & format);
+		if (common == BRASERO_IMAGE_FORMAT_NONE)
+			continue;
+
+		if (common != caps->type.subtype.img_format) {
+			/* img_format encompasses format. Split it in two and
+			 * keep caps with common format */
+			SUBSTRACT (caps->type.subtype.img_format, common);
+			self->priv->caps_list = g_slist_sort (self->priv->caps_list,
+							      brasero_burn_caps_sort);
+
+			caps = brasero_caps_duplicate_deep (self, caps);
+			caps->type.subtype.img_format = common;
+
+			self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+								       caps,
+								       brasero_burn_caps_sort);
+		}
+
+		retval = g_slist_prepend (retval, caps);
+		remaining_format &= ~common;
+	}
+
+	/* Now we make sure that all these new or already 
+	 * existing caps have the proper IO Flags */
+	retval = brasero_caps_list_check_io (self, retval, flags);
+
+	if (remaining_format != BRASERO_IMAGE_FORMAT_NONE) {
+		BraseroCaps *caps;
+
+		caps = g_new0 (BraseroCaps, 1);
+		caps->flags = flags;
+		caps->type.subtype.img_format = remaining_format;
+		caps->type.type = BRASERO_TRACK_TYPE_IMAGE;
+
+		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+							       caps,
+							       brasero_burn_caps_sort);
+		retval = g_slist_prepend (retval, caps);
+
+		BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
+	}
+
+	g_object_unref (self);
+	return retval;
+}
+
+GSList *
+brasero_caps_audio_new (BraseroPluginIOFlag flags,
+			BraseroStreamFormat format)
+{
+	GSList *iter;
+	GSList *retval = NULL;
+	BraseroBurnCaps *self;
+	GSList *encompassing = NULL;
+	gboolean have_the_one = FALSE;
+
+	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_STREAM,
+					 format,
+					 flags,
+					 "New caps required");
+
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		BraseroStreamFormat common;
+		BraseroPluginIOFlag common_io;
+		BraseroStreamFormat common_audio;
+		BraseroStreamFormat common_video;
+
+		caps = iter->data;
+
+		if (caps->type.type != BRASERO_TRACK_TYPE_STREAM)
+			continue;
+
+		common_io = (flags & caps->flags);
+		if (common_io == BRASERO_PLUGIN_IO_NONE)
+			continue;
+
+		if (caps->type.subtype.audio_format == format) {
+			/* that's the perfect fit */
+			have_the_one = TRUE;
+			retval = g_slist_prepend (retval, caps);
+			continue;
+		}
+
+		/* Search caps strictly encompassed or encompassing our format
+		 * NOTE: make sure that if there is a VIDEO stream in one of
+		 * them, the other does have a VIDEO stream too. */
+		common_audio = BRASERO_STREAM_FORMAT_AUDIO (caps->type.subtype.audio_format) & 
+			       BRASERO_STREAM_FORMAT_AUDIO (format);
+		if (common_audio == BRASERO_AUDIO_FORMAT_NONE
+		&& (BRASERO_STREAM_FORMAT_AUDIO (caps->type.subtype.audio_format)
+		||  BRASERO_STREAM_FORMAT_AUDIO (format)))
+			continue;
+
+		common_video = BRASERO_STREAM_FORMAT_VIDEO (caps->type.subtype.audio_format) & 
+			       BRASERO_STREAM_FORMAT_VIDEO (format);
+
+		if (common_video == BRASERO_AUDIO_FORMAT_NONE
+		&& (BRASERO_STREAM_FORMAT_VIDEO (caps->type.subtype.audio_format)
+		||  BRASERO_STREAM_FORMAT_VIDEO (format)))
+			continue;
+
+		/* Likewise... that must be common */
+		if ((caps->type.subtype.audio_format & BRASERO_METADATA_INFO) != (format & BRASERO_METADATA_INFO))
+			continue;
+
+		common = common_audio|common_video|(format & BRASERO_METADATA_INFO);
+
+		/* encompassed caps just add it to retval */
+		if (caps->type.subtype.audio_format == common)
+			retval = g_slist_prepend (retval, caps);
+
+		/* encompassing caps keep it if we need to create perfect fit */
+		if (format == common)
+			encompassing = g_slist_prepend (encompassing, caps);
+	}
+
+	/* Now we make sure that all these new or already 
+	 * existing caps have the proper IO Flags */
+	retval = brasero_caps_list_check_io (self, retval, flags);
+
+	if (!have_the_one) {
+		BraseroCaps *caps;
+
+		caps = g_new0 (BraseroCaps, 1);
+		caps->flags = flags;
+		caps->type.subtype.audio_format = format;
+		caps->type.type = BRASERO_TRACK_TYPE_STREAM;
+
+		if (encompassing) {
+			for (iter = encompassing; iter; iter = iter->next) {
+				BraseroCaps *iter_caps;
+
+				iter_caps = iter->data;
+				brasero_caps_copy_deep (self, caps, iter_caps);
+			}
+		}
+
+		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+							       caps,
+							       brasero_burn_caps_sort);
+		retval = g_slist_prepend (retval, caps);
+
+		BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
+	}
+
+	g_slist_free (encompassing);
+
+	g_object_unref (self);
+
+	return retval;
+}
+
+GSList *
+brasero_caps_data_new (BraseroImageFS fs_type)
+{
+	GSList *iter;
+	GSList *retval = NULL;
+	BraseroBurnCaps *self;
+	GSList *encompassing = NULL;
+	gboolean have_the_one = FALSE;
+
+	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_DATA,
+					 fs_type,
+					 BRASERO_PLUGIN_IO_NONE,
+					 "New caps required");
+
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		BraseroImageFS common;
+
+		caps = iter->data;
+
+		if (caps->type.type != BRASERO_TRACK_TYPE_DATA)
+			continue;
+
+		if (caps->type.subtype.fs_type == fs_type) {
+			/* that's the perfect fit */
+			have_the_one = TRUE;
+			retval = g_slist_prepend (retval, caps);
+			continue;
+		}
+
+		/* search caps strictly encompassing our format ... */
+		common = caps->type.subtype.fs_type & fs_type;
+		if (common == BRASERO_IMAGE_FS_NONE)
+			continue;
+
+		/* encompassed caps just add it to retval */
+		if (caps->type.subtype.fs_type == common)
+			retval = g_slist_prepend (retval, caps);
+
+		/* encompassing caps keep it if we need to create perfect fit */
+		if (fs_type == common)
+			encompassing = g_slist_prepend (encompassing, caps);
+	}
+
+	if (!have_the_one) {
+		BraseroCaps *caps;
+
+		caps = g_new0 (BraseroCaps, 1);
+		caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+		caps->type.type = BRASERO_TRACK_TYPE_DATA;
+		caps->type.subtype.fs_type = fs_type;
+
+		if (encompassing) {
+			for (iter = encompassing; iter; iter = iter->next) {
+				BraseroCaps *iter_caps;
+
+				iter_caps = iter->data;
+				brasero_caps_copy_deep (self, caps, iter_caps);
+			}
+		}
+
+		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
+							       caps,
+							       brasero_burn_caps_sort);
+		retval = g_slist_prepend (retval, caps);
+	}
+
+	g_slist_free (encompassing);
+
+	g_object_unref (self);
+
+	return retval;
+}
+
+static GSList *
+brasero_caps_disc_lookup_or_create (BraseroBurnCaps *self,
+				    GSList *retval,
+				    BraseroMedia media)
+{
+	GSList *iter;
+	BraseroCaps *caps;
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		caps = iter->data;
+
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if (caps->type.subtype.media == media) {
+			BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+						    caps->flags,
+						    "Retrieved");
+			return g_slist_prepend (retval, caps);
+		}
+	}
+
+	caps = g_new0 (BraseroCaps, 1);
+	caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+	caps->type.type = BRASERO_TRACK_TYPE_DISC;
+	caps->type.subtype.media = media;
+
+	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+				    caps->flags,
+				    "Created");
+
+	self->priv->caps_list = g_slist_prepend (self->priv->caps_list, caps);
+
+	return g_slist_prepend (retval, caps);
+}
+
+GSList *
+brasero_caps_disc_new (BraseroMedia type)
+{
+	BraseroBurnCaps *self;
+	GSList *retval = NULL;
+	GSList *list;
+	GSList *iter;
+
+	self = brasero_burn_caps_get_default ();
+
+	list = brasero_media_get_all_list (type);
+	for (iter = list; iter; iter = iter->next) {
+		BraseroMedia medium;
+
+		medium = GPOINTER_TO_INT (iter->data);
+		retval = brasero_caps_disc_lookup_or_create (self, retval, medium);
+	}
+	g_slist_free (list);
+
+	g_object_unref (self);
+	return retval;
+}
+
+/**
+ * these functions are to create links
+ */
+
+static void
+brasero_caps_create_links (BraseroCaps *output,
+	 		   GSList *inputs,
+	 		   BraseroPlugin *plugin)
+{
+	for (; inputs; inputs = inputs->next) {
+		BraseroCaps *input;
+		BraseroCapsLink *link;
+
+		input = inputs->data;
+
+		if (output == input) {
+			BRASERO_BURN_LOG ("Same input and output for link. Dropping");
+			continue;
+		}
+
+		if (input->flags == output->flags
+		&&  input->type.type == output->type.type  
+		&&  input->type.subtype.media == output->type.subtype.media)
+			BRASERO_BURN_LOG ("Recursive link");
+
+		link = brasero_caps_find_link_for_input (output, input);
+
+#if 0
+
+		/* Mainly for extra debugging */
+		BRASERO_BURN_LOG_TYPE (&output->type, "Linking");
+		BRASERO_BURN_LOG_TYPE (&input->type, "to");
+		BRASERO_BURN_LOG ("with %s", brasero_plugin_get_name (plugin));
+
+#endif
+
+		if (!link) {
+			link = g_new0 (BraseroCapsLink, 1);
+			link->caps = input;
+			link->plugins = g_slist_prepend (NULL, plugin);
+
+			output->links = g_slist_prepend (output->links, link);
+		}
+		else
+			link->plugins = g_slist_prepend (link->plugins, plugin);
+	}
+}
+
+void
+brasero_plugin_link_caps (BraseroPlugin *plugin,
+			  GSList *outputs,
+			  GSList *inputs)
+{
+	/* we make sure the caps exists and if not we create them */
+	for (; outputs; outputs = outputs->next) {
+		BraseroCaps *output;
+
+		output = outputs->data;
+		brasero_caps_create_links (output, inputs, plugin);
+	}
+}
+
+void
+brasero_plugin_blank_caps (BraseroPlugin *plugin,
+			   GSList *caps_list)
+{
+	for (; caps_list; caps_list = caps_list->next) {
+		BraseroCaps *caps;
+		BraseroCapsLink *link;
+
+		caps = caps_list->data;
+
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+	
+		BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+					    caps->flags,
+					    "Adding blank caps for");
+
+		/* we need to find the link whose caps is NULL */
+		link = brasero_caps_find_link_for_input (caps, NULL);
+		if (!link) {
+			link = g_new0 (BraseroCapsLink, 1);
+			link->caps = NULL;
+			link->plugins = g_slist_prepend (NULL, plugin);
+
+			caps->links = g_slist_prepend (caps->links, link);
+		}
+		else
+			link->plugins = g_slist_prepend (link->plugins, plugin);
+	}
+}
+
+void
+brasero_plugin_process_caps (BraseroPlugin *plugin,
+			     GSList *caps_list)
+{
+	for (; caps_list; caps_list = caps_list->next) {
+		BraseroCaps *caps;
+
+		caps = caps_list->data;
+		caps->modifiers = g_slist_prepend (caps->modifiers, plugin);
+	}
+}
+
+void
+brasero_plugin_check_caps (BraseroPlugin *plugin,
+			   BraseroChecksumType type,
+			   GSList *caps_list)
+{
+	BraseroCapsTest *test = NULL;
+	BraseroBurnCaps *self;
+	GSList *iter;
+
+	/* Find the the BraseroCapsTest for this type; if none create it */
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->tests; iter; iter = iter->next) {
+		BraseroCapsTest *tmp;
+
+		tmp = iter->data;
+		if (tmp->type == type) {
+			test = tmp;
+			break;
+		}
+	}
+
+	if (!test) {
+		test = g_new0 (BraseroCapsTest, 1);
+		test->type = type;
+		self->priv->tests = g_slist_prepend (self->priv->tests, test);
+	}
+
+	g_object_unref (self);
+
+	for (; caps_list; caps_list = caps_list->next) {
+		GSList *links;
+		BraseroCaps *caps;
+		BraseroCapsLink *link;
+
+		caps = caps_list->data;
+
+		/* try to find a link for the above caps, if none create one */
+		link = NULL;
+		for (links = test->links; links; links = links->next) {
+			BraseroCapsLink *tmp;
+
+			tmp = links->data;
+			if (tmp->caps == caps) {
+				link = tmp;
+				break;
+			}
+		}
+
+		if (!link) {
+			link = g_new0 (BraseroCapsLink, 1);
+			link->caps = caps;
+			test->links = g_slist_prepend (test->links, link);
+		}
+
+		link->plugins = g_slist_prepend (link->plugins, plugin);
+	}
+}
+
+/**
+ * This is to register a plugin group 
+ * This function is only define here (though it's implemented in burn-plugin.c).
+ */
+
+void
+brasero_plugin_set_group (BraseroPlugin *plugin, gint group_id);
+
+void
+brasero_plugin_register_group (BraseroPlugin *plugin,
+			       const gchar *name)
+{
+	guint retval;
+	BraseroBurnCaps *self;
+
+	if (!name) {
+		brasero_plugin_set_group (plugin, 0);
+		return;
+	}
+
+	self = brasero_burn_caps_get_default ();
+
+	if (!self->priv->groups)
+		self->priv->groups = g_hash_table_new_full (g_str_hash,
+							    g_str_equal,
+							    g_free,
+							    NULL);
+
+	retval = GPOINTER_TO_INT (g_hash_table_lookup (self->priv->groups, name));
+	if (retval) {
+		brasero_plugin_set_group (plugin, retval);
+		g_object_unref (self);
+		return;
+	}
+
+	g_hash_table_insert (self->priv->groups,
+			     g_strdup (name),
+			     GINT_TO_POINTER (g_hash_table_size (self->priv->groups) + 1));
+
+	/* see if we have a group id now */
+	if (!self->priv->group_id
+	&&   self->priv->group_str
+	&&  !strcmp (name, self->priv->group_str))
+		self->priv->group_id = g_hash_table_size (self->priv->groups) + 1;
+
+	brasero_plugin_set_group (plugin, g_hash_table_size (self->priv->groups) + 1);
+
+	g_object_unref (self);
+}
+
+/** 
+ * This is to find out what are the capacities of a plugin
+ * Declared in brasero-plugin-private.h
+ */
+
+BraseroBurnResult
+brasero_plugin_can_burn (BraseroPlugin *plugin)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		for (links = caps->links; links; links = links->next) {
+			BraseroCapsLink *link;
+			GSList *plugins;
+
+			link = links->data;
+
+			/* see if the plugin is in the link by going through the list */
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *tmp;
+
+				tmp = plugins->data;
+				if (tmp == plugin) {
+					g_object_unref (self);
+					return BRASERO_BURN_OK;
+				}
+			}
+		}
+	}
+
+	g_object_unref (self);
+	return BRASERO_BURN_NOT_SUPPORTED;
+}
+
+BraseroBurnResult
+brasero_plugin_can_image (BraseroPlugin *plugin)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroTrackDataType destination;
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
+		&&  caps->type.type != BRASERO_TRACK_TYPE_STREAM
+		&&  caps->type.type != BRASERO_TRACK_TYPE_DATA)
+			continue;
+
+		destination = caps->type.type;
+		for (links = caps->links; links; links = links->next) {
+			BraseroCapsLink *link;
+			GSList *plugins;
+
+			link = links->data;
+			if (!link->caps
+			||   link->caps->type.type == destination)
+				continue;
+
+			/* see if the plugin is in the link by going through the list */
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *tmp;
+
+				tmp = plugins->data;
+				if (tmp == plugin) {
+					g_object_unref (self);
+					return BRASERO_BURN_OK;
+				}
+			}
+		}
+	}
+
+	g_object_unref (self);
+	return BRASERO_BURN_NOT_SUPPORTED;
+}
+
+BraseroBurnResult
+brasero_plugin_can_convert (BraseroPlugin *plugin)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroTrackDataType destination;
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
+		&&  caps->type.type != BRASERO_TRACK_TYPE_STREAM)
+			continue;
+
+		destination = caps->type.type;
+		for (links = caps->links; links; links = links->next) {
+			BraseroCapsLink *link;
+			GSList *plugins;
+
+			link = links->data;
+			if (!link->caps
+			||   link->caps->type.type != destination)
+				continue;
+
+			/* see if the plugin is in the link by going through the list */
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *tmp;
+
+				tmp = plugins->data;
+				if (tmp == plugin) {
+					g_object_unref (self);
+					return BRASERO_BURN_OK;
+				}
+			}
+		}
+	}
+
+	g_object_unref (self);
+
+	return BRASERO_BURN_NOT_SUPPORTED;
+}
+

Added: trunk/libbrasero-burn/brasero-caps-session.c
==============================================================================
--- (empty file)
+++ trunk/libbrasero-burn/brasero-caps-session.c	Sun Apr  5 08:45:48 2009
@@ -0,0 +1,1587 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Libbrasero-burn
+ * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app wanadoo fr>
+ *
+ * Libbrasero-burn 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-burn authors hereby grant permission for non-GPL compatible
+ * GStreamer plugins to be used and distributed together with GStreamer
+ * and Libbrasero-burn. This permission is above and beyond the permissions granted
+ * by the GPL license by which Libbrasero-burn 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-burn 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 <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "burn-caps.h"
+#include "burn-debug.h"
+#include "burn-plugin-private.h"
+
+#define BRASERO_BURN_CAPS_SHOULD_BLANK(media_MACRO, flags_MACRO)		\
+	((media_MACRO & BRASERO_MEDIUM_UNFORMATTED) ||				\
+	((media_MACRO & (BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) &&	\
+	 (flags_MACRO & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND)) == FALSE))
+
+#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES(session)			\
+{										\
+	brasero_burn_session_log (session, "Unsupported type of task operation"); \
+	BRASERO_BURN_LOG ("Unsupported type of task operation");		\
+	return BRASERO_BURN_NOT_SUPPORTED;					\
+}
+
+static BraseroBurnResult
+brasero_burn_caps_get_blanking_flags_real (BraseroBurnCaps *caps,
+					   BraseroMedia media,
+					   BraseroBurnFlag session_flags,
+					   BraseroBurnFlag *supported,
+					   BraseroBurnFlag *compulsory)
+{
+	GSList *iter;
+	gboolean supported_media;
+	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
+	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
+
+	BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
+	if (media == BRASERO_MEDIUM_NONE) {
+		BRASERO_BURN_LOG ("Blanking not possible: no media");
+		if (supported)
+			*supported = BRASERO_BURN_FLAG_NONE;
+		if (compulsory)
+			*compulsory = BRASERO_BURN_FLAG_NONE;
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	supported_media = FALSE;
+	for (iter = caps->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if ((media & caps->type.subtype.media) != media)
+			continue;
+
+		for (links = caps->links; links; links = links->next) {
+			GSList *plugins;
+			BraseroCapsLink *link;
+
+			link = links->data;
+
+			if (link->caps != NULL)
+				continue;
+
+			supported_media = TRUE;
+			/* don't need the plugins to be sorted since we go
+			 * through all the plugin list to get all blanking flags
+			 * available. */
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *plugin;
+				BraseroBurnFlag supported_plugin;
+				BraseroBurnFlag compulsory_plugin;
+
+				plugin = plugins->data;
+				if (!brasero_plugin_get_active (plugin))
+					continue;
+
+				if (!brasero_plugin_get_blank_flags (plugin,
+								     media,
+								     session_flags,
+								     &supported_plugin,
+								     &compulsory_plugin))
+					continue;
+
+				supported_flags |= supported_plugin;
+				compulsory_flags &= compulsory_plugin;
+			}
+		}
+	}
+
+	if (!supported_media) {
+		BRASERO_BURN_LOG ("media blanking not supported");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	if (supported)
+		*supported = supported_flags;
+	if (compulsory)
+		*compulsory = compulsory_flags;
+
+	return BRASERO_BURN_OK;
+}
+
+BraseroBurnResult
+brasero_burn_session_get_blank_flags (BraseroBurnSession *session,
+				      BraseroBurnFlag *supported,
+				      BraseroBurnFlag *compulsory)
+{
+	BraseroMedia media;
+	BraseroBurnCaps *self;
+	BraseroBurnResult result;
+	BraseroBurnFlag session_flags;
+
+	media = brasero_burn_session_get_dest_media (session);
+	BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
+
+	if (media == BRASERO_MEDIUM_NONE) {
+		BRASERO_BURN_LOG ("Blanking not possible: no media");
+		if (supported)
+			*supported = BRASERO_BURN_FLAG_NONE;
+		if (compulsory)
+			*compulsory = BRASERO_BURN_FLAG_NONE;
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	session_flags = brasero_burn_session_get_flags (session);
+
+	self = brasero_burn_caps_get_default ();
+	result = brasero_burn_caps_get_blanking_flags_real (self,
+							    media,
+							    session_flags,
+							    supported,
+							    compulsory);
+	g_object_unref (self);
+
+	return result;
+}
+
+static BraseroBurnResult
+brasero_burn_caps_can_blank_real (BraseroBurnCaps *self,
+				  BraseroMedia media,
+				  BraseroBurnFlag flags)
+{
+	GSList *iter;
+
+	BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
+	if (media == BRASERO_MEDIUM_NONE) {
+		BRASERO_BURN_LOG ("no media => no blanking possible");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		GSList *links;
+
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if ((media & caps->type.subtype.media) != media)
+			continue;
+
+		BRASERO_BURN_LOG_TYPE (&caps->type, "Searching links for caps");
+
+		for (links = caps->links; links; links = links->next) {
+			GSList *plugins;
+			BraseroCapsLink *link;
+
+			link = links->data;
+
+			if (link->caps != NULL)
+				continue;
+
+			BRASERO_BURN_LOG ("Searching plugins");
+
+			/* Go through all plugins for the link and stop if we 
+			 * find at least one active plugin that accepts the
+			 * flags. No need for plugins to be sorted */
+			for (plugins = link->plugins; plugins; plugins = plugins->next) {
+				BraseroPlugin *plugin;
+
+				plugin = plugins->data;
+				if (!brasero_plugin_get_active (plugin))
+					continue;
+
+				if (brasero_plugin_check_blank_flags (plugin, media, flags)) {
+					BRASERO_BURN_LOG_DISC_TYPE (media, "Can blank");
+					return BRASERO_BURN_OK;
+				}
+			}
+		}
+	}
+
+	BRASERO_BURN_LOG_DISC_TYPE (media, "No blanking capabilities for");
+
+	return BRASERO_BURN_NOT_SUPPORTED;
+}
+
+BraseroBurnResult
+brasero_burn_session_can_blank (BraseroBurnSession *session)
+{
+	BraseroMedia media;
+	BraseroBurnFlag flags;
+	BraseroBurnCaps *self;
+	BraseroBurnResult result;
+
+	self = brasero_burn_caps_get_default ();
+
+	media = brasero_burn_session_get_dest_media (session);
+	BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
+
+	if (media == BRASERO_MEDIUM_NONE) {
+		BRASERO_BURN_LOG ("no media => no blanking possible");
+		g_object_unref (self);
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	flags = brasero_burn_session_get_flags (session);
+	result = brasero_burn_caps_can_blank_real (self, media, flags);
+	g_object_unref (self);
+
+	return result;
+}
+
+/**
+ *
+ */
+
+static void
+brasero_caps_link_get_record_flags (BraseroCapsLink *link,
+				    BraseroMedia media,
+				    BraseroBurnFlag session_flags,
+				    BraseroBurnFlag *supported,
+				    BraseroBurnFlag *compulsory_retval)
+{
+	GSList *iter;
+	BraseroBurnFlag compulsory;
+
+	compulsory = BRASERO_BURN_FLAG_ALL;
+
+	/* Go through all plugins to get the supported/... record flags for link */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		gboolean result;
+		BraseroPlugin *plugin;
+		BraseroBurnFlag plugin_supported;
+		BraseroBurnFlag plugin_compulsory;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		result = brasero_plugin_get_record_flags (plugin,
+							  media,
+							  session_flags,
+							  &plugin_supported,
+							  &plugin_compulsory);
+		if (!result)
+			continue;
+
+		*supported |= plugin_supported;
+		compulsory &= plugin_compulsory;
+	}
+
+	*compulsory_retval = compulsory;
+}
+
+static void
+brasero_caps_link_get_data_flags (BraseroCapsLink *link,
+				  BraseroMedia media,
+				  BraseroBurnFlag session_flags,
+				  BraseroBurnFlag *supported)
+{
+	GSList *iter;
+
+	/* Go through all plugins the get the supported/... data flags for link */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		gboolean result;
+		BraseroPlugin *plugin;
+		BraseroBurnFlag plugin_supported;
+		BraseroBurnFlag plugin_compulsory;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		result = brasero_plugin_get_image_flags (plugin,
+							 media,
+							 session_flags,
+							 &plugin_supported,
+							 &plugin_compulsory);
+		*supported |= plugin_supported;
+	}
+}
+
+static gboolean
+brasero_caps_link_check_data_flags (BraseroCapsLink *link,
+				    BraseroBurnFlag session_flags,
+				    BraseroMedia media)
+{
+	GSList *iter;
+	BraseroBurnFlag flags;
+
+	/* here we just make sure that at least one of the plugins in the link
+	 * can comply with the flags (APPEND/MERGE) */
+	flags = session_flags & (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE);
+
+	/* If there are no image flags forget it */
+	if (flags == BRASERO_BURN_FLAG_NONE)
+		return TRUE;
+
+	/* Go through all plugins; at least one must support image flags */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		gboolean result;
+		BraseroPlugin *plugin;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		result = brasero_plugin_check_image_flags (plugin,
+							   media,
+							   session_flags);
+		if (result)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+brasero_caps_link_check_record_flags (BraseroCapsLink *link,
+				      BraseroBurnFlag session_flags,
+				      BraseroMedia media)
+{
+	GSList *iter;
+	BraseroBurnFlag flags;
+
+	flags = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
+
+	/* If there are no record flags forget it */
+	if (flags == BRASERO_BURN_FLAG_NONE)
+		return TRUE;
+	
+	/* Go through all plugins: at least one must support record flags */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		gboolean result;
+		BraseroPlugin *plugin;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		result = brasero_plugin_check_record_flags (plugin,
+							    media,
+							    session_flags);
+		if (result)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+brasero_caps_link_check_media_restrictions (BraseroCapsLink *link,
+					    BraseroMedia media)
+{
+	GSList *iter;
+
+	/* Go through all plugins: at least one must support media */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		gboolean result;
+		BraseroPlugin *plugin;
+
+		plugin = iter->data;
+		if (!brasero_plugin_get_active (plugin))
+			continue;
+
+		result = brasero_plugin_check_media_restrictions (plugin, media);
+		if (result)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+brasero_caps_find_link (BraseroCaps *caps,
+			BraseroBurnFlag session_flags,
+			gboolean use_flags,
+			BraseroMedia media,
+			BraseroTrackType *input,
+			BraseroPluginIOFlag io_flags)
+{
+	GSList *iter;
+
+	BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_link");
+
+	/* Here we only make sure we have at least one link working. For a link
+	 * to be followed it must first:
+	 * - link to a caps with correct io flags
+	 * - have at least a plugin accepting the record flags if caps type is
+	 *   a disc (that means that the link is the recording part)
+	 *
+	 * and either:
+	 * - link to a caps equal to the input
+	 * - link to a caps (linking itself to another caps, ...) accepting the
+	 *   input
+	 */
+
+	for (iter = caps->links; iter; iter = iter->next) {
+		BraseroCapsLink *link;
+		gboolean result;
+
+		link = iter->data;
+
+		if (!link->caps)
+			continue;
+
+		/* check that the link has some active plugin */
+		if (!brasero_caps_link_active (link))
+			continue;
+
+		/* since this link contains recorders, check that at least one
+		 * of them can handle the record flags */
+		if (use_flags
+		&&  caps->type.type == BRASERO_TRACK_TYPE_DISC
+		&& !brasero_caps_link_check_record_flags (link, session_flags, media))
+			continue;
+
+		/* first see if that's the perfect fit:
+		 * - it must have the same caps (type + subtype)
+		 * - it must have the proper IO */
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
+			if (use_flags
+			&& !brasero_caps_link_check_data_flags (link, session_flags, media))
+				continue;
+		}
+		else if (!brasero_caps_link_check_media_restrictions (link, media))
+			continue;
+
+		if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
+		&&   brasero_caps_is_compatible_type (link->caps, input))
+			return TRUE;
+
+		/* we can't go further than a DISC type */
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE)
+			continue;
+
+		/* try to see where the inputs of this caps leads to */
+		result = brasero_caps_find_link (link->caps,
+						 session_flags,
+						 use_flags,
+						 media,
+						 input,
+						 io_flags);
+		if (result)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+brasero_caps_try_output (BraseroBurnCaps *self,
+			 BraseroBurnFlag session_flags,
+			 gboolean use_flags,
+			 BraseroTrackType *output,
+			 BraseroTrackType *input,
+			 BraseroPluginIOFlag flags)
+{
+	BraseroCaps *caps;
+	BraseroMedia media;
+
+	/* here we search the start caps */
+	caps = brasero_burn_caps_find_start_caps (self, output);
+	if (!caps) {
+		BRASERO_BURN_LOG ("No caps available");
+		return FALSE;
+	}
+
+	if (output->type == BRASERO_TRACK_TYPE_DISC)
+		media = output->subtype.media;
+	else
+		media = BRASERO_MEDIUM_FILE;
+
+	return brasero_caps_find_link (caps,
+				       session_flags,
+				       use_flags,
+				       media,
+				       input,
+				       flags);
+}
+
+static gboolean
+brasero_caps_try_output_with_blanking (BraseroBurnCaps *self,
+				       BraseroBurnSession *session,
+				       BraseroTrackType *output,
+				       BraseroTrackType *input,
+				       BraseroPluginIOFlag io_flags,
+				       gboolean use_flags)
+{
+	gboolean result;
+	BraseroMedia media;
+	BraseroCaps *last_caps;
+	BraseroBurnFlag session_flags = BRASERO_BURN_FLAG_NONE;
+
+	if (use_flags)
+		session_flags = brasero_burn_session_get_flags (session);
+
+	result = brasero_caps_try_output (self,
+					  session_flags,
+					  use_flags,
+					  output,
+					  input,
+					  io_flags);
+	if (result)
+		return result;
+
+	/* we reached this point in two cases:
+	 * - if the disc cannot be handled
+	 * - if some flags are not handled
+	 * It is helpful only if:
+	 * - the disc was closed and no plugin can handle this type of 
+	 * disc once closed (CD-R(W))
+	 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
+	 * handle this flag (means that the plugin should erase and
+	 * then write on its own. Basically that works only with
+	 * overwrite formatted discs, DVD+RW, ...) */
+	if (output->type != BRASERO_TRACK_TYPE_DISC)
+		return FALSE;
+
+	/* output is a disc try with initial blanking */
+	BRASERO_BURN_LOG ("Support for input/output failed.");
+
+	/* apparently nothing can be done to reach our goal. Maybe that
+	 * is because we first have to blank the disc. If so add a blank 
+	 * task to the others as a first step */
+	if ((use_flags && !(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE))
+	||   brasero_burn_session_can_blank (session) != BRASERO_BURN_OK)
+		return FALSE;
+
+	BRASERO_BURN_LOG ("Trying with initial blanking");
+
+	/* retry with the same disc type but blank this time */
+	media = output->subtype.media;
+	media &= ~(BRASERO_MEDIUM_CLOSED|
+		   BRASERO_MEDIUM_APPENDABLE|
+		   BRASERO_MEDIUM_UNFORMATTED|
+		   BRASERO_MEDIUM_HAS_DATA|
+		   BRASERO_MEDIUM_HAS_AUDIO);
+	media |= BRASERO_MEDIUM_BLANK;
+	output->subtype.media = media;
+
+	last_caps = brasero_burn_caps_find_start_caps (self, output);
+	if (!last_caps)
+		return FALSE;
+
+	return brasero_caps_find_link (last_caps,
+				       session_flags,
+				       use_flags,
+				       media,
+				       input,
+				       io_flags);
+}
+
+BraseroBurnResult
+brasero_burn_session_input_supported (BraseroBurnSession *session,
+				      BraseroTrackType *input,
+				      gboolean use_flags)
+{
+	gboolean result;
+	BraseroBurnCaps *self;
+	BraseroTrackType output;
+	BraseroPluginIOFlag io_flags;
+
+	if (use_flags) {
+		result = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session),
+							brasero_burn_session_get_flags (session));
+
+		if (!result)
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
+	}
+
+	self = brasero_burn_caps_get_default ();
+	if (!brasero_burn_session_is_dest_file (session)) {
+		output.type = BRASERO_TRACK_TYPE_DISC;
+		output.subtype.media = brasero_burn_session_get_dest_media (session);
+
+		/* NOTE: for the special case where a disc could be rewritten
+		 * and cannot be handled as such but needs prior blanking, we
+		 * handle that situation in previous function.*/
+	}
+	else {
+		output.type = BRASERO_TRACK_TYPE_IMAGE;
+		output.subtype.img_format = brasero_burn_session_get_output_format (session);
+	}
+
+	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+	else
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+
+	BRASERO_BURN_LOG_TYPE (input, "Checking support for input");
+	BRASERO_BURN_LOG_TYPE (&output, "and output");
+
+	if (use_flags)
+		BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
+
+	result = brasero_caps_try_output_with_blanking (self,
+							session,
+							&output,
+							input,
+							io_flags,
+							use_flags);
+	g_object_unref (self);
+
+	if (!result) {
+		BRASERO_BURN_LOG_TYPE (input, "Input not supported");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	return BRASERO_BURN_OK;
+}
+
+BraseroBurnResult
+brasero_burn_session_output_supported (BraseroBurnSession *session,
+				       BraseroTrackType *output)
+{
+	gboolean result;
+	BraseroBurnCaps *self;
+	BraseroTrackType input;
+	BraseroPluginIOFlag io_flags;
+
+	self = brasero_burn_caps_get_default ();
+
+	/* Here, we can't check if the drive supports the flags since the output
+	 * is hypothetical. There is no real medium. So forget the following :
+	 * if (!brasero_burn_caps_flags_check_for_drive (session))
+	 *	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
+	 * The only thing we could do would be to check some known forbidden 
+	 * flags for some media provided the output type is DISC. */
+
+	/* Here flags don't matter as we don't record anything. Even the IOFlags
+	 * since that can be checked later with brasero_burn_caps_get_flags. */
+	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+	else
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_TYPE (output, "Checking support for output");
+	BRASERO_BURN_LOG_TYPE (&input, "and input");
+	BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
+	
+	result = brasero_caps_try_output_with_blanking (self,
+							session,
+							output,
+							&input,
+							io_flags,
+							TRUE);
+
+	g_object_unref (self);
+
+	if (!result) {
+		BRASERO_BURN_LOG_TYPE (output, "Output not supported");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	return BRASERO_BURN_OK;
+}
+
+/**
+ * This is only to be used in case one wants to copy using the same drive.
+ * It determines the possible middle image type.
+ */
+
+static BraseroBurnResult
+brasero_burn_caps_is_session_supported_same_src_dest (BraseroBurnCaps *self,
+						      BraseroBurnSession *session,
+						      gboolean use_flags)
+{
+	GSList *iter;
+	BraseroTrackType input;
+	BraseroTrackType output;
+	BraseroImageFormat format;
+	BraseroBurnFlag session_flags;
+
+	BRASERO_BURN_LOG ("Checking disc copy support with same source and destination");
+
+	/* To determine if a CD/DVD can be copied using the same source/dest,
+	 * we first determine if can be imaged and then if this image can be 
+	 * burnt to whatever medium type. */
+	memset (&input, 0, sizeof (BraseroTrackType));
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_TYPE (&input, "input");
+
+	if (use_flags) {
+		/* NOTE: DAO can be a problem. So just in case remove it. It is
+		 * not really useful in this context. What we want here is to
+		 * know whether a medium can be used given the input; only 1
+		 * flag is important here (MERGE) and can have consequences. */
+		session_flags = brasero_burn_session_get_flags (session);
+		session_flags &= ~BRASERO_BURN_FLAG_DAO;
+
+		BRASERO_BURN_LOG_FLAGS (session_flags, "flags");
+	}
+	else
+		session_flags = BRASERO_BURN_FLAG_NONE;
+
+	/* Find one available output format */
+	format = BRASERO_IMAGE_FORMAT_CDRDAO;
+	output.type = BRASERO_TRACK_TYPE_IMAGE;
+
+	for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
+		gboolean supported;
+
+		output.subtype.img_format = format;
+
+		BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
+		supported = brasero_caps_try_output_with_blanking (self,
+								   session,
+								   &output,
+								   &input,
+								   BRASERO_PLUGIN_IO_ACCEPT_FILE,
+								   use_flags);
+		if (!supported)
+			continue;
+
+		/* This format can be used to create an image. Check if can be
+		 * burnt now. Just find at least one medium. */
+		for (iter = self->priv->caps_list; iter; iter = iter->next) {
+			BraseroCaps *caps;
+			gboolean result;
+
+			caps = iter->data;
+
+			if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+				continue;
+
+			result = brasero_caps_find_link (caps,
+							 TRUE,
+							 session_flags,
+							 caps->type.subtype.media,
+							 &input,
+							 BRASERO_PLUGIN_IO_ACCEPT_FILE);
+
+			BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
+						    "Tested medium (%s)",
+						    result ? "working":"not working");
+
+			if (result)
+				return BRASERO_BURN_OK;
+		}
+	}
+
+	return BRASERO_BURN_NOT_SUPPORTED;
+}
+
+BraseroBurnResult
+brasero_burn_session_can_burn (BraseroBurnSession *session,
+			       gboolean use_flags)
+{
+	gboolean result;
+	BraseroBurnCaps *self;
+	BraseroTrackType input;
+	BraseroTrackType output;
+	BraseroPluginIOFlag io_flags;
+
+	self = brasero_burn_caps_get_default ();
+
+	/* Special case */
+	if (brasero_burn_session_same_src_dest_drive (session)) {
+		BraseroBurnResult res;
+
+		res = brasero_burn_caps_is_session_supported_same_src_dest (self, session, use_flags);
+		g_object_unref (self);
+		return res;
+	}
+
+	if (use_flags) {
+		result = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session),
+							brasero_burn_session_get_flags (session));
+
+		if (!result) {
+			g_object_unref (self);
+			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
+		}
+	}
+
+	/* Here flags don't matter as we don't record anything.
+	 * Even the IOFlags since that can be checked later with
+	 * brasero_burn_caps_get_flags. */
+	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+	else
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+
+	brasero_burn_session_get_input_type (session, &input);
+
+	if (!brasero_burn_session_is_dest_file (session)) {
+		output.type = BRASERO_TRACK_TYPE_DISC;
+		output.subtype.media = brasero_burn_session_get_dest_media (session);
+
+		/* NOTE: for the special case where a disc could be rewritten
+		 * and cannot be handled as such but needs prior blanking, we
+		 * handle that situation in previous function.*/
+	}
+	else {
+		output.type = BRASERO_TRACK_TYPE_IMAGE;
+		output.subtype.img_format = brasero_burn_session_get_output_format (session);
+	}
+
+	BRASERO_BURN_LOG_TYPE (&output, "Checking support for session output");
+	BRASERO_BURN_LOG_TYPE (&input, "and input");
+
+	if (use_flags)
+		BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
+
+	result = brasero_caps_try_output_with_blanking (self,
+							session,
+							&output,
+							&input,
+							io_flags,
+							use_flags);
+
+	g_object_unref (self);
+
+	if (!result) {
+		BRASERO_BURN_LOG_TYPE (&output, "Output not supported");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	return BRASERO_BURN_OK;
+}
+
+BraseroMedia
+brasero_burn_session_get_required_media_type (BraseroBurnSession *session)
+{
+	BraseroMedia required_media = BRASERO_MEDIUM_NONE;
+	BraseroBurnFlag session_flags;
+	BraseroPluginIOFlag io_flags;
+	BraseroTrackType input;
+	BraseroBurnCaps *self;
+	GSList *iter;
+
+	if (brasero_burn_session_is_dest_file (session))
+		return BRASERO_MEDIUM_FILE;
+
+	self = brasero_burn_caps_get_default ();
+
+	/* we try to determine here what type of medium is allowed to be burnt
+	 * to whether a CD or a DVD. Appendable, blank are not properties being
+	 * determined here. We just want it to be writable in a broad sense. */
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_TYPE (&input, "Determining required media type for input");
+
+	/* NOTE: BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE is a problem here since it
+	 * is only used if needed. Likewise DAO can be a problem. So just in
+	 * case remove them. They are not really useful in this context. What we
+	 * want here is to know which media can be used given the input; only 1
+	 * flag is important here (MERGE) and can have consequences. */
+	session_flags = brasero_burn_session_get_flags (session);
+	session_flags &= ~BRASERO_BURN_FLAG_DAO;
+
+	BRASERO_BURN_LOG_FLAGS (session_flags, "and flags");
+
+	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+	else
+		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+		gboolean result;
+
+		caps = iter->data;
+
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		/* Put BRASERO_MEDIUM_NONE so we can always succeed */
+		result = brasero_caps_find_link (caps,
+						 session_flags,
+						 TRUE,
+						 BRASERO_MEDIUM_NONE,
+						 &input,
+						 io_flags);
+
+		BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
+					    "Tested (%s)",
+					    result ? "working":"not working");
+
+		if (!result)
+			continue;
+
+		/* This caps work, add its subtype */
+		required_media |= caps->type.subtype.media;
+	}
+
+	/* filter as we are only interested in these */
+	required_media &= BRASERO_MEDIUM_WRITABLE|
+			  BRASERO_MEDIUM_CD|
+			  BRASERO_MEDIUM_DVD;
+
+	g_object_unref (self);
+	return required_media;
+}
+
+BraseroImageFormat
+brasero_burn_session_get_default_output_format (BraseroBurnSession *session)
+{
+	BraseroBurnCaps *self;
+	BraseroTrackType source;
+	BraseroTrackType output;
+	BraseroBurnResult result;
+
+	self = brasero_burn_caps_get_default ();
+
+	if (!brasero_burn_session_is_dest_file (session)) {
+		g_object_unref (self);
+		return BRASERO_IMAGE_FORMAT_NONE;
+	}
+
+	brasero_burn_session_get_input_type (session, &source);
+	if (source.type == BRASERO_TRACK_TYPE_NONE) {
+		g_object_unref (self);
+		return BRASERO_IMAGE_FORMAT_NONE;
+	}
+
+	if (source.type == BRASERO_TRACK_TYPE_IMAGE) {
+		g_object_unref (self);
+		return source.subtype.img_format;
+	}
+
+	output.type = BRASERO_TRACK_TYPE_IMAGE;
+	output.subtype.img_format = BRASERO_IMAGE_FORMAT_NONE;
+
+	if (source.type == BRASERO_TRACK_TYPE_STREAM) {
+		/* If that's AUDIO only without VIDEO then return */
+		if (!(source.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD))) {
+			g_object_unref (self);
+			return BRASERO_IMAGE_FORMAT_NONE;
+		}
+
+		/* Otherwise try all possible image types */
+		output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
+		for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
+		       output.subtype.img_format >>= 1) {
+		
+			result = brasero_burn_session_output_supported (session,
+									&output);
+			if (result == BRASERO_BURN_OK) {
+				g_object_unref (self);
+				return output.subtype.img_format;
+			}
+		}
+
+		g_object_unref (self);
+		return BRASERO_IMAGE_FORMAT_NONE;
+	}
+
+	if (source.type == BRASERO_TRACK_TYPE_DATA
+	|| (source.type == BRASERO_TRACK_TYPE_DISC
+	&& (source.subtype.media & BRASERO_MEDIUM_DVD))) {
+		output.subtype.img_format = BRASERO_IMAGE_FORMAT_BIN;
+		result = brasero_burn_session_output_supported (session,
+								&output);
+
+		g_object_unref (self);
+
+		if (result != BRASERO_BURN_OK)
+			return BRASERO_IMAGE_FORMAT_NONE;
+
+		return BRASERO_IMAGE_FORMAT_BIN;
+	}
+
+	/* for the input which are CDs there are lots of possible formats */
+	output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
+	for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
+	       output.subtype.img_format >>= 1) {
+	
+		result = brasero_burn_session_output_supported (session,
+								&output);
+		if (result == BRASERO_BURN_OK) {
+			g_object_unref (self);
+			return output.subtype.img_format;
+		}
+	}
+
+	g_object_unref (self);
+	return BRASERO_IMAGE_FORMAT_NONE;
+}
+
+static BraseroPluginIOFlag
+brasero_caps_get_flags (BraseroCaps *caps,
+			BraseroBurnFlag session_flags,
+			BraseroMedia media,
+			BraseroTrackType *input,
+			BraseroPluginIOFlag flags,
+			BraseroBurnFlag *supported,
+			BraseroBurnFlag *compulsory)
+{
+	GSList *iter;
+	BraseroPluginIOFlag retval = BRASERO_PLUGIN_IO_NONE;
+
+	/* First we must know if this link leads somewhere. It must 
+	 * accept the already existing flags. If it does, see if it 
+	 * accepts the input and if not, if one of its ancestors does */
+	for (iter = caps->links; iter; iter = iter->next) {
+		BraseroBurnFlag data_supported = BRASERO_BURN_FLAG_NONE;
+		BraseroBurnFlag rec_compulsory = BRASERO_BURN_FLAG_ALL;
+		BraseroBurnFlag rec_supported = BRASERO_BURN_FLAG_NONE;
+		BraseroPluginIOFlag io_flags;
+		BraseroCapsLink *link;
+
+		link = iter->data;
+
+		if (!link->caps)
+			continue;
+
+		/* check that the link has some active plugin */
+		if (!brasero_caps_link_active (link))
+			continue;
+
+		if (caps->type.type == BRASERO_TRACK_TYPE_DISC) {
+			BraseroBurnFlag tmp;
+
+			brasero_caps_link_get_record_flags (link,
+							    media,
+							    session_flags,
+							    &rec_supported,
+							    &rec_compulsory);
+
+			/* see if that link can handle the record flags.
+			 * NOTE: compulsory are not a failure in this case. */
+			tmp = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
+			if ((tmp & rec_supported) != tmp)
+				continue;
+		}
+
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
+			BraseroBurnFlag tmp;
+
+			brasero_caps_link_get_data_flags (link,
+							  media,
+							  session_flags,
+						    	  &data_supported);
+
+			/* see if that link can handle the data flags. 
+			 * NOTE: compulsory are not a failure in this case. */
+			tmp = session_flags & (BRASERO_BURN_FLAG_APPEND|
+					       BRASERO_BURN_FLAG_MERGE);
+
+			if ((tmp & data_supported) != tmp)
+				continue;
+		}
+		else if (!brasero_caps_link_check_media_restrictions (link, media))
+			continue;
+
+		/* see if that's the perfect fit */
+		if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
+		&&   brasero_caps_is_compatible_type (link->caps, input)) {
+			/* special case for input that handle output/input */
+			if (caps->type.type == BRASERO_TRACK_TYPE_DISC)
+				retval |= BRASERO_PLUGIN_IO_ACCEPT_PIPE;
+			else
+				retval |= caps->flags;
+
+			(*compulsory) &= rec_compulsory;
+			(*supported) |= data_supported|rec_supported;
+			continue;
+		}
+
+		if ((link->caps->flags & flags) == BRASERO_PLUGIN_IO_NONE)
+			continue;
+
+		/* we can't go further than a DISC type */
+		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		/* try to see where the inputs of this caps leads to */
+		io_flags = brasero_caps_get_flags (link->caps,
+						   session_flags,
+						   media,
+						   input,
+						   flags,
+						   supported,
+						   compulsory);
+		if (io_flags == BRASERO_PLUGIN_IO_NONE)
+			continue;
+
+		retval |= (io_flags & flags);
+		(*compulsory) &= rec_compulsory;
+		(*supported) |= data_supported|rec_supported;
+	}
+
+	return retval;
+}
+
+static BraseroBurnFlag
+brasero_medium_supported_flags (BraseroMedium *medium,
+				BraseroBurnFlag flags)
+{
+	BraseroMedia media;
+
+	media = brasero_medium_get_status (medium);
+
+	/* This is always FALSE */
+	if (media & BRASERO_MEDIUM_PLUS)
+		flags &= ~BRASERO_BURN_FLAG_DUMMY;
+
+	/* Simulation is only possible according to write modes. This mode is
+	 * mostly used by cdrecord/wodim for CLONE images. */
+	else if (media & BRASERO_MEDIUM_DVD) {
+		if (!brasero_medium_can_use_dummy_for_sao (medium))
+			flags &= ~BRASERO_BURN_FLAG_DUMMY;
+	}
+	else if (flags & BRASERO_BURN_FLAG_DAO) {
+		if (!brasero_medium_can_use_dummy_for_sao (medium))
+			flags &= ~BRASERO_BURN_FLAG_DUMMY;
+	}
+	else if (!brasero_medium_can_use_dummy_for_tao (medium))
+		flags &= ~BRASERO_BURN_FLAG_DUMMY;
+
+	if (!brasero_medium_can_use_burnfree (medium))
+		flags &= ~BRASERO_BURN_FLAG_BURNPROOF;
+
+	return flags;
+}
+
+static BraseroBurnFlag
+brasero_burn_caps_flags_update_for_drive (BraseroBurnFlag flags,
+					  BraseroBurnSession *session)
+{
+	BraseroDrive *drive;
+	BraseroMedium *medium;
+
+	drive = brasero_burn_session_get_burner (session);
+	if (!drive)
+		return flags;
+
+	medium = brasero_drive_get_medium (drive);
+	if (!medium)
+		return TRUE;
+
+	return brasero_medium_supported_flags (medium, flags);
+}
+
+static BraseroBurnResult
+brasero_caps_get_flags_for_disc (BraseroBurnCaps *self,
+				 BraseroBurnFlag session_flags,
+				 BraseroMedia media,
+				 BraseroTrackType *input,
+				 BraseroBurnFlag *supported,
+				 BraseroBurnFlag *compulsory)
+{
+	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
+	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
+	BraseroPluginIOFlag io_flags;
+	BraseroTrackType output;
+	BraseroCaps *caps;
+
+	/* create the output to find first caps */
+	output.type = BRASERO_TRACK_TYPE_DISC;
+	output.subtype.media = media;
+
+	caps = brasero_burn_caps_find_start_caps (self, &output);
+	if (!caps) {
+		BRASERO_BURN_LOG_DISC_TYPE (media, "FLAGS: no caps could be found for");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+				    caps->flags,
+				    "FLAGS: trying caps");
+
+	io_flags = brasero_caps_get_flags (caps,
+					   session_flags,
+					   media,
+					   input,
+					   BRASERO_PLUGIN_IO_ACCEPT_FILE|
+					   BRASERO_PLUGIN_IO_ACCEPT_PIPE,
+					   &supported_flags,
+					   &compulsory_flags);
+
+	if (io_flags == BRASERO_PLUGIN_IO_NONE) {
+		BRASERO_BURN_LOG ("FLAGS: not supported");
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+
+	/* RAW write mode should (must) only be used in this case */
+	if ((supported_flags & BRASERO_BURN_FLAG_RAW)
+	&&   input->type == BRASERO_TRACK_TYPE_IMAGE
+	&&   input->subtype.img_format == BRASERO_IMAGE_FORMAT_CLONE) {
+		supported_flags &= ~BRASERO_BURN_FLAG_DAO;
+		compulsory_flags &= ~BRASERO_BURN_FLAG_DAO;
+		compulsory_flags |= BRASERO_BURN_FLAG_RAW;
+	}
+	else
+		supported_flags &= ~BRASERO_BURN_FLAG_RAW;
+
+	if ((supported_flags & BRASERO_BURN_FLAG_DAO)
+	&&   input->type == BRASERO_TRACK_TYPE_STREAM
+	&&  (input->subtype.img_format & BRASERO_METADATA_INFO)) {
+		/* In this case, DAO is compulsory if we want to write CD-TEXT */
+		compulsory_flags |= BRASERO_BURN_FLAG_DAO;
+	}
+
+	if (io_flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE) {
+		supported_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
+
+		if ((io_flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) == 0)
+			compulsory_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
+	}
+
+	*supported |= supported_flags;
+	*compulsory |= compulsory_flags;
+
+	return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_burn_caps_get_flags_for_medium (BraseroBurnCaps *self,
+					BraseroMedia media,
+					BraseroBurnFlag session_flags,
+					BraseroTrackType *input,
+					BraseroBurnFlag *supported_flags,
+					BraseroBurnFlag *compulsory_flags)
+{
+	BraseroBurnResult result;
+
+	/* See if medium is supported out of the box */
+	result = brasero_caps_get_flags_for_disc (self,
+						  session_flags,
+						  media,
+						  input,
+						  supported_flags,
+						  compulsory_flags);
+
+	/* see if we can add BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE. Add it when:
+	 * - media can be blanked, it has audio or data and we're not merging
+	 * - media is not formatted and it can be blanked/formatted */
+	if (BRASERO_BURN_CAPS_SHOULD_BLANK (media, session_flags)
+	&&  brasero_burn_caps_can_blank_real (self, media, session_flags) == BRASERO_BURN_OK)
+		(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
+	else if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
+		return BRASERO_BURN_NOT_SUPPORTED;
+
+	if (((*supported_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
+		BraseroBurnFlag blank_compulsory = BRASERO_BURN_FLAG_NONE;
+		BraseroBurnFlag blank_supported = BRASERO_BURN_FLAG_NONE;
+
+		/* If BLANK flag is supported then MERGE/APPEND can't be compulsory */
+		(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
+
+		/* we reached this point in two cases:
+		 * - if the disc cannot be handled
+		 * - if some flags are not handled
+		 * It is helpful only if:
+		 * - the disc was closed and no plugin can handle this type of 
+		 * disc once closed (CD-R(W))
+		 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
+		 * handle this flag (means that the plugin should erase and
+		 * then write on its own. Basically that works only with
+		 * overwrite formatted discs, DVD+RW, ...) */
+
+		/* What's above is not entirely true. In fact we always need to
+		 * check even if we first succeeded. There are some cases like
+		 * CDRW where it's useful.
+		 * Ex: a CDRW with data appendable can be either appended (then
+		 * no DAO possible) or blanked and written (DAO possible). */
+
+		(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
+
+		/* result here is the result of the first operation, so if it
+		 * failed, BLANK before becomes compulsory. */
+		if (result != BRASERO_BURN_OK)
+			(*compulsory_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
+
+		/* pretends it is blank and formatted to see if it would work.
+		 * If it works then that means that the BLANK_BEFORE_WRITE flag
+		 * is compulsory. */
+		media &= ~(BRASERO_MEDIUM_CLOSED|
+			   BRASERO_MEDIUM_APPENDABLE|
+			   BRASERO_MEDIUM_UNFORMATTED|
+			   BRASERO_MEDIUM_HAS_DATA|
+			   BRASERO_MEDIUM_HAS_AUDIO);
+		media |= BRASERO_MEDIUM_BLANK;
+		result = brasero_caps_get_flags_for_disc (self,
+							  session_flags,
+							  media,
+							  input,
+							  supported_flags,
+							  compulsory_flags);
+
+		/* if both attempts failed, drop it */
+		if (result != BRASERO_BURN_OK
+		&& (((*compulsory_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)))
+			return result;
+
+		/* need to add blanking flags */
+		brasero_burn_caps_get_blanking_flags_real (self,
+							   media,
+							   session_flags,
+							   &blank_supported,
+							   &blank_compulsory);
+		(*supported_flags) |= blank_supported;
+		(*compulsory_flags) |= blank_compulsory;
+	}
+	else if (result != BRASERO_BURN_OK)
+		return result;
+
+	if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) {
+		/* make sure we remove MERGE/APPEND from supported and
+		 * compulsory since that's not possible anymore */
+		(*supported_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
+		(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
+	}
+
+	/* FIXME! we should restart the whole process if
+	 * ((session_flags & compulsory_flags) != compulsory_flags) since that
+	 * means that some supported files could be excluded but were not */
+
+	return BRASERO_BURN_OK;
+}
+
+static BraseroBurnResult
+brasero_burn_caps_get_flags_same_src_dest (BraseroBurnCaps *self,
+					   BraseroBurnSession *session,
+					   BraseroBurnFlag *supported_ret,
+					   BraseroBurnFlag *compulsory_ret)
+{
+	GSList *iter;
+	gboolean copy_supported;
+	BraseroTrackType input;
+	BraseroTrackType output;
+	BraseroImageFormat format;
+	BraseroBurnFlag session_flags;
+	BraseroBurnFlag supported_final = BRASERO_BURN_FLAG_NONE;
+	BraseroBurnFlag compulsory_final = BRASERO_BURN_FLAG_ALL;
+
+	BRASERO_BURN_LOG ("Retrieving disc copy flags with same source and destination");
+
+	/* To determine if a CD/DVD can be copied using the same source/dest,
+	 * we first determine if can be imaged and then what are the flags when
+	 * we can burn it to a particular medium type. */
+	memset (&input, 0, sizeof (BraseroTrackType));
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_TYPE (&input, "input");
+
+	session_flags = brasero_burn_session_get_flags (session);
+	BRASERO_BURN_LOG_FLAGS (session_flags, "(FLAGS) Session flags");
+
+	/* Check the current flags are possible */
+	if (session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_NO_TMP_FILES))
+		return BRASERO_BURN_NOT_SUPPORTED;
+
+	/* Check flags for all available format */
+	format = BRASERO_IMAGE_FORMAT_CDRDAO;
+	output.type = BRASERO_TRACK_TYPE_IMAGE;
+
+	copy_supported = FALSE;
+	for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
+		BraseroBurnResult result;
+		gboolean format_supported;
+
+		/* check this image type is possible given the current flags */
+		if (format != BRASERO_IMAGE_FORMAT_CLONE
+		&& (session_flags & BRASERO_BURN_FLAG_RAW))
+			continue;
+
+		output.subtype.img_format = format;
+
+		/* NOTE: there is no need to get the flags here since there are
+		 * no specific DISC => IMAGE flags. We just want to know if that
+		 * is possible. */
+		BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
+		format_supported = brasero_caps_try_output_with_blanking (self,
+									  session,
+									  &output,
+									  &input,
+									  BRASERO_PLUGIN_IO_ACCEPT_FILE,
+									  FALSE);
+		if (!format_supported) {
+			BRASERO_BURN_LOG_TYPE (&output, "Format not supported");
+			continue;
+		}
+
+		/* This format can be used to create an image. Check if can be
+		 * burnt now. Just find at least one medium. */
+		format_supported = FALSE;
+		for (iter = self->priv->caps_list; iter; iter = iter->next) {
+			BraseroBurnFlag compulsory;
+			BraseroBurnFlag supported;
+			BraseroCaps *caps;
+
+			caps = iter->data;
+			if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+				continue;
+
+			/* Merge all available flags for each possible medium type */
+			supported = BRASERO_BURN_FLAG_NONE;
+			compulsory = BRASERO_BURN_FLAG_NONE;
+			result = brasero_burn_caps_get_flags_for_medium (self,
+									 caps->type.subtype.media,
+									 session_flags,
+									 &output,
+									 &supported,
+									 &compulsory);
+			if (result != BRASERO_BURN_OK)
+				continue;
+
+			format_supported = TRUE;
+			supported_final |= supported;
+			compulsory_final &= compulsory;
+		}
+
+		BRASERO_BURN_LOG_TYPE (&output, "Format supported %i", format_supported);
+		if (format_supported)
+			copy_supported = TRUE;
+	}
+
+	if (!copy_supported)
+		return BRASERO_BURN_NOT_SUPPORTED;
+
+	*supported_ret |= supported_final;
+	*compulsory_ret |= compulsory_final;
+	
+	return BRASERO_BURN_OK;
+}
+
+BraseroBurnResult
+brasero_burn_session_get_burn_flags (BraseroBurnSession *session,
+				     BraseroBurnFlag *supported,
+				     BraseroBurnFlag *compulsory)
+{
+	gboolean res;
+	BraseroMedia media;
+	BraseroBurnCaps *self;
+	BraseroTrackType input;
+	BraseroBurnResult result;
+
+	BraseroBurnFlag session_flags;
+	/* FIXME: what's the meaning of NOGRACE when outputting ? */
+	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_NONE;
+	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_DONT_OVERWRITE|
+					  BRASERO_BURN_FLAG_CHECK_SIZE|
+					  BRASERO_BURN_FLAG_NOGRACE;
+
+	self = brasero_burn_caps_get_default ();
+
+	brasero_burn_session_get_input_type (session, &input);
+	BRASERO_BURN_LOG_WITH_TYPE (&input,
+				    BRASERO_PLUGIN_IO_NONE,
+				    "FLAGS: searching available flags for input");
+
+	if (brasero_burn_session_is_dest_file (session)) {
+		BRASERO_BURN_LOG ("FLAGS: image required");
+
+		/* In this case no APPEND/MERGE is possible */
+		if (input.type == BRASERO_TRACK_TYPE_DISC)
+			supported_flags |= BRASERO_BURN_FLAG_EJECT;
+
+		*supported = supported_flags;
+		*compulsory = compulsory_flags;
+
+		BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
+		BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
+
+		g_object_unref (self);
+		return BRASERO_BURN_OK;
+	}
+
+	supported_flags |= BRASERO_BURN_FLAG_EJECT;
+
+	/* special case */
+	if (brasero_burn_session_same_src_dest_drive (session)) {
+		result = brasero_burn_caps_get_flags_same_src_dest (self,
+								    session,
+								    &supported_flags,
+								    &compulsory_flags);
+
+		/* These flags are of course never possible */
+		supported_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
+				     BRASERO_BURN_FLAG_MERGE);
+		compulsory_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
+				      BRASERO_BURN_FLAG_MERGE);
+
+		if (result == BRASERO_BURN_OK) {
+			BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
+			BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
+
+			*supported = supported_flags;
+			*compulsory = compulsory_flags;
+		}
+		else
+			BRASERO_BURN_LOG ("No available flags for copy");
+
+		g_object_unref (self);
+		return result;
+	}
+
+	session_flags = brasero_burn_session_get_flags (session);
+	BRASERO_BURN_LOG_FLAGS (session_flags, "FLAGS (session):");
+
+	/* sanity check:
+	 * - drive must support flags
+	 * - MERGE and BLANK are not possible together.
+	 * - APPEND and MERGE are compatible. MERGE wins
+	 * - APPEND and BLANK are incompatible */
+	res = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session), session_flags);
+	if (!res) {
+		BRASERO_BURN_LOG ("Session flags not supported by drive");
+		g_object_unref (self);
+		return BRASERO_BURN_ERR;
+	}
+
+	if ((session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
+	&&  (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
+		g_object_unref (self);
+		return BRASERO_BURN_NOT_SUPPORTED;
+	}
+	
+	/* Let's get flags for recording */
+	media = brasero_burn_session_get_dest_media (session);
+	result = brasero_burn_caps_get_flags_for_medium (self,
+							 media,
+							 session_flags,
+							 &input,
+							 &supported_flags,
+							 &compulsory_flags);
+
+	g_object_unref (self);
+
+	if (result != BRASERO_BURN_OK)
+		return result;
+
+	supported_flags = brasero_burn_caps_flags_update_for_drive (supported_flags,
+								    session);
+
+	if (supported)
+		*supported = supported_flags;
+
+	if (compulsory)
+		*compulsory = compulsory_flags;
+
+	BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
+	BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
+	return BRASERO_BURN_OK;
+}

Modified: trunk/libbrasero-burn/brasero-track.c
==============================================================================
--- trunk/libbrasero-burn/brasero-track.c	(original)
+++ trunk/libbrasero-burn/brasero-track.c	Sun Apr  5 08:45:48 2009
@@ -43,6 +43,7 @@
 
 #include "brasero-track.h"
 #include "burn-debug.h"
+#include "burn-caps.h"
 #include "brasero-medium.h"
 #include "burn-image-format.h"
 #include "brasero-drive.h"
@@ -415,6 +416,34 @@
 }
 
 /**
+ * This is to determine whether of not a track type is supported
+ */
+
+BraseroBurnResult
+brasero_track_type_is_supported (BraseroTrackType *type)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+
+		caps = iter->data;
+
+		if (brasero_caps_is_compatible_type (caps, type)
+		&&  brasero_burn_caps_is_input (self, caps)) {
+			g_object_unref (self);
+			return BRASERO_BURN_OK;
+		}
+	}
+
+	g_object_unref (self);
+	return BRASERO_BURN_ERR;
+}
+
+/**
  * GObject part
  */
 

Modified: trunk/libbrasero-burn/burn-basics.c
==============================================================================
--- trunk/libbrasero-burn/burn-basics.c	(original)
+++ trunk/libbrasero-burn/burn-basics.c	Sun Apr  5 08:45:48 2009
@@ -49,11 +49,6 @@
 static BraseroPluginManager *plugin_manager = NULL;
 static BraseroMediumMonitor *medium_manager = NULL;
 
-/**
- * This is defined in burn-caps.c it's for debugging mainly
- */
-
-void brasero_caps_list_dump (void);
 
 GQuark
 brasero_burn_quark (void)
@@ -90,9 +85,52 @@
 }
 
 /**
- * Two utility functions
+ * utility functions
  */
 
+gboolean
+brasero_check_flags_for_drive (BraseroDrive *drive,
+			       BraseroBurnFlag flags)
+{
+	BraseroMedia media;
+	BraseroMedium *medium;
+
+	if (!drive)
+		return TRUE;
+
+	if (brasero_drive_is_fake (drive))
+		return TRUE;
+
+	medium = brasero_drive_get_medium (drive);
+	if (!medium)
+		return TRUE;
+
+	media = brasero_medium_get_status (medium);
+	if (flags & BRASERO_BURN_FLAG_DUMMY) {
+		/* This is always FALSE */
+		if (media & BRASERO_MEDIUM_PLUS)
+			return FALSE;
+
+		if (media & BRASERO_MEDIUM_DVD) {
+			if (!brasero_medium_can_use_dummy_for_sao (medium))
+				return FALSE;
+		}
+		else if (flags & BRASERO_BURN_FLAG_DAO) {
+			if (!brasero_medium_can_use_dummy_for_sao (medium))
+				return FALSE;
+		}
+		else if (!brasero_medium_can_use_dummy_for_tao (medium))
+			return FALSE;
+	}
+
+	if (flags & BRASERO_BURN_FLAG_BURNPROOF) {
+		if (!brasero_medium_can_use_burnfree (medium))
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
 gchar *
 brasero_string_get_localpath (const gchar *uri)
 {
@@ -138,6 +176,26 @@
 	return uri_return;
 }
 
+static void
+brasero_caps_list_dump (void)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *caps;
+
+		caps = iter->data;
+		BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
+					    caps->flags,
+					    "Created %i links pointing to",
+					    g_slist_length (caps->links));
+	}
+
+	g_object_unref (self);
+}
+
 gboolean
 brasero_burn_library_start (void)
 {
@@ -186,3 +244,116 @@
 	/* close HAL connection */
 //	brasero_hal_watch_destroy ();
 }
+
+gboolean
+brasero_burn_library_can_checksum (void)
+{
+	GSList *iter;
+	BraseroBurnCaps *self;
+
+	self = brasero_burn_caps_get_default ();
+
+	if (self->priv->tests == NULL) {
+		g_object_unref (self);
+		return FALSE;
+	}
+
+	for (iter = self->priv->tests; iter; iter = iter->next) {
+		BraseroCapsTest *tmp;
+		GSList *links;
+
+		tmp = iter->data;
+		for (links = tmp->links; links; links = links->next) {
+			BraseroCapsLink *link;
+
+			link = links->data;
+			if (brasero_caps_link_active (link)) {
+				g_object_unref (self);
+				return TRUE;
+			}
+		}
+	}
+
+	g_object_unref (self);
+	return FALSE;
+}
+
+/**
+ * Used to test what the library can do based on the medium type.
+ * Returns BRASERO_MEDIUM_WRITABLE if the disc can be written
+ * and / or BRASERO_MEDIUM_REWRITABLE if the disc can be erased.
+ */
+
+BraseroMedia
+brasero_burn_library_get_media_capabilities (BraseroMedia media)
+{
+	GSList *iter;
+	GSList *links;
+	BraseroMedia retval;
+	BraseroBurnCaps *self;
+	BraseroCaps *caps = NULL;
+
+	self = brasero_burn_caps_get_default ();
+
+	retval = BRASERO_MEDIUM_NONE;
+	BRASERO_BURN_LOG_DISC_TYPE (media, "checking media caps for");
+
+	/* we're only interested in DISC caps. There should be only one caps fitting */
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		caps = iter->data;
+		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
+			continue;
+
+		if ((media & caps->type.subtype.media) == media)
+			break;
+
+		caps = NULL;
+	}
+
+	if (!caps) {
+		g_object_unref (self);
+		return BRASERO_MEDIUM_NONE;
+	}
+
+	/* check the links */
+	for (links = caps->links; links; links = links->next) {
+		GSList *plugins;
+		gboolean active;
+		BraseroCapsLink *link;
+
+		link = links->data;
+
+		/* this link must have at least one active plugin to be valid
+		 * plugins are not sorted but in this case we don't need them
+		 * to be. we just need one active if another is with a better
+		 * priority all the better. */
+		active = FALSE;
+		for (plugins = link->plugins; plugins; plugins = plugins->next) {
+			BraseroPlugin *plugin;
+
+			plugin = plugins->data;
+			if (brasero_plugin_get_active (plugin)) {
+				/* this link is valid */
+				active = TRUE;
+				break;
+			}
+		}
+
+		if (!active)
+			continue;
+
+		if (!link->caps) {
+			/* means that it can be blanked */
+			retval |= BRASERO_MEDIUM_REWRITABLE;
+			continue;
+		}
+
+		/* means it can be written. NOTE: if this disc has already some
+		 * data on it, it even means it can be appended */
+		retval |= BRASERO_MEDIUM_WRITABLE;
+	}
+
+	g_object_unref (self);
+	return retval;
+}
+

Modified: trunk/libbrasero-burn/burn-basics.h
==============================================================================
--- trunk/libbrasero-burn/burn-basics.h	(original)
+++ trunk/libbrasero-burn/burn-basics.h	Sun Apr  5 08:45:48 2009
@@ -33,6 +33,7 @@
 
 #include <glib.h>
 
+#include "brasero-drive.h"
 #include "brasero-units.h"
 #include "brasero-enums.h"
 
@@ -66,6 +67,10 @@
 gchar *
 brasero_string_get_uri (const gchar *uri);
 
+gboolean
+brasero_check_flags_for_drive (BraseroDrive *drive,
+			       BraseroBurnFlag flags);
+
 G_END_DECLS
 
 #endif /* _BURN_BASICS_H */

Modified: trunk/libbrasero-burn/burn-caps.c
==============================================================================
--- trunk/libbrasero-burn/burn-caps.c	(original)
+++ trunk/libbrasero-burn/burn-caps.c	Sun Apr  5 08:45:48 2009
@@ -56,73 +56,9 @@
 
 G_DEFINE_TYPE (BraseroBurnCaps, brasero_burn_caps, G_TYPE_OBJECT);
 
-struct BraseroBurnCapsPrivate {
-	GSList *caps_list;
-	GSList *tests;
-
-	GHashTable *groups;
-
-	gchar *group_str;
-	guint group_id;
-};
-
-struct _BraseroCaps {
-	GSList *links;
-	GSList *modifiers;
-	BraseroTrackType type;
-	BraseroPluginIOFlag flags;
-};
-typedef struct _BraseroCaps BraseroCaps;
-
-struct _BraseroCapsLink {
-	GSList *plugins;
-	BraseroCaps *caps;
-};
-typedef struct _BraseroCapsLink BraseroCapsLink;
-
-struct _BraseroCapsTest {
-	GSList *links;
-	BraseroChecksumType type;
-};
-typedef struct _BraseroCapsTest BraseroCapsTest;
-
-#define SUBSTRACT(a, b)		((a) &= ~((b)&(a)))
-
 static GObjectClass *parent_class = NULL;
 static BraseroBurnCaps *default_caps = NULL;
 
-/**
- * This macro is used to determine whether or not blanking could change anything
- * for the medium so that we can write to it.
- */
-#define BRASERO_BURN_CAPS_SHOULD_BLANK(media_MACRO, flags_MACRO)		\
-	((media_MACRO & BRASERO_MEDIUM_UNFORMATTED) ||				\
-	((media_MACRO & (BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) &&	\
-	 (flags_MACRO & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND)) == FALSE))
-
-#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG(session)				\
-{										\
-	brasero_burn_session_log (session, "Unsupported type of task operation"); \
-	BRASERO_BURN_LOG ("Unsupported type of task operation");		\
-	return NULL;								\
-}
-
-#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES(session)			\
-{										\
-	brasero_burn_session_log (session, "Unsupported type of task operation"); \
-	BRASERO_BURN_LOG ("Unsupported type of task operation");		\
-	return BRASERO_BURN_NOT_SUPPORTED;					\
-}
-
-#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR(session, error)		\
-{										\
-	if (error)								\
-		g_set_error (error,						\
-			     BRASERO_BURN_ERROR,				\
-			     BRASERO_BURN_ERROR_GENERAL,			\
-			     _("An internal error occured"));	 		\
-	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session);				\
-}
 
 static void
 brasero_caps_link_free (BraseroCapsLink *link)
@@ -131,103 +67,73 @@
 	g_free (link);
 }
 
-static void
-brasero_caps_free (BraseroCaps *caps)
-{
-	g_slist_foreach (caps->links, (GFunc) brasero_caps_link_free, NULL);
-	g_slist_free (caps->links);
-	g_free (caps);
-}
-
-static void
-brasero_burn_caps_finalize (GObject *object)
+gboolean
+brasero_caps_link_active (BraseroCapsLink *link)
 {
-	BraseroBurnCaps *cobj;
+	GSList *iter;
 
-	cobj = BRASERO_BURNCAPS (object);
-	
-	default_caps = NULL;
+	/* See if link is active by going through all plugins. There must be at
+	 * least one. */
+	for (iter = link->plugins; iter; iter = iter->next) {
+		BraseroPlugin *plugin;
 
-	if (cobj->priv->groups) {
-		g_hash_table_destroy (cobj->priv->groups);
-		cobj->priv->groups = NULL;
+		plugin = iter->data;
+		if (brasero_plugin_get_active (plugin))
+			return TRUE;
 	}
 
-	g_slist_foreach (cobj->priv->caps_list, (GFunc) brasero_caps_free, NULL);
-	g_slist_free (cobj->priv->caps_list);
-
-	g_free (cobj->priv);
-	G_OBJECT_CLASS (parent_class)->finalize (object);
+	return FALSE;
 }
 
 static void
-brasero_burn_caps_class_init (BraseroBurnCapsClass *klass)
+brasero_caps_free (BraseroCaps *caps)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	parent_class = g_type_class_peek_parent (klass);
-	object_class->finalize = brasero_burn_caps_finalize;
+	g_slist_foreach (caps->links, (GFunc) brasero_caps_link_free, NULL);
+	g_slist_free (caps->links);
+	g_free (caps);
 }
 
-static void
-brasero_burn_caps_init (BraseroBurnCaps *obj)
+static gboolean
+brasero_caps_has_active_input (BraseroCaps *caps,
+			       BraseroCaps *input)
 {
-	GConfClient *client;
+	GSList *links;
 
-	obj->priv = g_new0 (BraseroBurnCapsPrivate, 1);
+	for (links = caps->links; links; links = links->next) {
+		BraseroCapsLink *link;
 
-	client = gconf_client_get_default ();
-	obj->priv->group_str = gconf_client_get_string (client,
-							BRASERO_ENGINE_GROUP_KEY,
-							NULL);
-	g_object_unref (client);
-}
+		link = links->data;
+		if (link->caps != input)
+			continue;
 
-BraseroBurnCaps *
-brasero_burn_caps_get_default ()
-{
-	if (!default_caps) 
-		default_caps = BRASERO_BURNCAPS (g_object_new (BRASERO_TYPE_BURNCAPS, NULL));
-	else
-		g_object_ref (default_caps);
+		if (brasero_caps_link_active (link))
+			return TRUE;
+	}
 
-	return default_caps;
+	return FALSE;
 }
 
-/* That function receives all errors returned by the object and 'learns' from 
- * these errors what are the safest defaults for a particular system. It should 
- * also offer fallbacks if an error occurs through a signal */
-static BraseroBurnResult
-brasero_burn_caps_job_error_cb (BraseroJob *job,
-				BraseroBurnError error,
-				BraseroBurnCaps *caps)
+gboolean
+brasero_burn_caps_is_input (BraseroBurnCaps *self,
+			    BraseroCaps *input)
 {
-#if 0
-	GError *error = NULL;
-	GConfClient *client;
+	GSList *iter;
 
-	/* This was originally to fix a bug in fedora 5 that prevents from
-	 * sending SCSI commands as a normal user through cdrdao. There is a
-	 * fallback fortunately with cdrecord and raw images but no on_the_fly
-	 * burning.
-	 * That could be used as a hook to know how a job runs and give a
-	 * "penalty" to job types being too often faulty. There could also be
-	 * a dialog to ask the user if he wants to use another backend.
-	 */
+	for (iter = self->priv->caps_list; iter; iter = iter->next) {
+		BraseroCaps *tmp;
 
-	/* set it in GConf to remember that next time */
-	client = gconf_client_get_default ();
-	gconf_client_set_bool (client, GCONF_KEY_CDRDAO_DISABLED, TRUE, &error);
-	if (error) {
-		g_warning ("Can't write with GConf: %s", error->message);
-		g_error_free (error);
+		tmp = iter->data;
+		if (tmp == input)
+			continue;
+
+		if (brasero_caps_has_active_input (tmp, input))
+			return TRUE;
 	}
-	g_object_unref (client);
-#endif
-	return BRASERO_BURN_ERR;
+
+	return FALSE;
 }
 
-static gboolean
+gboolean
 brasero_caps_is_compatible_type (const BraseroCaps *caps,
 				 const BraseroTrackType *type)
 {
@@ -278,9 +184,9 @@
 	return TRUE;
 }
 
-static BraseroCaps *
-brasero_caps_find_start_caps (BraseroBurnCaps *self,
-			      BraseroTrackType *output)
+BraseroCaps *
+brasero_burn_caps_find_start_caps (BraseroBurnCaps *self,
+				   BraseroTrackType *output)
 {
 	GSList *iter;
 
@@ -300,3741 +206,57 @@
 	return NULL;
 }
 
-static BraseroBurnResult
-brasero_burn_caps_get_blanking_flags_real (BraseroBurnCaps *caps,
-					   BraseroMedia media,
-					   BraseroBurnFlag session_flags,
-					   BraseroBurnFlag *supported,
-					   BraseroBurnFlag *compulsory)
-{
-	GSList *iter;
-	gboolean supported_media;
-	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
-	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
-
-	BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
-	if (media == BRASERO_MEDIUM_NONE) {
-		BRASERO_BURN_LOG ("Blanking not possible: no media");
-		if (supported)
-			*supported = BRASERO_BURN_FLAG_NONE;
-		if (compulsory)
-			*compulsory = BRASERO_BURN_FLAG_NONE;
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	supported_media = FALSE;
-	for (iter = caps->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if ((media & caps->type.subtype.media) != media)
-			continue;
-
-		for (links = caps->links; links; links = links->next) {
-			GSList *plugins;
-			BraseroCapsLink *link;
-
-			link = links->data;
-
-			if (link->caps != NULL)
-				continue;
-
-			supported_media = TRUE;
-			/* don't need the plugins to be sorted since we go
-			 * through all the plugin list to get all blanking flags
-			 * available. */
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *plugin;
-				BraseroBurnFlag supported_plugin;
-				BraseroBurnFlag compulsory_plugin;
-
-				plugin = plugins->data;
-				if (!brasero_plugin_get_active (plugin))
-					continue;
-
-				if (!brasero_plugin_get_blank_flags (plugin,
-								     media,
-								     session_flags,
-								     &supported_plugin,
-								     &compulsory_plugin))
-					continue;
-
-				supported_flags |= supported_plugin;
-				compulsory_flags &= compulsory_plugin;
-			}
-		}
-	}
-
-	if (!supported_media) {
-		BRASERO_BURN_LOG ("media blanking not supported");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	if (supported)
-		*supported = supported_flags;
-	if (compulsory)
-		*compulsory = compulsory_flags;
-
-	return BRASERO_BURN_OK;
-}
-
-BraseroBurnResult
-brasero_burn_session_get_blank_flags (BraseroBurnSession *session,
-				      BraseroBurnFlag *supported,
-				      BraseroBurnFlag *compulsory)
-{
-	BraseroMedia media;
-	BraseroBurnCaps *self;
-	BraseroBurnResult result;
-	BraseroBurnFlag session_flags;
-
-	media = brasero_burn_session_get_dest_media (session);
-	BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
-
-	if (media == BRASERO_MEDIUM_NONE) {
-		BRASERO_BURN_LOG ("Blanking not possible: no media");
-		if (supported)
-			*supported = BRASERO_BURN_FLAG_NONE;
-		if (compulsory)
-			*compulsory = BRASERO_BURN_FLAG_NONE;
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	session_flags = brasero_burn_session_get_flags (session);
-
-	self = brasero_burn_caps_get_default ();
-	result = brasero_burn_caps_get_blanking_flags_real (self,
-							    media,
-							    session_flags,
-							    supported,
-							    compulsory);
-	g_object_unref (self);
-
-	return result;
-}
-
-BraseroTask *
-brasero_burn_caps_new_blanking_task (BraseroBurnCaps *self,
-				     BraseroBurnSession *session,
-				     GError **error)
-{
-	GSList *iter;
-	BraseroMedia media;
-	BraseroBurnFlag flags;
-	BraseroTask *task = NULL;
-
-	media = brasero_burn_session_get_dest_media (session);
-	flags = brasero_burn_session_get_flags (session);
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if ((media & caps->type.subtype.media) != media)
-			continue;
-
-		for (links = caps->links; links; links = links->next) {
-			GSList *plugins;
-			BraseroCapsLink *link;
-			BraseroPlugin *candidate;
-
-			link = links->data;
-
-			if (link->caps != NULL)
-				continue;
-
-			/* Go through all the plugins and find the best plugin
-			 * for the task. It must :
-			 * - be active
-			 * - have the highest priority
-			 * - accept the flags */
-			candidate = NULL;
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *plugin;
-
-				plugin = plugins->data;
-
-				if (!brasero_plugin_get_active (plugin))
-					continue;
-
-				if (!brasero_plugin_check_blank_flags (plugin, media, flags))
-					continue;
-
-				if (self->priv->group_id > 0 && candidate) {
-					/* the candidate must be in the favourite group as much as possible */
-					if (brasero_plugin_get_group (candidate) != self->priv->group_id) {
-						if (brasero_plugin_get_group (plugin) == self->priv->group_id) {
-							candidate = plugin;
-							continue;
-						}
-					}
-					else if (brasero_plugin_get_group (plugin) != self->priv->group_id)
-						continue;
-				}
-
-				if (!candidate)
-					candidate = plugin;
-				else if (brasero_plugin_get_priority (plugin) >
-					 brasero_plugin_get_priority (candidate))
-					candidate = plugin;
-			}
-
-			if (candidate) {
-				BraseroJob *job;
-				GType type;
-
-				type = brasero_plugin_get_gtype (candidate);
-				job = BRASERO_JOB (g_object_new (type,
-								 "output", NULL,
-								 NULL));
-				g_signal_connect (job,
-						  "error",
-						  G_CALLBACK (brasero_burn_caps_job_error_cb),
-						  caps);
-
-				task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
-								   "session", session,
-								   "action", BRASERO_TASK_ACTION_ERASE,
-								   NULL));
-				brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
-				return task;
-			}
-		}
-	}
-
-	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-}
-
-static BraseroBurnResult
-brasero_burn_caps_can_blank_real (BraseroBurnCaps *self,
-				  BraseroMedia media,
-				  BraseroBurnFlag flags)
+static void
+brasero_burn_caps_finalize (GObject *object)
 {
-	GSList *iter;
-
-	BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
-	if (media == BRASERO_MEDIUM_NONE) {
-		BRASERO_BURN_LOG ("no media => no blanking possible");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if ((media & caps->type.subtype.media) != media)
-			continue;
-
-		BRASERO_BURN_LOG_TYPE (&caps->type, "Searching links for caps");
-
-		for (links = caps->links; links; links = links->next) {
-			GSList *plugins;
-			BraseroCapsLink *link;
-
-			link = links->data;
-
-			if (link->caps != NULL)
-				continue;
-
-			BRASERO_BURN_LOG ("Searching plugins");
-
-			/* Go through all plugins for the link and stop if we 
-			 * find at least one active plugin that accepts the
-			 * flags. No need for plugins to be sorted */
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *plugin;
-
-				plugin = plugins->data;
-				if (!brasero_plugin_get_active (plugin))
-					continue;
-
-				if (brasero_plugin_check_blank_flags (plugin, media, flags)) {
-					BRASERO_BURN_LOG_DISC_TYPE (media, "Can blank");
-					return BRASERO_BURN_OK;
-				}
-			}
-		}
-	}
-
-	BRASERO_BURN_LOG_DISC_TYPE (media, "No blanking capabilities for");
+	BraseroBurnCaps *cobj;
 
-	return BRASERO_BURN_NOT_SUPPORTED;
-}
+	cobj = BRASERO_BURNCAPS (object);
+	
+	default_caps = NULL;
 
-BraseroBurnResult
-brasero_burn_session_can_blank (BraseroBurnSession *session)
-{
-	BraseroMedia media;
-	BraseroBurnFlag flags;
-	BraseroBurnCaps *self;
-	BraseroBurnResult result;
-
-	self = brasero_burn_caps_get_default ();
-
-	media = brasero_burn_session_get_dest_media (session);
-	BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
-
-	if (media == BRASERO_MEDIUM_NONE) {
-		BRASERO_BURN_LOG ("no media => no blanking possible");
-		g_object_unref (self);
-		return BRASERO_BURN_NOT_SUPPORTED;
+	if (cobj->priv->groups) {
+		g_hash_table_destroy (cobj->priv->groups);
+		cobj->priv->groups = NULL;
 	}
 
-	flags = brasero_burn_session_get_flags (session);
-	result = brasero_burn_caps_can_blank_real (self, media, flags);
-	g_object_unref (self);
+	g_slist_foreach (cobj->priv->caps_list, (GFunc) brasero_caps_free, NULL);
+	g_slist_free (cobj->priv->caps_list);
 
-	return result;
+	g_free (cobj->priv);
+	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-/**
- *
- */
-
 static void
-brasero_caps_link_get_record_flags (BraseroCapsLink *link,
-				    BraseroMedia media,
-				    BraseroBurnFlag session_flags,
-				    BraseroBurnFlag *supported,
-				    BraseroBurnFlag *compulsory_retval)
+brasero_burn_caps_class_init (BraseroBurnCapsClass *klass)
 {
-	GSList *iter;
-	BraseroBurnFlag compulsory;
-
-	compulsory = BRASERO_BURN_FLAG_ALL;
-
-	/* Go through all plugins to get the supported/... record flags for link */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		gboolean result;
-		BraseroPlugin *plugin;
-		BraseroBurnFlag plugin_supported;
-		BraseroBurnFlag plugin_compulsory;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		result = brasero_plugin_get_record_flags (plugin,
-							  media,
-							  session_flags,
-							  &plugin_supported,
-							  &plugin_compulsory);
-		if (!result)
-			continue;
-
-		*supported |= plugin_supported;
-		compulsory &= plugin_compulsory;
-	}
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	*compulsory_retval = compulsory;
+	parent_class = g_type_class_peek_parent (klass);
+	object_class->finalize = brasero_burn_caps_finalize;
 }
 
 static void
-brasero_caps_link_get_data_flags (BraseroCapsLink *link,
-				  BraseroMedia media,
-				  BraseroBurnFlag session_flags,
-				  BraseroBurnFlag *supported)
-{
-	GSList *iter;
-
-	/* Go through all plugins the get the supported/... data flags for link */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		gboolean result;
-		BraseroPlugin *plugin;
-		BraseroBurnFlag plugin_supported;
-		BraseroBurnFlag plugin_compulsory;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		result = brasero_plugin_get_image_flags (plugin,
-							 media,
-							 session_flags,
-							 &plugin_supported,
-							 &plugin_compulsory);
-		*supported |= plugin_supported;
-	}
-}
-
-static gboolean
-brasero_caps_link_active (BraseroCapsLink *link)
+brasero_burn_caps_init (BraseroBurnCaps *obj)
 {
-	GSList *iter;
-
-	/* See if link is active by going through all plugins. There must be at
-	 * least one. */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		BraseroPlugin *plugin;
+	GConfClient *client;
 
-		plugin = iter->data;
-		if (brasero_plugin_get_active (plugin))
-			return TRUE;
-	}
+	obj->priv = g_new0 (BraseroBurnCapsPrivate, 1);
 
-	return FALSE;
+	client = gconf_client_get_default ();
+	obj->priv->group_str = gconf_client_get_string (client,
+							BRASERO_ENGINE_GROUP_KEY,
+							NULL);
+	g_object_unref (client);
 }
 
-static gboolean
-brasero_caps_link_check_data_flags (BraseroCapsLink *link,
-				    BraseroBurnFlag session_flags,
-				    BraseroMedia media)
+BraseroBurnCaps *
+brasero_burn_caps_get_default ()
 {
-	GSList *iter;
-	BraseroBurnFlag flags;
-
-	/* here we just make sure that at least one of the plugins in the link
-	 * can comply with the flags (APPEND/MERGE) */
-	flags = session_flags & (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE);
-
-	/* If there are no image flags forget it */
-	if (flags == BRASERO_BURN_FLAG_NONE)
-		return TRUE;
-
-	/* Go through all plugins; at least one must support image flags */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		gboolean result;
-		BraseroPlugin *plugin;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		result = brasero_plugin_check_image_flags (plugin,
-							   media,
-							   session_flags);
-		if (result)
-			return TRUE;
-	}
+	if (!default_caps) 
+		default_caps = BRASERO_BURNCAPS (g_object_new (BRASERO_TYPE_BURNCAPS, NULL));
+	else
+		g_object_ref (default_caps);
 
-	return FALSE;
+	return default_caps;
 }
-
-static gboolean
-brasero_caps_link_check_record_flags (BraseroCapsLink *link,
-				      BraseroBurnFlag session_flags,
-				      BraseroMedia media)
-{
-	GSList *iter;
-	BraseroBurnFlag flags;
-
-	flags = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
-
-	/* If there are no record flags forget it */
-	if (flags == BRASERO_BURN_FLAG_NONE)
-		return TRUE;
-	
-	/* Go through all plugins: at least one must support record flags */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		gboolean result;
-		BraseroPlugin *plugin;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		result = brasero_plugin_check_record_flags (plugin,
-							    media,
-							    session_flags);
-		if (result)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-brasero_caps_link_check_media_restrictions (BraseroCapsLink *link,
-					    BraseroMedia media)
-{
-	GSList *iter;
-
-	/* Go through all plugins: at least one must support media */
-	for (iter = link->plugins; iter; iter = iter->next) {
-		gboolean result;
-		BraseroPlugin *plugin;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		result = brasero_plugin_check_media_restrictions (plugin, media);
-		if (result)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static BraseroPlugin *
-brasero_caps_link_find_plugin (BraseroCapsLink *link,
-			       gint group_id,
-			       BraseroBurnFlag session_flags,
-			       BraseroTrackType *output,
-			       BraseroMedia media)
-{
-	GSList *iter;
-	BraseroPlugin *candidate;
-
-	/* Go through all plugins for a link and find the best one. It must:
-	 * - be active
-	 * - be part of the group (as much as possible)
-	 * - have the highest priority
-	 * - support the flags */
-	candidate = NULL;
-	for (iter = link->plugins; iter; iter = iter->next) {
-		BraseroPlugin *plugin;
-
-		plugin = iter->data;
-
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		if (output->type == BRASERO_TRACK_TYPE_DISC) {
-			gboolean result;
-
-			result = brasero_plugin_check_record_flags (plugin,
-								    media,
-								    session_flags);
-			if (!result)
-				continue;
-		}
-
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
-			gboolean result;
-
-			result = brasero_plugin_check_image_flags (plugin,
-								   media,
-								   session_flags);
-			if (!result)
-				continue;
-		}
-		else if (!brasero_plugin_check_media_restrictions (plugin, media))
-			continue;
-
-		if (group_id > 0 && candidate) {
-			/* the candidate must be in the favourite group as much as possible */
-			if (brasero_plugin_get_group (candidate) != group_id) {
-				if (brasero_plugin_get_group (plugin) == group_id) {
-					candidate = plugin;
-					continue;
-				}
-			}
-			else if (brasero_plugin_get_group (plugin) != group_id)
-				continue;
-		}
-
-		if (!candidate)
-			candidate = plugin;
-		else if (brasero_plugin_get_priority (plugin) >
-			 brasero_plugin_get_priority (candidate))
-			candidate = plugin;
-	}
-
-	return candidate;
-}
-
-typedef struct _BraseroCapsLinkList BraseroCapsLinkList;
-struct _BraseroCapsLinkList {
-	BraseroCapsLinkList *next;
-	BraseroCapsLink *link;
-	BraseroPlugin *plugin;
-};
-
-static BraseroCapsLinkList *
-brasero_caps_link_list_insert (BraseroCapsLinkList *list,
-			       BraseroCapsLinkList *node,
-			       gboolean fits)
-{
-	BraseroCapsLinkList *iter;
-
-	if (!list)
-		return node;
-
-	if (brasero_plugin_get_priority (node->plugin) >
-	    brasero_plugin_get_priority (list->plugin)) {
-		node->next = list;
-		return node;
-	}
-
-	if (brasero_plugin_get_priority (node->plugin) ==
-	    brasero_plugin_get_priority (list->plugin)) {
-		if (fits) {
-			node->next = list;
-			return node;
-		}
-
-		node->next = list->next;
-		list->next = node;
-		return list;
-	}
-
-	if (!list->next) {
-		node->next = NULL;
-		list->next = node;
-		return list;
-	}
-
-	/* Need a node with at least the same priority. Stop if end is reached */
-	iter = list;
-	while (iter->next &&
-	       brasero_plugin_get_priority (node->plugin) <
-	       brasero_plugin_get_priority (iter->next->plugin))
-		iter = iter->next;
-
-	if (!iter->next) {
-		/* reached the end of the list, put it at the end */
-		iter->next = node;
-		node->next = NULL;
-	}
-	else if (brasero_plugin_get_priority (node->plugin) <
-		 brasero_plugin_get_priority (iter->next->plugin)) {
-		/* Put it at the end of the list */
-		node->next = NULL;
-		iter->next->next = node;
-	}
-	else if (brasero_plugin_get_priority (node->plugin) >
-		 brasero_plugin_get_priority (iter->next->plugin)) {
-		/* insert it before iter->next */
-		node->next = iter->next;
-		iter->next = node;
-	}
-	else if (fits) {
-		/* insert it before the link with the same priority */
-		node->next = iter->next;
-		iter->next = node;
-	}
-	else {
-		/* insert it after the link with the same priority */
-		node->next = iter->next->next;
-		iter->next->next = node;
-	}
-	return list;
-}
-
-static GSList *
-brasero_caps_find_best_link (BraseroCaps *caps,
-			     gint group_id,
-			     GSList *used_caps,
-			     BraseroBurnFlag session_flags,
-			     BraseroMedia media,
-			     BraseroTrackType *input,
-			     BraseroPluginIOFlag io_flags)
-{
-	GSList *iter;
-	GSList *results = NULL;
-	BraseroCapsLinkList *node = NULL;
-	BraseroCapsLinkList *list = NULL;
-
-	BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_best_link");
-
-	/* First, build a list of possible links and sort them out according to
-	 * the priority based on the highest priority among their plugins. In 
-	 * this case, we can't sort links beforehand since according to the
-	 * flags, input, output in the session the plugins will or will not 
-	 * be used. Moreover given the group_id thing the choice of plugin may
-	 * depends. */
-
-	/* This is done to address possible issues namely:
-	 * - growisofs can handle DATA right from the start but has a lower
-	 * priority than libburn. In this case growisofs would be used every 
-	 * time for DATA despite its having a lower priority than libburn if we
-	 * were looking for the best fit first
-	 * - We don't want to follow the long path and have a useless (in this
-	 * case) image converter plugin get included.
-	 * ex: we would have: CDRDAO (input) toc2cue => (CUE) cdrdao => (DISC)
-	 * instead of simply: CDRDAO (input) cdrdao => (DISC) */
-
-	for (iter = caps->links; iter; iter = iter->next) {
-		BraseroPlugin *plugin;
-		BraseroCapsLink *link;
-		gboolean fits;
-
-		link = iter->data;
-
-		/* skip blanking links */
-		if (!link->caps) {
-			BRASERO_BURN_LOG ("Blanking caps");
-			continue;
-		}
-
-		/* the link should not link to an already used caps */
-		if (g_slist_find (used_caps, link->caps)) {
-			BRASERO_BURN_LOG ("Already used caps");
-			continue;
-		}
-
-		/* see if that's a perfect fit;
-		 * - it must have the same caps (type + subtype)
-		 * - it must have the proper IO (file). */
-		fits = (link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) &&
-			brasero_caps_is_compatible_type (link->caps, input);
-
-		if (!fits) {
-			/* if it doesn't fit it must be at least connectable */
-			if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE) {
-				BRASERO_BURN_LOG ("Not connectable");
-				continue;
-			}
-
-			/* we can't go further than a DISC type, no need to keep it */
-			if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC) {
-				BRASERO_BURN_LOG ("Can't go further than DISC caps");
-				continue;
-			}
-		}
-
-		/* See if this link can be used. For a link to be followed it 
-		 * must:
-		 * - have at least an active plugin
-		 * - have at least a plugin accepting the record flags if caps type (output) 
-		 *   is a disc (that means that the link is the recording part) 
-		 * - have at least a plugin accepting the data flags if caps type (input)
-		 *   is DATA. */
-		plugin = brasero_caps_link_find_plugin (link,
-							group_id,
-							session_flags,
-							&caps->type,
-							media);
-		if (!plugin) {
-			BRASERO_BURN_LOG ("No plugin found");
-			continue;
-		}
-
-		BRASERO_BURN_LOG ("Found candidate link");
-
-		/* A plugin could be found which means that link can be used.
-		 * Insert it in the list at the right place.
-		 * The list is sorted according to priorities (starting with the
-		 * highest). If 2 links have the same priority put first the one
-		 * that has the correct input. */
-		node = g_new0 (BraseroCapsLinkList, 1);
-		node->plugin = plugin;
-		node->link = link;
-
-		list = brasero_caps_link_list_insert (list, node, fits);
-	}
-
-	if (!list) {
-		BRASERO_BURN_LOG ("No links found");
-		return NULL;
-	}
-
-	used_caps = g_slist_prepend (used_caps, caps);
-
-	/* Then, go through this list (starting with highest priority links)
-	 * The rule is we prefer the links with the highest priority; if two
-	 * links have the same priority and one of them leads to a caps
-	 * with the correct type then choose this one. */
-	for (node = list; node; node = node->next) {
-		guint search_group_id;
-
-		/* see if that's a perfect fit; if so, then we're good. 
-		 * - it must have the same caps (type + subtype)
-		 * - it must have the proper IO (file) */
-		if ((node->link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
-		&&   brasero_caps_is_compatible_type (node->link->caps, input)) {
-			results = g_slist_prepend (NULL, node->link);
-			break;
-		}
-
-		/* determine the group_id for the search */
-		if (brasero_plugin_get_group (node->plugin) > 0 && group_id <= 0)
-			search_group_id = brasero_plugin_get_group (node->plugin);
-		else
-			search_group_id = group_id;
-
-		/* It's not a perfect fit. First see if a plugin with the same
-		 * priority don't have the right input. Then see if we can reach
-		 * the right input by going through all previous nodes */
-		results = brasero_caps_find_best_link (node->link->caps,
-						       search_group_id,
-						       used_caps,
-						       session_flags,
-						       media,
-						       input,
-						       io_flags);
-		if (results) {
-			results = g_slist_prepend (results, node->link);
-			break;
-		}
-	}
-
-	/* clear up */
-	used_caps = g_slist_remove (used_caps, caps);
-	for (node = list; node; node = list) {
-		list = node->next;
-		g_free (node);
-	}
-
-	return results;
-}
-
-static gboolean
-brasero_burn_caps_sort_modifiers (gconstpointer a,
-				  gconstpointer b)
-{
-	BraseroPlugin *plug_a = BRASERO_PLUGIN (a);
-	BraseroPlugin *plug_b = BRASERO_PLUGIN (b);
-
-	return brasero_plugin_get_priority (plug_a) -
-	       brasero_plugin_get_priority (plug_b);
-}
-
-static GSList *
-brasero_caps_add_processing_plugins_to_task (BraseroBurnSession *session,
-					     BraseroTask *task,
-					     BraseroCaps *caps,
-					     BraseroTrackType *io_type,
-					     BraseroPluginProcessFlag position)
-{
-	GSList *retval = NULL;
-	GSList *modifiers;
-	GSList *iter;
-
-	if (position == BRASERO_PLUGIN_RUN_NEVER
-	||  caps->type.type == BRASERO_TRACK_TYPE_DISC)
-		return NULL;
-
-	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-				    caps->flags,
-				    "Adding modifiers (position %i) (%i modifiers available) for",
-				    position,
-				    g_slist_length (caps->modifiers));
-
-	/* Go through all plugins and add all possible modifiers. They must:
-	 * - be active
-	 * - accept the position flags */
-	modifiers = g_slist_copy (caps->modifiers);
-	modifiers = g_slist_sort (modifiers, brasero_burn_caps_sort_modifiers);
-
-	for (iter = modifiers; iter; iter = iter->next) {
-		BraseroPluginProcessFlag flags;
-		BraseroPlugin *plugin;
-		BraseroJob *job;
-		GType type;
-
-		plugin = iter->data;
-		if (!brasero_plugin_get_active (plugin))
-			continue;
-
-		brasero_plugin_get_process_flags (plugin, &flags);
-		if ((flags & position) != position)
-			continue;
-
-		type = brasero_plugin_get_gtype (plugin);
-		job = BRASERO_JOB (g_object_new (type,
-						 "output", io_type,
-						 NULL));
-		g_signal_connect (job,
-				  "error",
-				  G_CALLBACK (brasero_burn_caps_job_error_cb),
-				  caps);
-
-		if (!task
-		||  !(caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
-		||  !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
-			/* here the action taken is always to create an image */
-			task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
-							   "session", session,
-							   "action", BRASERO_BURN_ACTION_CREATING_IMAGE,
-							   NULL));
-			retval = g_slist_prepend (retval, task);
-		}
-
-		BRASERO_BURN_LOG ("%s (modifier) added to task",
-				  brasero_plugin_get_name (plugin));
-
-		BRASERO_BURN_LOG_TYPE (io_type, "IO type");
-
-		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
-	}
-	g_slist_free (modifiers);
-
-	return retval;
-}
-
-/**
- * This one is not supposed to be public API. It's declared in burn-caps.c
- */
-
-gboolean
-brasero_medium_support_flags (BraseroMedium *medium,
-			      BraseroBurnFlag flags)
-{
-	BraseroMedia media;
-
-	media = brasero_medium_get_status (medium);
-	if (flags & BRASERO_BURN_FLAG_DUMMY) {
-		/* This is always FALSE */
-		if (media & BRASERO_MEDIUM_PLUS)
-			return FALSE;
-
-		if (media & BRASERO_MEDIUM_DVD) {
-			if (!brasero_medium_can_use_dummy_for_sao (medium))
-				return FALSE;
-		}
-		else if (flags & BRASERO_BURN_FLAG_DAO) {
-			if (!brasero_medium_can_use_dummy_for_sao (medium))
-				return FALSE;
-		}
-		else if (!brasero_medium_can_use_dummy_for_tao (medium))
-			return FALSE;
-	}
-
-	if (flags & BRASERO_BURN_FLAG_BURNPROOF) {
-		if (!brasero_medium_can_use_burnfree (medium))
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean
-brasero_burn_caps_flags_check_for_drive (BraseroBurnSession *session)
-{
-	BraseroDrive *drive;
-	BraseroMedium *medium;
-	BraseroBurnFlag flags;
-
-	drive = brasero_burn_session_get_burner (session);
-	if (!drive)
-		return TRUE;
-
-	if (brasero_drive_is_fake (drive))
-		return TRUE;
-
-	medium = brasero_drive_get_medium (drive);
-	if (!medium)
-		return TRUE;
-
-	flags = brasero_burn_session_get_flags (session);
-	return brasero_medium_support_flags (medium, flags);
-}
-
-GSList *
-brasero_burn_caps_new_task (BraseroBurnCaps *self,
-			    BraseroBurnSession *session,
-			    GError **error)
-{
-	BraseroPluginProcessFlag position;
-	BraseroBurnFlag session_flags;
-	BraseroTrackType plugin_input;
-	BraseroTask *blanking = NULL;
-	BraseroPluginIOFlag flags;
-	BraseroTask *task = NULL;
-	BraseroTrackType output;
-	BraseroTrackType input;
-	BraseroCaps *last_caps;
-	GSList *retval = NULL;
-	GSList *iter, *list;
-	BraseroMedia media;
-	gint group_id;
-
-	/* determine the output and the flags for this task */
-	if (brasero_burn_session_is_dest_file (session)) {
-		media = BRASERO_MEDIUM_FILE;
-
-		output.type = BRASERO_TRACK_TYPE_IMAGE;
-		output.subtype.img_format = brasero_burn_session_get_output_format (session);
-	}
-	else {
-		media = brasero_burn_session_get_dest_media (session);
-
-		output.type = BRASERO_TRACK_TYPE_DISC;
-		output.subtype.media = media;
-	}
-
-	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
-		flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-	else
-		flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-
-	BRASERO_BURN_LOG_WITH_TYPE (&output,
-				    flags,
-				    "Creating recording/imaging task");
-
-	/* search the start caps and try to get a list of links */
-	last_caps = brasero_caps_find_start_caps (self, &output);
-	if (!last_caps)
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_WITH_TYPE (&input,
-				    BRASERO_PLUGIN_IO_NONE,
-				    "Input set =");
-
-	if (!brasero_burn_caps_flags_check_for_drive (session))
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session);
-
-	session_flags = brasero_burn_session_get_flags (session);
-	list = brasero_caps_find_best_link (last_caps,
-					    self->priv->group_id,
-					    NULL,
-					    session_flags,
-					    media,
-					    &input,
-					    flags);
-	if (!list) {
-		/* we reached this point in two cases:
-		 * - if the disc cannot be handled
-		 * - if some flags are not handled
-		 * It is helpful only if:
-		 * - the disc was closed and no plugin can handle this type of 
-		 * disc once closed (CD-R(W))
-		 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
-		 * handle this flag (means that the plugin should erase and
-		 * then write on its own. Basically that works only with
-		 * overwrite formatted discs, DVD+RW, ...) */
-		if (output.type != BRASERO_TRACK_TYPE_DISC)
-			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-
-		/* output is a disc try with initial blanking */
-		BRASERO_BURN_LOG ("failed to create proper task. Trying with initial blanking");
-
-		/* apparently nothing can be done to reach our goal. Maybe that
-		 * is because we first have to blank the disc. If so add a blank 
-		 * task to the others as a first step */
-		if (!(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
-		||    brasero_burn_session_can_blank (session) != BRASERO_BURN_OK)
-			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-
-		/* retry with the same disc type but blank this time */
-		media &= ~(BRASERO_MEDIUM_CLOSED|
-			   BRASERO_MEDIUM_APPENDABLE|
-	   		   BRASERO_MEDIUM_UNFORMATTED|
-			   BRASERO_MEDIUM_HAS_DATA|
-			   BRASERO_MEDIUM_HAS_AUDIO);
-		media |= BRASERO_MEDIUM_BLANK;
-
-		output.subtype.media = media;
-
-		last_caps = brasero_caps_find_start_caps (self, &output);
-		if (!last_caps)
-			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-
-		/* if the flag BLANK_BEFORE_WRITE was set then remove it since
-		 * we are actually blanking. Simply the record plugin won't have
-		 * to do it. */
-		session_flags &= ~BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
-		list = brasero_caps_find_best_link (last_caps,
-						    self->priv->group_id,
-						    NULL,
-						    session_flags,
-						    media,
-						    &input,
-						    flags);
-		if (!list)
-			BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-
-		BRASERO_BURN_LOG ("initial blank/erase task required")
-
-		blanking = brasero_burn_caps_new_blanking_task (self, session, error);
-		/* The problem here is that we shouldn't always prepend such a 
-		 * task. For example when we copy a disc to another using the 
-		 * same drive. In this case we should insert it before the last.
-		 * Now, that always work so that's what we do in all cases. Once
-		 * the whole list of tasks is created we insert this blanking
-		 * task just before the last one. Another advantage is that the
-		 * blanking of the disc is delayed as late as we can which means
-		 * in case of error we keep it intact as late as we can. */
-	}
-
-	/* reverse the list of links to have them in the right order */
-	list = g_slist_reverse (list);
-	position = BRASERO_PLUGIN_RUN_PREPROCESSING;
-	group_id = self->priv->group_id;
-
-	brasero_burn_session_get_input_type (session, &plugin_input);
-	for (iter = list; iter; iter = iter->next) {
-		BraseroTrackType plugin_output;
-		BraseroCapsLink *link;
-		BraseroPlugin *plugin;
-		BraseroJob *job;
-		GSList *result;
-		GType type;
-
-		link = iter->data;
-
-		/* determine the plugin output */
-		if (iter->next) {
-			BraseroCapsLink *next_link;
-
-			next_link = iter->next->data;
-			if (next_link == link) {
-				/* That's a processing plugin so the output must
-				 * be the exact same as the input, which is not
-				 * necessarily the caps type referred to by the 
-				 * link if the link is amongst the first. In
-				 * that case that's the session input. */
-				memcpy (&plugin_output,
-					&plugin_input,
-					sizeof (BraseroTrackType));
-			}
-			else {
-				memcpy (&plugin_output,
-					&next_link->caps->type,
-					sizeof (BraseroTrackType));
-			}
-		}
-		else
-			memcpy (&plugin_output,
-				&output,
-				sizeof (BraseroTrackType));
-
-		/* first see if there are track processing plugins */
-		result = brasero_caps_add_processing_plugins_to_task (session,
-								      task,
-								      link->caps,
-								      &plugin_input,
-								      position);
-		retval = g_slist_concat (retval, result);
-
-		/* create job from the best plugin in link */
-		plugin = brasero_caps_link_find_plugin (link,
-							group_id,
-							session_flags,
-							&plugin_output,
-							media);
-		if (!plugin) {
-			g_set_error (error,
-				     BRASERO_BURN_ERROR,
-				     BRASERO_BURN_ERROR_GENERAL,
-				     _("An internal error occured"));
-			g_slist_foreach (retval, (GFunc) g_object_unref, NULL);
-			g_slist_free (retval);
-			g_slist_free (list);
-			return NULL;
-		}
-
-		/* This is meant to have plugins in the same group id as much as
-		 * possible */
-		if (brasero_plugin_get_group (plugin) > 0 && group_id <= 0)
-			group_id = brasero_plugin_get_group (plugin);
-
-		type = brasero_plugin_get_gtype (plugin);
-		job = BRASERO_JOB (g_object_new (type,
-						 "output", &plugin_output,
-						 NULL));
-		g_signal_connect (job,
-				  "error",
-				  G_CALLBACK (brasero_burn_caps_job_error_cb),
-				  link);
-
-		if (!task
-		||  !(link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
-		||  !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
-			/* only the last task will be doing the proper action
-			 * all other are only steps to take to reach the final
-			 * action */
-			BRASERO_BURN_LOG ("New task");
-			task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
-							   "session", session,
-							   "action", BRASERO_TASK_ACTION_NORMAL,
-							   NULL));
-			retval = g_slist_append (retval, task);
-		}
-
-		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
-
-		BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (plugin));
-		BRASERO_BURN_LOG_TYPE (&plugin_input, "input");
-		BRASERO_BURN_LOG_TYPE (&plugin_output, "output");
-
-		position = BRASERO_PLUGIN_RUN_BEFORE_TARGET;
-
-		/* the output of the plugin will become the input of the next */
-		memcpy (&plugin_input, &plugin_output, sizeof (BraseroTrackType));
-	}
-	g_slist_free (list);
-
-	/* add the post processing plugins */
-	list = brasero_caps_add_processing_plugins_to_task (session,
-							    NULL,
-							    last_caps,
-							    &output,
-							    BRASERO_PLUGIN_RUN_AFTER_TARGET);
-	retval = g_slist_concat (retval, list);
-
-	if (last_caps->type.type == BRASERO_TRACK_TYPE_DISC && blanking) {
-		retval = g_slist_insert_before (retval,
-						g_slist_last (retval),
-						blanking);
-	}
-
-	return retval;
-}
-
-BraseroTask *
-brasero_burn_caps_new_checksuming_task (BraseroBurnCaps *self,
-					BraseroBurnSession *session,
-					GError **error)
-{
-	BraseroTrackType track_type;
-	BraseroPlugin *candidate;
-	BraseroCaps *last_caps;
-	BraseroTrackType input;
-	guint checksum_type;
-	BraseroTrack *track;
-	BraseroTask *task;
-	BraseroJob *job;
-	GSList *tracks;
-	GSList *links;
-	GSList *list;
-	GSList *iter;
-
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_WITH_TYPE (&input,
-				    BRASERO_PLUGIN_IO_NONE,
-				    "Creating checksuming task with input");
-
-	/* first find a checksuming job that can output the type of required
-	 * checksum. Then go through the caps to see if the input type can be
-	 * found. */
-
-	/* some checks */
-	tracks = brasero_burn_session_get_tracks (session);
-	if (g_slist_length (tracks) != 1) {
-		g_set_error (error,
-			     BRASERO_BURN_ERROR,
-			     BRASERO_BURN_ERROR_GENERAL,
-			     _("Only one track at a time can be checked"));
-		return NULL;
-	}
-
-	/* get the required checksum type */
-	track = tracks->data;
-	checksum_type = brasero_track_get_checksum_type (track);
-
-	links = NULL;
-	for (iter = self->priv->tests; iter; iter = iter->next) {
-		BraseroCapsTest *test;
-
-		test = iter->data;
-		if (!test->links)
-			continue;
-
-		/* check this caps test supports the right checksum type */
-		if (test->type & checksum_type) {
-			links = test->links;
-			break;
-		}
-	}
-
-	if (!links) {
-		/* we failed to find and create a proper task */
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-	}
-
-	list = NULL;
-	last_caps = NULL;
-	brasero_track_get_track_type (track, &track_type);
-	for (iter = links; iter; iter = iter->next) {
-		BraseroCapsLink *link;
-		GSList *plugins;
-
-		link = iter->data;
-
-		/* NOTE: that shouldn't happen */
-		if (!link->caps)
-			continue;
-
-		BRASERO_BURN_LOG_TYPE (&link->caps->type, "Trying link to");
-
-		/* Make sure we have a candidate */
-		candidate = NULL;
-		for (plugins = link->plugins; plugins; plugins = plugins->next) {
-			BraseroPlugin *plugin;
-
-			plugin = plugins->data;
-			if (!brasero_plugin_get_active (plugin))
-				continue;
-
-			/* note for checksuming task there is no group possible */
-			if (!candidate)
-				candidate = plugin;
-			else if (brasero_plugin_get_priority (plugin) >
-				 brasero_plugin_get_priority (candidate))
-				candidate = plugin;
-		}
-
-		if (!candidate)
-			continue;
-
-		/* see if it can handle the input or if it can be linked to 
-		 * another plugin that can */
-		if (brasero_caps_is_compatible_type (link->caps, &input)) {
-			/* this is the right caps */
-			last_caps = link->caps;
-			break;
-		}
-
-		/* don't go any further if that's a DISC type */
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		/* the caps itself is not the right one so we try to 
-		 * go through its links to find the right caps. */
-		list = brasero_caps_find_best_link (link->caps,
-						    self->priv->group_id,
-						    NULL,
-						    BRASERO_BURN_FLAG_NONE,
-						    BRASERO_MEDIUM_NONE,
-						    &input,
-						    BRASERO_PLUGIN_IO_ACCEPT_PIPE);
-		if (list) {
-			last_caps = link->caps;
-			break;
-		}
-	}
-
-	if (!last_caps) {
-		/* no link worked failure */
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
-	}
-
-	/* we made it. Create task */
-	task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
-					   "session", session,
-					   "action", BRASERO_TASK_ACTION_CHECKSUM,
-					   NULL));
-
-	list = g_slist_reverse (list);
-	for (iter = list; iter; iter = iter->next) {
-		GType type;
-		GSList *plugins;
-		BraseroCapsLink *link;
-		BraseroPlugin *candidate_plugin;
-		BraseroTrackType *plugin_output;
-
-		link = iter->data;
-
-		/* determine the plugin output */
-		if (iter->next) {
-			BraseroCapsLink *next_link;
-
-			next_link = iter->next->data;
-			plugin_output = &next_link->caps->type;
-		}
-		else
-			plugin_output = &last_caps->type;
-
-		/* find the best plugin */
-		candidate_plugin = NULL;
-		for (plugins = link->plugins; plugins; plugins = plugins->next) {
-			BraseroPlugin *plugin;
-
-			plugin = plugins->data;
-
-			if (!brasero_plugin_get_active (plugin))
-				continue;
-
-			if (!candidate_plugin)
-				candidate_plugin = plugin;
-			else if (brasero_plugin_get_priority (plugin) >
-				 brasero_plugin_get_priority (candidate_plugin))
-				candidate_plugin = plugin;
-		}
-
-		/* create the object */
-		type = brasero_plugin_get_gtype (candidate_plugin);
-		job = BRASERO_JOB (g_object_new (type,
-						 "output", plugin_output,
-						 NULL));
-		g_signal_connect (job,
-				  "error",
-				  G_CALLBACK (brasero_burn_caps_job_error_cb),
-				  link);
-
-		brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
-
-		BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (candidate_plugin));
-	}
-	g_slist_free (list);
-
-	/* Create the candidate */
-	job = BRASERO_JOB (g_object_new (brasero_plugin_get_gtype (candidate),
-					 "output", NULL,
-					 NULL));
-	g_signal_connect (job,
-			  "error",
-			  G_CALLBACK (brasero_burn_caps_job_error_cb),
-			  self);
-	brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
-
-	return task;
-}
-
-static gboolean
-brasero_caps_find_link (BraseroCaps *caps,
-			BraseroBurnFlag session_flags,
-			gboolean use_flags,
-			BraseroMedia media,
-			BraseroTrackType *input,
-			BraseroPluginIOFlag io_flags)
-{
-	GSList *iter;
-
-	BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_link");
-
-	/* Here we only make sure we have at least one link working. For a link
-	 * to be followed it must first:
-	 * - link to a caps with correct io flags
-	 * - have at least a plugin accepting the record flags if caps type is
-	 *   a disc (that means that the link is the recording part)
-	 *
-	 * and either:
-	 * - link to a caps equal to the input
-	 * - link to a caps (linking itself to another caps, ...) accepting the
-	 *   input
-	 */
-
-	for (iter = caps->links; iter; iter = iter->next) {
-		BraseroCapsLink *link;
-		gboolean result;
-
-		link = iter->data;
-
-		if (!link->caps)
-			continue;
-
-		/* check that the link has some active plugin */
-		if (!brasero_caps_link_active (link))
-			continue;
-
-		/* since this link contains recorders, check that at least one
-		 * of them can handle the record flags */
-		if (use_flags
-		&&  caps->type.type == BRASERO_TRACK_TYPE_DISC
-		&& !brasero_caps_link_check_record_flags (link, session_flags, media))
-			continue;
-
-		/* first see if that's the perfect fit:
-		 * - it must have the same caps (type + subtype)
-		 * - it must have the proper IO */
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
-			if (use_flags
-			&& !brasero_caps_link_check_data_flags (link, session_flags, media))
-				continue;
-		}
-		else if (!brasero_caps_link_check_media_restrictions (link, media))
-			continue;
-
-		if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
-		&&   brasero_caps_is_compatible_type (link->caps, input))
-			return TRUE;
-
-		/* we can't go further than a DISC type */
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE)
-			continue;
-
-		/* try to see where the inputs of this caps leads to */
-		result = brasero_caps_find_link (link->caps,
-						 session_flags,
-						 use_flags,
-						 media,
-						 input,
-						 io_flags);
-		if (result)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-brasero_caps_try_output (BraseroBurnCaps *self,
-			 BraseroBurnFlag session_flags,
-			 gboolean use_flags,
-			 BraseroTrackType *output,
-			 BraseroTrackType *input,
-			 BraseroPluginIOFlag flags)
-{
-	BraseroCaps *caps;
-	BraseroMedia media;
-
-	/* here we search the start caps */
-	caps = brasero_caps_find_start_caps (self, output);
-	if (!caps) {
-		BRASERO_BURN_LOG ("No caps available");
-		return FALSE;
-	}
-
-	if (output->type == BRASERO_TRACK_TYPE_DISC)
-		media = output->subtype.media;
-	else
-		media = BRASERO_MEDIUM_FILE;
-
-	return brasero_caps_find_link (caps,
-				       session_flags,
-				       use_flags,
-				       media,
-				       input,
-				       flags);
-}
-
-static gboolean
-brasero_caps_try_output_with_blanking (BraseroBurnCaps *self,
-				       BraseroBurnSession *session,
-				       BraseroTrackType *output,
-				       BraseroTrackType *input,
-				       BraseroPluginIOFlag io_flags,
-				       gboolean use_flags)
-{
-	gboolean result;
-	BraseroMedia media;
-	BraseroCaps *last_caps;
-	BraseroBurnFlag session_flags = BRASERO_BURN_FLAG_NONE;
-
-	if (use_flags)
-		session_flags = brasero_burn_session_get_flags (session);
-
-	result = brasero_caps_try_output (self,
-					  session_flags,
-					  use_flags,
-					  output,
-					  input,
-					  io_flags);
-	if (result)
-		return result;
-
-	/* we reached this point in two cases:
-	 * - if the disc cannot be handled
-	 * - if some flags are not handled
-	 * It is helpful only if:
-	 * - the disc was closed and no plugin can handle this type of 
-	 * disc once closed (CD-R(W))
-	 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
-	 * handle this flag (means that the plugin should erase and
-	 * then write on its own. Basically that works only with
-	 * overwrite formatted discs, DVD+RW, ...) */
-	if (output->type != BRASERO_TRACK_TYPE_DISC)
-		return FALSE;
-
-	/* output is a disc try with initial blanking */
-	BRASERO_BURN_LOG ("Support for input/output failed.");
-
-	/* apparently nothing can be done to reach our goal. Maybe that
-	 * is because we first have to blank the disc. If so add a blank 
-	 * task to the others as a first step */
-	if ((use_flags && !(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE))
-	||   brasero_burn_session_can_blank (session) != BRASERO_BURN_OK)
-		return FALSE;
-
-	BRASERO_BURN_LOG ("Trying with initial blanking");
-
-	/* retry with the same disc type but blank this time */
-	media = output->subtype.media;
-	media &= ~(BRASERO_MEDIUM_CLOSED|
-		   BRASERO_MEDIUM_APPENDABLE|
-		   BRASERO_MEDIUM_UNFORMATTED|
-		   BRASERO_MEDIUM_HAS_DATA|
-		   BRASERO_MEDIUM_HAS_AUDIO);
-	media |= BRASERO_MEDIUM_BLANK;
-	output->subtype.media = media;
-
-	last_caps = brasero_caps_find_start_caps (self, output);
-	if (!last_caps)
-		return FALSE;
-
-	return brasero_caps_find_link (last_caps,
-				       session_flags,
-				       use_flags,
-				       media,
-				       input,
-				       io_flags);
-}
-
-BraseroBurnResult
-brasero_burn_session_input_supported (BraseroBurnSession *session,
-				      BraseroTrackType *input,
-				      gboolean use_flags)
-{
-	gboolean result;
-	BraseroBurnCaps *self;
-	BraseroTrackType output;
-	BraseroPluginIOFlag io_flags;
-
-	self = brasero_burn_caps_get_default ();
-	if (use_flags && !brasero_burn_caps_flags_check_for_drive (session)) {
-		g_object_unref (self);
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
-	}
-
-	if (!brasero_burn_session_is_dest_file (session)) {
-		output.type = BRASERO_TRACK_TYPE_DISC;
-		output.subtype.media = brasero_burn_session_get_dest_media (session);
-
-		/* NOTE: for the special case where a disc could be rewritten
-		 * and cannot be handled as such but needs prior blanking, we
-		 * handle that situation in previous function.*/
-	}
-	else {
-		output.type = BRASERO_TRACK_TYPE_IMAGE;
-		output.subtype.img_format = brasero_burn_session_get_output_format (session);
-	}
-
-	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-	else
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-
-	BRASERO_BURN_LOG_TYPE (input, "Checking support for input");
-	BRASERO_BURN_LOG_TYPE (&output, "and output");
-
-	if (use_flags)
-		BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
-
-	result = brasero_caps_try_output_with_blanking (self,
-							session,
-							&output,
-							input,
-							io_flags,
-							use_flags);
-	g_object_unref (self);
-
-	if (!result) {
-		BRASERO_BURN_LOG_TYPE (input, "Input not supported");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	return BRASERO_BURN_OK;
-}
-
-BraseroBurnResult
-brasero_burn_session_output_supported (BraseroBurnSession *session,
-				       BraseroTrackType *output)
-{
-	gboolean result;
-	BraseroBurnCaps *self;
-	BraseroTrackType input;
-	BraseroPluginIOFlag io_flags;
-
-	self = brasero_burn_caps_get_default ();
-
-	/* Here, we can't check if the drive supports the flags since the output
-	 * is hypothetical. There is no real medium. So forget the following :
-	 * if (!brasero_burn_caps_flags_check_for_drive (session))
-	 *	BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
-	 * The only thing we could do would be to check some known forbidden 
-	 * flags for some media provided the output type is DISC. */
-
-	/* Here flags don't matter as we don't record anything. Even the IOFlags
-	 * since that can be checked later with brasero_burn_caps_get_flags. */
-	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-	else
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_TYPE (output, "Checking support for output");
-	BRASERO_BURN_LOG_TYPE (&input, "and input");
-	BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
-	
-	result = brasero_caps_try_output_with_blanking (self,
-							session,
-							output,
-							&input,
-							io_flags,
-							TRUE);
-
-	g_object_unref (self);
-
-	if (!result) {
-		BRASERO_BURN_LOG_TYPE (output, "Output not supported");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	return BRASERO_BURN_OK;
-}
-
-/**
- * This is only to be used in case one wants to copy using the same drive.
- * It determines the possible middle image type.
- */
-
-static BraseroBurnResult
-brasero_burn_caps_is_session_supported_same_src_dest (BraseroBurnCaps *self,
-						      BraseroBurnSession *session,
-						      gboolean use_flags)
-{
-	GSList *iter;
-	BraseroTrackType input;
-	BraseroTrackType output;
-	BraseroImageFormat format;
-	BraseroBurnFlag session_flags;
-
-	BRASERO_BURN_LOG ("Checking disc copy support with same source and destination");
-
-	/* To determine if a CD/DVD can be copied using the same source/dest,
-	 * we first determine if can be imaged and then if this image can be 
-	 * burnt to whatever medium type. */
-	memset (&input, 0, sizeof (BraseroTrackType));
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_TYPE (&input, "input");
-
-	if (use_flags) {
-		/* NOTE: DAO can be a problem. So just in case remove it. It is
-		 * not really useful in this context. What we want here is to
-		 * know whether a medium can be used given the input; only 1
-		 * flag is important here (MERGE) and can have consequences. */
-		session_flags = brasero_burn_session_get_flags (session);
-		session_flags &= ~BRASERO_BURN_FLAG_DAO;
-
-		BRASERO_BURN_LOG_FLAGS (session_flags, "flags");
-	}
-	else
-		session_flags = BRASERO_BURN_FLAG_NONE;
-
-	/* Find one available output format */
-	format = BRASERO_IMAGE_FORMAT_CDRDAO;
-	output.type = BRASERO_TRACK_TYPE_IMAGE;
-
-	for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
-		gboolean supported;
-
-		output.subtype.img_format = format;
-
-		BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
-		supported = brasero_caps_try_output_with_blanking (self,
-								   session,
-								   &output,
-								   &input,
-								   BRASERO_PLUGIN_IO_ACCEPT_FILE,
-								   use_flags);
-		if (!supported)
-			continue;
-
-		/* This format can be used to create an image. Check if can be
-		 * burnt now. Just find at least one medium. */
-		for (iter = self->priv->caps_list; iter; iter = iter->next) {
-			BraseroCaps *caps;
-			gboolean result;
-
-			caps = iter->data;
-
-			if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-				continue;
-
-			result = brasero_caps_find_link (caps,
-							 TRUE,
-							 session_flags,
-							 caps->type.subtype.media,
-							 &input,
-							 BRASERO_PLUGIN_IO_ACCEPT_FILE);
-
-			BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
-						    "Tested medium (%s)",
-						    result ? "working":"not working");
-
-			if (result)
-				return BRASERO_BURN_OK;
-		}
-	}
-
-	return BRASERO_BURN_NOT_SUPPORTED;
-}
-
-BraseroBurnResult
-brasero_burn_session_can_burn (BraseroBurnSession *session,
-			       gboolean use_flags)
-{
-	gboolean result;
-	BraseroBurnCaps *self;
-	BraseroTrackType input;
-	BraseroTrackType output;
-	BraseroPluginIOFlag io_flags;
-
-	self = brasero_burn_caps_get_default ();
-
-	/* Special case */
-	if (brasero_burn_session_same_src_dest_drive (session)) {
-		BraseroBurnResult result;
-
-		result = brasero_burn_caps_is_session_supported_same_src_dest (self, session, use_flags);
-		g_object_unref (self);
-		return result;
-	}
-
-	if (use_flags && !brasero_burn_caps_flags_check_for_drive (session)) {
-		g_object_unref (self);
-		BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
-	}
-
-	/* Here flags don't matter as we don't record anything.
-	 * Even the IOFlags since that can be checked later with
-	 * brasero_burn_caps_get_flags. */
-	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-	else
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-
-	brasero_burn_session_get_input_type (session, &input);
-
-	if (!brasero_burn_session_is_dest_file (session)) {
-		output.type = BRASERO_TRACK_TYPE_DISC;
-		output.subtype.media = brasero_burn_session_get_dest_media (session);
-
-		/* NOTE: for the special case where a disc could be rewritten
-		 * and cannot be handled as such but needs prior blanking, we
-		 * handle that situation in previous function.*/
-	}
-	else {
-		output.type = BRASERO_TRACK_TYPE_IMAGE;
-		output.subtype.img_format = brasero_burn_session_get_output_format (session);
-	}
-
-	BRASERO_BURN_LOG_TYPE (&output, "Checking support for session output");
-	BRASERO_BURN_LOG_TYPE (&input, "and input");
-
-	if (use_flags)
-		BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
-
-	result = brasero_caps_try_output_with_blanking (self,
-							session,
-							&output,
-							&input,
-							io_flags,
-							use_flags);
-
-	g_object_unref (self);
-
-	if (!result) {
-		BRASERO_BURN_LOG_TYPE (&output, "Output not supported");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	return BRASERO_BURN_OK;
-}
-
-BraseroMedia
-brasero_burn_session_get_required_media_type (BraseroBurnSession *session)
-{
-	BraseroMedia required_media = BRASERO_MEDIUM_NONE;
-	BraseroBurnFlag session_flags;
-	BraseroPluginIOFlag io_flags;
-	BraseroTrackType input;
-	BraseroBurnCaps *self;
-	GSList *iter;
-
-	if (brasero_burn_session_is_dest_file (session))
-		return BRASERO_MEDIUM_FILE;
-
-	self = brasero_burn_caps_get_default ();
-
-	/* we try to determine here what type of medium is allowed to be burnt
-	 * to whether a CD or a DVD. Appendable, blank are not properties being
-	 * determined here. We just want it to be writable in a broad sense. */
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_TYPE (&input, "Determining required media type for input");
-
-	/* NOTE: BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE is a problem here since it
-	 * is only used if needed. Likewise DAO can be a problem. So just in
-	 * case remove them. They are not really useful in this context. What we
-	 * want here is to know which media can be used given the input; only 1
-	 * flag is important here (MERGE) and can have consequences. */
-	session_flags = brasero_burn_session_get_flags (session);
-	session_flags &= ~BRASERO_BURN_FLAG_DAO;
-
-	BRASERO_BURN_LOG_FLAGS (session_flags, "and flags");
-
-	if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-	else
-		io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		gboolean result;
-
-		caps = iter->data;
-
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		/* Put BRASERO_MEDIUM_NONE so we can always succeed */
-		result = brasero_caps_find_link (caps,
-						 session_flags,
-						 TRUE,
-						 BRASERO_MEDIUM_NONE,
-						 &input,
-						 io_flags);
-
-		BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
-					    "Tested (%s)",
-					    result ? "working":"not working");
-
-		if (!result)
-			continue;
-
-		/* This caps work, add its subtype */
-		required_media |= caps->type.subtype.media;
-	}
-
-	/* filter as we are only interested in these */
-	required_media &= BRASERO_MEDIUM_WRITABLE|
-			  BRASERO_MEDIUM_CD|
-			  BRASERO_MEDIUM_DVD;
-
-	g_object_unref (self);
-	return required_media;
-}
-
-BraseroImageFormat
-brasero_burn_session_get_default_output_format (BraseroBurnSession *session)
-{
-	BraseroBurnCaps *self;
-	BraseroTrackType source;
-	BraseroTrackType output;
-	BraseroBurnResult result;
-
-	self = brasero_burn_caps_get_default ();
-
-	if (!brasero_burn_session_is_dest_file (session)) {
-		g_object_unref (self);
-		return BRASERO_IMAGE_FORMAT_NONE;
-	}
-
-	brasero_burn_session_get_input_type (session, &source);
-	if (source.type == BRASERO_TRACK_TYPE_NONE) {
-		g_object_unref (self);
-		return BRASERO_IMAGE_FORMAT_NONE;
-	}
-
-	if (source.type == BRASERO_TRACK_TYPE_IMAGE) {
-		g_object_unref (self);
-		return source.subtype.img_format;
-	}
-
-	output.type = BRASERO_TRACK_TYPE_IMAGE;
-	output.subtype.img_format = BRASERO_IMAGE_FORMAT_NONE;
-
-	if (source.type == BRASERO_TRACK_TYPE_STREAM) {
-		/* If that's AUDIO only without VIDEO then return */
-		if (!(source.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD))) {
-			g_object_unref (self);
-			return BRASERO_IMAGE_FORMAT_NONE;
-		}
-
-		/* Otherwise try all possible image types */
-		output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
-		for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
-		       output.subtype.img_format >>= 1) {
-		
-			result = brasero_burn_session_output_supported (session,
-									&output);
-			if (result == BRASERO_BURN_OK) {
-				g_object_unref (self);
-				return output.subtype.img_format;
-			}
-		}
-
-		g_object_unref (self);
-		return BRASERO_IMAGE_FORMAT_NONE;
-	}
-
-	if (source.type == BRASERO_TRACK_TYPE_DATA
-	|| (source.type == BRASERO_TRACK_TYPE_DISC
-	&& (source.subtype.media & BRASERO_MEDIUM_DVD))) {
-		output.subtype.img_format = BRASERO_IMAGE_FORMAT_BIN;
-		result = brasero_burn_session_output_supported (session,
-								&output);
-
-		g_object_unref (self);
-
-		if (result != BRASERO_BURN_OK)
-			return BRASERO_IMAGE_FORMAT_NONE;
-
-		return BRASERO_IMAGE_FORMAT_BIN;
-	}
-
-	/* for the input which are CDs there are lots of possible formats */
-	output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
-	for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
-	       output.subtype.img_format >>= 1) {
-	
-		result = brasero_burn_session_output_supported (session,
-								&output);
-		if (result == BRASERO_BURN_OK) {
-			g_object_unref (self);
-			return output.subtype.img_format;
-		}
-	}
-
-	g_object_unref (self);
-	return BRASERO_IMAGE_FORMAT_NONE;
-}
-
-static BraseroCapsLink *
-brasero_caps_find_link_for_input (BraseroCaps *caps,
-				  BraseroCaps *input)
-{
-	GSList *links;
-
-	for (links = caps->links; links; links = links->next) {
-		BraseroCapsLink *link;
-
-		link = links->data;
-		if (link->caps == input)
-			return link;
-	}
-
-	return NULL;
-}
-
-static gboolean
-brasero_caps_has_active_input (BraseroCaps *caps,
-			       BraseroCaps *input)
-{
-	GSList *links;
-
-	for (links = caps->links; links; links = links->next) {
-		BraseroCapsLink *link;
-
-		link = links->data;
-		if (link->caps != input)
-			continue;
-
-		if (brasero_caps_link_active (link))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-brasero_burn_caps_is_input (BraseroBurnCaps *self,
-			    BraseroCaps *input)
-{
-	GSList *iter;
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *tmp;
-
-		tmp = iter->data;
-		if (tmp == input)
-			continue;
-
-		if (brasero_caps_has_active_input (tmp, input))
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-static BraseroPluginIOFlag
-brasero_caps_get_flags (BraseroCaps *caps,
-			BraseroBurnFlag session_flags,
-			BraseroMedia media,
-			BraseroTrackType *input,
-			BraseroPluginIOFlag flags,
-			BraseroBurnFlag *supported,
-			BraseroBurnFlag *compulsory)
-{
-	GSList *iter;
-	BraseroPluginIOFlag retval = BRASERO_PLUGIN_IO_NONE;
-
-	/* First we must know if this link leads somewhere. It must 
-	 * accept the already existing flags. If it does, see if it 
-	 * accepts the input and if not, if one of its ancestors does */
-	for (iter = caps->links; iter; iter = iter->next) {
-		BraseroBurnFlag data_supported = BRASERO_BURN_FLAG_NONE;
-		BraseroBurnFlag rec_compulsory = BRASERO_BURN_FLAG_ALL;
-		BraseroBurnFlag rec_supported = BRASERO_BURN_FLAG_NONE;
-		BraseroPluginIOFlag io_flags;
-		BraseroCapsLink *link;
-
-		link = iter->data;
-
-		if (!link->caps)
-			continue;
-
-		/* check that the link has some active plugin */
-		if (!brasero_caps_link_active (link))
-			continue;
-
-		if (caps->type.type == BRASERO_TRACK_TYPE_DISC) {
-			BraseroBurnFlag tmp;
-
-			brasero_caps_link_get_record_flags (link,
-							    media,
-							    session_flags,
-							    &rec_supported,
-							    &rec_compulsory);
-
-			/* see if that link can handle the record flags.
-			 * NOTE: compulsory are not a failure in this case. */
-			tmp = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
-			if ((tmp & rec_supported) != tmp)
-				continue;
-		}
-
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
-			BraseroBurnFlag tmp;
-
-			brasero_caps_link_get_data_flags (link,
-							  media,
-							  session_flags,
-						    	  &data_supported);
-
-			/* see if that link can handle the data flags. 
-			 * NOTE: compulsory are not a failure in this case. */
-			tmp = session_flags & (BRASERO_BURN_FLAG_APPEND|
-					       BRASERO_BURN_FLAG_MERGE);
-
-			if ((tmp & data_supported) != tmp)
-				continue;
-		}
-		else if (!brasero_caps_link_check_media_restrictions (link, media))
-			continue;
-
-		/* see if that's the perfect fit */
-		if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
-		&&   brasero_caps_is_compatible_type (link->caps, input)) {
-			/* special case for input that handle output/input */
-			if (caps->type.type == BRASERO_TRACK_TYPE_DISC)
-				retval |= BRASERO_PLUGIN_IO_ACCEPT_PIPE;
-			else
-				retval |= caps->flags;
-
-			(*compulsory) &= rec_compulsory;
-			(*supported) |= data_supported|rec_supported;
-			continue;
-		}
-
-		if ((link->caps->flags & flags) == BRASERO_PLUGIN_IO_NONE)
-			continue;
-
-		/* we can't go further than a DISC type */
-		if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		/* try to see where the inputs of this caps leads to */
-		io_flags = brasero_caps_get_flags (link->caps,
-						   session_flags,
-						   media,
-						   input,
-						   flags,
-						   supported,
-						   compulsory);
-		if (io_flags == BRASERO_PLUGIN_IO_NONE)
-			continue;
-
-		retval |= (io_flags & flags);
-		(*compulsory) &= rec_compulsory;
-		(*supported) |= data_supported|rec_supported;
-	}
-
-	return retval;
-}
-
-static BraseroBurnFlag
-brasero_medium_supported_flags (BraseroMedium *medium,
-				BraseroBurnFlag flags)
-{
-	BraseroMedia media;
-
-	media = brasero_medium_get_status (medium);
-
-	/* This is always FALSE */
-	if (media & BRASERO_MEDIUM_PLUS)
-		flags &= ~BRASERO_BURN_FLAG_DUMMY;
-
-	/* Simulation is only possible according to write modes. This mode is
-	 * mostly used by cdrecord/wodim for CLONE images. */
-	else if (media & BRASERO_MEDIUM_DVD) {
-		if (!brasero_medium_can_use_dummy_for_sao (medium))
-			flags &= ~BRASERO_BURN_FLAG_DUMMY;
-	}
-	else if (flags & BRASERO_BURN_FLAG_DAO) {
-		if (!brasero_medium_can_use_dummy_for_sao (medium))
-			flags &= ~BRASERO_BURN_FLAG_DUMMY;
-	}
-	else if (!brasero_medium_can_use_dummy_for_tao (medium))
-		flags &= ~BRASERO_BURN_FLAG_DUMMY;
-
-	if (!brasero_medium_can_use_burnfree (medium))
-		flags &= ~BRASERO_BURN_FLAG_BURNPROOF;
-
-	return flags;
-}
-
-static BraseroBurnFlag
-brasero_burn_caps_flags_update_for_drive (BraseroBurnFlag flags,
-					  BraseroBurnSession *session)
-{
-	BraseroDrive *drive;
-	BraseroMedium *medium;
-
-	drive = brasero_burn_session_get_burner (session);
-	if (!drive)
-		return flags;
-
-	medium = brasero_drive_get_medium (drive);
-	if (!medium)
-		return TRUE;
-
-	return brasero_medium_supported_flags (medium, flags);
-}
-
-static BraseroBurnResult
-brasero_caps_get_flags_for_disc (BraseroBurnCaps *self,
-				 BraseroBurnFlag session_flags,
-				 BraseroMedia media,
-				 BraseroTrackType *input,
-				 BraseroBurnFlag *supported,
-				 BraseroBurnFlag *compulsory)
-{
-	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
-	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
-	BraseroPluginIOFlag io_flags;
-	BraseroTrackType output;
-	BraseroCaps *caps;
-
-	/* create the output to find first caps */
-	output.type = BRASERO_TRACK_TYPE_DISC;
-	output.subtype.media = media;
-
-	caps = brasero_caps_find_start_caps (self, &output);
-	if (!caps) {
-		BRASERO_BURN_LOG_DISC_TYPE (media, "FLAGS: no caps could be found for");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-				    caps->flags,
-				    "FLAGS: trying caps");
-
-	io_flags = brasero_caps_get_flags (caps,
-					   session_flags,
-					   media,
-					   input,
-					   BRASERO_PLUGIN_IO_ACCEPT_FILE|
-					   BRASERO_PLUGIN_IO_ACCEPT_PIPE,
-					   &supported_flags,
-					   &compulsory_flags);
-
-	if (io_flags == BRASERO_PLUGIN_IO_NONE) {
-		BRASERO_BURN_LOG ("FLAGS: not supported");
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-
-	/* RAW write mode should (must) only be used in this case */
-	if ((supported_flags & BRASERO_BURN_FLAG_RAW)
-	&&   input->type == BRASERO_TRACK_TYPE_IMAGE
-	&&   input->subtype.img_format == BRASERO_IMAGE_FORMAT_CLONE) {
-		supported_flags &= ~BRASERO_BURN_FLAG_DAO;
-		compulsory_flags &= ~BRASERO_BURN_FLAG_DAO;
-		compulsory_flags |= BRASERO_BURN_FLAG_RAW;
-	}
-	else
-		supported_flags &= ~BRASERO_BURN_FLAG_RAW;
-
-	if ((supported_flags & BRASERO_BURN_FLAG_DAO)
-	&&   input->type == BRASERO_TRACK_TYPE_STREAM
-	&&  (input->subtype.img_format & BRASERO_METADATA_INFO)) {
-		/* In this case, DAO is compulsory if we want to write CD-TEXT */
-		compulsory_flags |= BRASERO_BURN_FLAG_DAO;
-	}
-
-	if (io_flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE) {
-		supported_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
-
-		if ((io_flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) == 0)
-			compulsory_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
-	}
-
-	*supported |= supported_flags;
-	*compulsory |= compulsory_flags;
-
-	return BRASERO_BURN_OK;
-}
-
-static BraseroBurnResult
-brasero_burn_caps_get_flags_for_medium (BraseroBurnCaps *self,
-					BraseroMedia media,
-					BraseroBurnFlag session_flags,
-					BraseroTrackType *input,
-					BraseroBurnFlag *supported_flags,
-					BraseroBurnFlag *compulsory_flags)
-{
-	BraseroBurnResult result;
-
-	/* See if medium is supported out of the box */
-	result = brasero_caps_get_flags_for_disc (self,
-						  session_flags,
-						  media,
-						  input,
-						  supported_flags,
-						  compulsory_flags);
-
-	/* see if we can add BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE. Add it when:
-	 * - media can be blanked, it has audio or data and we're not merging
-	 * - media is not formatted and it can be blanked/formatted */
-	if (BRASERO_BURN_CAPS_SHOULD_BLANK (media, session_flags)
-	&&  brasero_burn_caps_can_blank_real (self, media, session_flags) == BRASERO_BURN_OK)
-		(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
-	else if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
-		return BRASERO_BURN_NOT_SUPPORTED;
-
-	if (((*supported_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
-		BraseroBurnFlag blank_compulsory = BRASERO_BURN_FLAG_NONE;
-		BraseroBurnFlag blank_supported = BRASERO_BURN_FLAG_NONE;
-
-		/* If BLANK flag is supported then MERGE/APPEND can't be compulsory */
-		(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
-
-		/* we reached this point in two cases:
-		 * - if the disc cannot be handled
-		 * - if some flags are not handled
-		 * It is helpful only if:
-		 * - the disc was closed and no plugin can handle this type of 
-		 * disc once closed (CD-R(W))
-		 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
-		 * handle this flag (means that the plugin should erase and
-		 * then write on its own. Basically that works only with
-		 * overwrite formatted discs, DVD+RW, ...) */
-
-		/* What's above is not entirely true. In fact we always need to
-		 * check even if we first succeeded. There are some cases like
-		 * CDRW where it's useful.
-		 * Ex: a CDRW with data appendable can be either appended (then
-		 * no DAO possible) or blanked and written (DAO possible). */
-
-		(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
-
-		/* result here is the result of the first operation, so if it
-		 * failed, BLANK before becomes compulsory. */
-		if (result != BRASERO_BURN_OK)
-			(*compulsory_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
-
-		/* pretends it is blank and formatted to see if it would work.
-		 * If it works then that means that the BLANK_BEFORE_WRITE flag
-		 * is compulsory. */
-		media &= ~(BRASERO_MEDIUM_CLOSED|
-			   BRASERO_MEDIUM_APPENDABLE|
-			   BRASERO_MEDIUM_UNFORMATTED|
-			   BRASERO_MEDIUM_HAS_DATA|
-			   BRASERO_MEDIUM_HAS_AUDIO);
-		media |= BRASERO_MEDIUM_BLANK;
-		result = brasero_caps_get_flags_for_disc (self,
-							  session_flags,
-							  media,
-							  input,
-							  supported_flags,
-							  compulsory_flags);
-
-		/* if both attempts failed, drop it */
-		if (result != BRASERO_BURN_OK
-		&& (((*compulsory_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)))
-			return result;
-
-		/* need to add blanking flags */
-		brasero_burn_caps_get_blanking_flags_real (self,
-							   media,
-							   session_flags,
-							   &blank_supported,
-							   &blank_compulsory);
-		(*supported_flags) |= blank_supported;
-		(*compulsory_flags) |= blank_compulsory;
-	}
-	else if (result != BRASERO_BURN_OK)
-		return result;
-
-	if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) {
-		/* make sure we remove MERGE/APPEND from supported and
-		 * compulsory since that's not possible anymore */
-		(*supported_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
-		(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
-	}
-
-	/* FIXME! we should restart the whole process if
-	 * ((session_flags & compulsory_flags) != compulsory_flags) since that
-	 * means that some supported files could be excluded but were not */
-
-	return BRASERO_BURN_OK;
-}
-
-static BraseroBurnResult
-brasero_burn_caps_get_flags_same_src_dest (BraseroBurnCaps *self,
-					   BraseroBurnSession *session,
-					   BraseroBurnFlag *supported_ret,
-					   BraseroBurnFlag *compulsory_ret)
-{
-	GSList *iter;
-	gboolean copy_supported;
-	BraseroTrackType input;
-	BraseroTrackType output;
-	BraseroImageFormat format;
-	BraseroBurnFlag session_flags;
-	BraseroBurnFlag supported_final = BRASERO_BURN_FLAG_NONE;
-	BraseroBurnFlag compulsory_final = BRASERO_BURN_FLAG_ALL;
-
-	BRASERO_BURN_LOG ("Retrieving disc copy flags with same source and destination");
-
-	/* To determine if a CD/DVD can be copied using the same source/dest,
-	 * we first determine if can be imaged and then what are the flags when
-	 * we can burn it to a particular medium type. */
-	memset (&input, 0, sizeof (BraseroTrackType));
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_TYPE (&input, "input");
-
-	session_flags = brasero_burn_session_get_flags (session);
-	BRASERO_BURN_LOG_FLAGS (session_flags, "(FLAGS) Session flags");
-
-	/* Check the current flags are possible */
-	if (session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_NO_TMP_FILES))
-		return BRASERO_BURN_NOT_SUPPORTED;
-
-	/* Check flags for all available format */
-	format = BRASERO_IMAGE_FORMAT_CDRDAO;
-	output.type = BRASERO_TRACK_TYPE_IMAGE;
-
-	copy_supported = FALSE;
-	for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
-		BraseroBurnResult result;
-		gboolean format_supported;
-
-		/* check this image type is possible given the current flags */
-		if (format != BRASERO_IMAGE_FORMAT_CLONE
-		&& (session_flags & BRASERO_BURN_FLAG_RAW))
-			continue;
-
-		output.subtype.img_format = format;
-
-		/* NOTE: there is no need to get the flags here since there are
-		 * no specific DISC => IMAGE flags. We just want to know if that
-		 * is possible. */
-		BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
-		format_supported = brasero_caps_try_output_with_blanking (self,
-									  session,
-									  &output,
-									  &input,
-									  BRASERO_PLUGIN_IO_ACCEPT_FILE,
-									  FALSE);
-		if (!format_supported) {
-			BRASERO_BURN_LOG_TYPE (&output, "Format not supported");
-			continue;
-		}
-
-		/* This format can be used to create an image. Check if can be
-		 * burnt now. Just find at least one medium. */
-		format_supported = FALSE;
-		for (iter = self->priv->caps_list; iter; iter = iter->next) {
-			BraseroBurnFlag compulsory;
-			BraseroBurnFlag supported;
-			BraseroCaps *caps;
-
-			caps = iter->data;
-			if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-				continue;
-
-			/* Merge all available flags for each possible medium type */
-			supported = BRASERO_BURN_FLAG_NONE;
-			compulsory = BRASERO_BURN_FLAG_NONE;
-			result = brasero_burn_caps_get_flags_for_medium (self,
-									 caps->type.subtype.media,
-									 session_flags,
-									 &output,
-									 &supported,
-									 &compulsory);
-			if (result != BRASERO_BURN_OK)
-				continue;
-
-			format_supported = TRUE;
-			supported_final |= supported;
-			compulsory_final &= compulsory;
-		}
-
-		BRASERO_BURN_LOG_TYPE (&output, "Format supported %i", format_supported);
-		if (format_supported)
-			copy_supported = TRUE;
-	}
-
-	if (!copy_supported)
-		return BRASERO_BURN_NOT_SUPPORTED;
-
-	*supported_ret |= supported_final;
-	*compulsory_ret |= compulsory_final;
-	
-	return BRASERO_BURN_OK;
-}
-
-BraseroBurnResult
-brasero_burn_session_get_burn_flags (BraseroBurnSession *session,
-				     BraseroBurnFlag *supported,
-				     BraseroBurnFlag *compulsory)
-{
-	BraseroMedia media;
-	BraseroBurnCaps *self;
-	BraseroTrackType input;
-	BraseroBurnResult result;
-
-	BraseroBurnFlag session_flags;
-	/* FIXME: what's the meaning of NOGRACE when outputting ? */
-	BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_NONE;
-	BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_DONT_OVERWRITE|
-					  BRASERO_BURN_FLAG_CHECK_SIZE|
-					  BRASERO_BURN_FLAG_NOGRACE;
-
-	self = brasero_burn_caps_get_default ();
-
-	brasero_burn_session_get_input_type (session, &input);
-	BRASERO_BURN_LOG_WITH_TYPE (&input,
-				    BRASERO_PLUGIN_IO_NONE,
-				    "FLAGS: searching available flags for input");
-
-	if (brasero_burn_session_is_dest_file (session)) {
-		BRASERO_BURN_LOG ("FLAGS: image required");
-
-		/* In this case no APPEND/MERGE is possible */
-		if (input.type == BRASERO_TRACK_TYPE_DISC)
-			supported_flags |= BRASERO_BURN_FLAG_EJECT;
-
-		*supported = supported_flags;
-		*compulsory = compulsory_flags;
-
-		BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
-		BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
-
-		g_object_unref (self);
-		return BRASERO_BURN_OK;
-	}
-
-	supported_flags |= BRASERO_BURN_FLAG_EJECT;
-
-	/* special case */
-	if (brasero_burn_session_same_src_dest_drive (session)) {
-		result = brasero_burn_caps_get_flags_same_src_dest (self,
-								    session,
-								    &supported_flags,
-								    &compulsory_flags);
-
-		/* These flags are of course never possible */
-		supported_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
-				     BRASERO_BURN_FLAG_MERGE);
-		compulsory_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
-				      BRASERO_BURN_FLAG_MERGE);
-
-		if (result == BRASERO_BURN_OK) {
-			BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
-			BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
-
-			*supported = supported_flags;
-			*compulsory = compulsory_flags;
-		}
-		else
-			BRASERO_BURN_LOG ("No available flags for copy");
-
-		g_object_unref (self);
-		return result;
-	}
-
-	session_flags = brasero_burn_session_get_flags (session);
-	BRASERO_BURN_LOG_FLAGS (session_flags, "FLAGS (session):");
-
-	/* sanity check:
-	 * - drive must support flags
-	 * - MERGE and BLANK are not possible together.
-	 * - APPEND and MERGE are compatible. MERGE wins
-	 * - APPEND and BLANK are incompatible */
-	if (!brasero_burn_caps_flags_check_for_drive (session)) {
-		BRASERO_BURN_LOG ("Session flags not supported by drive");
-		g_object_unref (self);
-		return BRASERO_BURN_ERR;
-	}
-
-	if ((session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
-	&&  (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
-		g_object_unref (self);
-		return BRASERO_BURN_NOT_SUPPORTED;
-	}
-	
-	/* Let's get flags for recording */
-	media = brasero_burn_session_get_dest_media (session);
-	result = brasero_burn_caps_get_flags_for_medium (self,
-							 media,
-							 session_flags,
-							 &input,
-							 &supported_flags,
-							 &compulsory_flags);
-
-	g_object_unref (self);
-
-	if (result != BRASERO_BURN_OK)
-		return result;
-
-	supported_flags = brasero_burn_caps_flags_update_for_drive (supported_flags,
-								    session);
-
-	if (supported)
-		*supported = supported_flags;
-
-	if (compulsory)
-		*compulsory = compulsory_flags;
-
-	BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
-	BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
-	return BRASERO_BURN_OK;
-}
-
-/**
- * the following functions are used to register new caps
- */
-
-static gint
-brasero_burn_caps_sort (gconstpointer a, gconstpointer b)
-{
-	const BraseroCaps *caps_a = a;
-	const BraseroCaps *caps_b = b;
-	gint result;
-
-	/* First put DISC (the most used caps) then IMAGE type; these two types
-	 * are the ones that most often searched. At the end of the list we put
-	 * DATA  and AUDIO.
-	 * Another (sub)rule is that for DATA, DISC, AUDIO we put a caps that is
-	 * encompassed by another before.
-	 */
-
-	result = caps_b->type.type - caps_a->type.type;
-	if (result)
-		return result;
-
-	switch (caps_a->type.type) {
-	case BRASERO_TRACK_TYPE_DISC:
-		if (BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) !=
-		    BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media))
-			return ((gint32) BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) -
-			        (gint32) BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media));
-
-		if ((caps_a->type.subtype.media & BRASERO_MEDIUM_DVD)
-		&&  BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) !=
-		    BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media))			
-			return ((gint32) BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) -
-			        (gint32) BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media));
-
-		if (BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) !=
-		    BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media))
-			return BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) -
-			       BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media);
-
-		if (BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) !=
-		    BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media))
-			return BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) -
-			       BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media);
-
-		return (BRASERO_MEDIUM_INFO (caps_a->type.subtype.media) -
-			BRASERO_MEDIUM_INFO (caps_b->type.subtype.media));
-
-	case BRASERO_TRACK_TYPE_IMAGE:
-		/* This way BIN subtype is always sorted at the end */
-		return caps_a->type.subtype.img_format - caps_b->type.subtype.img_format;
-
-	case BRASERO_TRACK_TYPE_STREAM:
-		if (caps_a->type.subtype.audio_format != caps_b->type.subtype.audio_format) {
-			result = (caps_a->type.subtype.audio_format & caps_b->type.subtype.audio_format);
-			if (result == caps_a->type.subtype.audio_format)
-				return -1;
-			else if (result == caps_b->type.subtype.audio_format)
-				return 1;
-
-			return  (gint32) caps_a->type.subtype.audio_format -
-				(gint32) caps_b->type.subtype.audio_format;
-		}
-		break;
-
-	case BRASERO_TRACK_TYPE_DATA:
-		result = (caps_a->type.subtype.fs_type & caps_b->type.subtype.fs_type);
-		if (result == caps_a->type.subtype.fs_type)
-			return -1;
-		else if (result == caps_b->type.subtype.fs_type)
-			return 1;
-
-		return (caps_a->type.subtype.fs_type - caps_b->type.subtype.fs_type);
-
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static BraseroCapsLink *
-brasero_caps_link_copy (BraseroCapsLink *link)
-{
-	BraseroCapsLink *retval;
-
-	retval = g_new0 (BraseroCapsLink, 1);
-	retval->plugins = g_slist_copy (link->plugins);
-	retval->caps = link->caps;
-
-	return retval;
-}
-
-static void
-brasero_caps_link_list_duplicate (BraseroCaps *dest, BraseroCaps *src)
-{
-	GSList *iter;
-
-	for (iter = src->links; iter; iter = iter->next) {
-		BraseroCapsLink *link;
-
-		link = iter->data;
-		dest->links = g_slist_prepend (dest->links, brasero_caps_link_copy (link));
-	}
-}
-
-static BraseroCaps *
-brasero_caps_duplicate (BraseroCaps *caps)
-{
-	BraseroCaps *retval;
-
-	retval = g_new0 (BraseroCaps, 1);
-	retval->flags = caps->flags;
-	memcpy (&retval->type, &caps->type, sizeof (BraseroTrackType));
-	retval->modifiers = g_slist_copy (caps->modifiers);
-
-	return retval;
-}
-
-static void
-brasero_caps_replicate_modifiers (BraseroCaps *dest, BraseroCaps *src)
-{
-	GSList *iter;
-
-	for (iter = src->modifiers; iter; iter = iter->next) {
-		BraseroPlugin *plugin;
-
-		plugin = iter->data;
-
-		if (g_slist_find (dest->modifiers, plugin))
-			continue;
-
-		dest->modifiers = g_slist_prepend (dest->modifiers, plugin);
-	}
-}
-
-static void
-brasero_caps_replicate_links (BraseroBurnCaps *self,
-			      BraseroCaps *dest,
-			      BraseroCaps *src)
-{
-	GSList *iter;
-
-	brasero_caps_link_list_duplicate (dest, src);
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *iter_caps;
-		GSList *links;
-
-		iter_caps = iter->data;
-		if (iter_caps == src)
-			continue;
-
-		for (links = iter_caps->links; links; links = links->next) {
-			BraseroCapsLink *link;
-
-			link = links->data;
-			if (link->caps == src) {
-				BraseroCapsLink *copy;
-
-				copy = brasero_caps_link_copy (link);
-				copy->caps = dest;
-				iter_caps->links = g_slist_prepend (iter_caps->links, copy);
-			}
-		}
-	}
-}
-
-static void
-brasero_caps_replicate_tests (BraseroBurnCaps *self,
-			      BraseroCaps *dest,
-			      BraseroCaps *src)
-{
-	GSList *iter;
-
-	for (iter = self->priv->tests; iter; iter = iter->next) {
-		BraseroCapsTest *test;
-		GSList *links;
-
-		test = iter->data;
-		for (links = test->links; links; links = links->next) {
-			BraseroCapsLink *link;
-
-			link = links->data;
-			if (link->caps == src) {
-				BraseroCapsLink *copy;
-
-				copy = brasero_caps_link_copy (link);
-				copy->caps = dest;
-				test->links = g_slist_prepend (test->links, copy);
-			}
-		}
-	}
-}
-
-static void
-brasero_caps_copy_deep (BraseroBurnCaps *self,
-			BraseroCaps *dest,
-			BraseroCaps *src)
-{
-	brasero_caps_replicate_links (self, dest, src);
-	brasero_caps_replicate_tests (self, dest, src);
-	brasero_caps_replicate_modifiers (dest,src);
-}
-
-static BraseroCaps *
-brasero_caps_duplicate_deep (BraseroBurnCaps *self,
-			     BraseroCaps *caps)
-{
-	BraseroCaps *retval;
-
-	retval = brasero_caps_duplicate (caps);
-	brasero_caps_copy_deep (self, retval, caps);
-	return retval;
-}
-
-static GSList *
-brasero_caps_list_check_io (BraseroBurnCaps *self,
-			    GSList *list,
-			    BraseroPluginIOFlag flags)
-{
-	GSList *iter;
-
-	/* in this function we create the caps with the missing IO. All in the
-	 * list have something in common with flags. */
-	for (iter = list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		BraseroPluginIOFlag common;
-
-		caps = iter->data;
-		common = caps->flags & flags;
-		if (common != caps->flags) {
-			BraseroCaps *new_caps;
-
-			/* (common == flags) && common != caps->flags
-			 * caps->flags encompasses flags: Split the caps in two
-			 * and only keep the interesting part */
-			caps->flags &= ~common;
-
-			/* this caps has changed and needs to be sorted again */
-			self->priv->caps_list = g_slist_sort (self->priv->caps_list,
-							      brasero_burn_caps_sort);
-
-			new_caps = brasero_caps_duplicate_deep (self, caps);
-			new_caps->flags = common;
-
-			self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-								       new_caps,
-								       brasero_burn_caps_sort);
-
-			list = g_slist_prepend (list, new_caps);
-		}
-		else if (common != flags) {
-			GSList *node, *next;
-			BraseroPluginIOFlag complement = flags;
-
-			complement &= ~common;
-			for (node = list; node; node = next) {
-				BraseroCaps *tmp;
-
-				tmp = node->data;
-				next = node->next;
-
-				if (node == iter)
-					continue;
-
-				if (caps->type.type != tmp->type.type
-				||  caps->type.subtype.media != tmp->type.subtype.media)
-					continue;
-
-				/* substract the flags and relocate them at the
-				 * head of the list since we don't need to look
-				 * them up again */
-				complement &= ~(tmp->flags);
-				list = g_slist_remove (list, tmp);
-				list = g_slist_prepend (list, tmp);
-			}
-
-			if (complement != BRASERO_PLUGIN_IO_NONE) {
-				BraseroCaps *new_caps;
-
-				/* common == caps->flags && common != flags.
-				 * Flags encompasses caps->flags. So we need to
-				 * create a new caps for this type with the
-				 * substraction of flags if the other part isn't
-				 * in the list */
-				new_caps = brasero_caps_duplicate (caps);
-				new_caps->flags = flags & (~common);
-				self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-									       new_caps,
-									       brasero_burn_caps_sort);
-
-				list = g_slist_prepend (list, new_caps);
-			}
-		}
-	}
-
-	return list;
-}
-
-GSList *
-brasero_caps_image_new (BraseroPluginIOFlag flags,
-			BraseroImageFormat format)
-{
-	BraseroImageFormat remaining_format;
-	BraseroBurnCaps *self;
-	GSList *retval = NULL;
-	GSList *iter;
-
-	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_IMAGE,
-					 format,
-					 flags,
-					 "New caps required");
-
-	self = brasero_burn_caps_get_default ();
-
-	remaining_format = format;
-
-	/* We have to search all caps with or related to the format */
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		BraseroImageFormat common;
-		BraseroPluginIOFlag common_io;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE)
-			continue;
-
-		common_io = caps->flags & flags;
-		if (common_io == BRASERO_PLUGIN_IO_NONE)
-			continue;
-
-		common = (caps->type.subtype.img_format & format);
-		if (common == BRASERO_IMAGE_FORMAT_NONE)
-			continue;
-
-		if (common != caps->type.subtype.img_format) {
-			/* img_format encompasses format. Split it in two and
-			 * keep caps with common format */
-			SUBSTRACT (caps->type.subtype.img_format, common);
-			self->priv->caps_list = g_slist_sort (self->priv->caps_list,
-							      brasero_burn_caps_sort);
-
-			caps = brasero_caps_duplicate_deep (self, caps);
-			caps->type.subtype.img_format = common;
-
-			self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-								       caps,
-								       brasero_burn_caps_sort);
-		}
-
-		retval = g_slist_prepend (retval, caps);
-		remaining_format &= ~common;
-	}
-
-	/* Now we make sure that all these new or already 
-	 * existing caps have the proper IO Flags */
-	retval = brasero_caps_list_check_io (self, retval, flags);
-
-	if (remaining_format != BRASERO_IMAGE_FORMAT_NONE) {
-		BraseroCaps *caps;
-
-		caps = g_new0 (BraseroCaps, 1);
-		caps->flags = flags;
-		caps->type.subtype.img_format = remaining_format;
-		caps->type.type = BRASERO_TRACK_TYPE_IMAGE;
-
-		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-							       caps,
-							       brasero_burn_caps_sort);
-		retval = g_slist_prepend (retval, caps);
-
-		BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
-	}
-
-	g_object_unref (self);
-	return retval;
-}
-
-GSList *
-brasero_caps_audio_new (BraseroPluginIOFlag flags,
-			BraseroStreamFormat format)
-{
-	GSList *iter;
-	GSList *retval = NULL;
-	BraseroBurnCaps *self;
-	GSList *encompassing = NULL;
-	gboolean have_the_one = FALSE;
-
-	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_STREAM,
-					 format,
-					 flags,
-					 "New caps required");
-
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		BraseroStreamFormat common;
-		BraseroPluginIOFlag common_io;
-		BraseroStreamFormat common_audio;
-		BraseroStreamFormat common_video;
-
-		caps = iter->data;
-
-		if (caps->type.type != BRASERO_TRACK_TYPE_STREAM)
-			continue;
-
-		common_io = (flags & caps->flags);
-		if (common_io == BRASERO_PLUGIN_IO_NONE)
-			continue;
-
-		if (caps->type.subtype.audio_format == format) {
-			/* that's the perfect fit */
-			have_the_one = TRUE;
-			retval = g_slist_prepend (retval, caps);
-			continue;
-		}
-
-		/* Search caps strictly encompassed or encompassing our format
-		 * NOTE: make sure that if there is a VIDEO stream in one of
-		 * them, the other does have a VIDEO stream too. */
-		common_audio = BRASERO_STREAM_FORMAT_AUDIO (caps->type.subtype.audio_format) & 
-			       BRASERO_STREAM_FORMAT_AUDIO (format);
-		if (common_audio == BRASERO_AUDIO_FORMAT_NONE
-		&& (BRASERO_STREAM_FORMAT_AUDIO (caps->type.subtype.audio_format)
-		||  BRASERO_STREAM_FORMAT_AUDIO (format)))
-			continue;
-
-		common_video = BRASERO_STREAM_FORMAT_VIDEO (caps->type.subtype.audio_format) & 
-			       BRASERO_STREAM_FORMAT_VIDEO (format);
-
-		if (common_video == BRASERO_AUDIO_FORMAT_NONE
-		&& (BRASERO_STREAM_FORMAT_VIDEO (caps->type.subtype.audio_format)
-		||  BRASERO_STREAM_FORMAT_VIDEO (format)))
-			continue;
-
-		/* Likewise... that must be common */
-		if ((caps->type.subtype.audio_format & BRASERO_METADATA_INFO) != (format & BRASERO_METADATA_INFO))
-			continue;
-
-		common = common_audio|common_video|(format & BRASERO_METADATA_INFO);
-
-		/* encompassed caps just add it to retval */
-		if (caps->type.subtype.audio_format == common)
-			retval = g_slist_prepend (retval, caps);
-
-		/* encompassing caps keep it if we need to create perfect fit */
-		if (format == common)
-			encompassing = g_slist_prepend (encompassing, caps);
-	}
-
-	/* Now we make sure that all these new or already 
-	 * existing caps have the proper IO Flags */
-	retval = brasero_caps_list_check_io (self, retval, flags);
-
-	if (!have_the_one) {
-		BraseroCaps *caps;
-
-		caps = g_new0 (BraseroCaps, 1);
-		caps->flags = flags;
-		caps->type.subtype.audio_format = format;
-		caps->type.type = BRASERO_TRACK_TYPE_STREAM;
-
-		if (encompassing) {
-			for (iter = encompassing; iter; iter = iter->next) {
-				BraseroCaps *iter_caps;
-
-				iter_caps = iter->data;
-				brasero_caps_copy_deep (self, caps, iter_caps);
-			}
-		}
-
-		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-							       caps,
-							       brasero_burn_caps_sort);
-		retval = g_slist_prepend (retval, caps);
-
-		BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
-	}
-
-	g_slist_free (encompassing);
-
-	g_object_unref (self);
-
-	return retval;
-}
-
-GSList *
-brasero_caps_data_new (BraseroImageFS fs_type)
-{
-	GSList *iter;
-	GSList *retval = NULL;
-	BraseroBurnCaps *self;
-	GSList *encompassing = NULL;
-	gboolean have_the_one = FALSE;
-
-	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_DATA,
-					 fs_type,
-					 BRASERO_PLUGIN_IO_NONE,
-					 "New caps required");
-
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		BraseroImageFS common;
-
-		caps = iter->data;
-
-		if (caps->type.type != BRASERO_TRACK_TYPE_DATA)
-			continue;
-
-		if (caps->type.subtype.fs_type == fs_type) {
-			/* that's the perfect fit */
-			have_the_one = TRUE;
-			retval = g_slist_prepend (retval, caps);
-			continue;
-		}
-
-		/* search caps strictly encompassing our format ... */
-		common = caps->type.subtype.fs_type & fs_type;
-		if (common == BRASERO_IMAGE_FS_NONE)
-			continue;
-
-		/* encompassed caps just add it to retval */
-		if (caps->type.subtype.fs_type == common)
-			retval = g_slist_prepend (retval, caps);
-
-		/* encompassing caps keep it if we need to create perfect fit */
-		if (fs_type == common)
-			encompassing = g_slist_prepend (encompassing, caps);
-	}
-
-	if (!have_the_one) {
-		BraseroCaps *caps;
-
-		caps = g_new0 (BraseroCaps, 1);
-		caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-		caps->type.type = BRASERO_TRACK_TYPE_DATA;
-		caps->type.subtype.fs_type = fs_type;
-
-		if (encompassing) {
-			for (iter = encompassing; iter; iter = iter->next) {
-				BraseroCaps *iter_caps;
-
-				iter_caps = iter->data;
-				brasero_caps_copy_deep (self, caps, iter_caps);
-			}
-		}
-
-		self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
-							       caps,
-							       brasero_burn_caps_sort);
-		retval = g_slist_prepend (retval, caps);
-	}
-
-	g_slist_free (encompassing);
-
-	g_object_unref (self);
-
-	return retval;
-}
-
-static GSList *
-brasero_caps_disc_lookup_or_create (BraseroBurnCaps *self,
-				    GSList *retval,
-				    BraseroMedia media)
-{
-	GSList *iter;
-	BraseroCaps *caps;
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		caps = iter->data;
-
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if (caps->type.subtype.media == media) {
-			BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-						    caps->flags,
-						    "Retrieved");
-			return g_slist_prepend (retval, caps);
-		}
-	}
-
-	caps = g_new0 (BraseroCaps, 1);
-	caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
-	caps->type.type = BRASERO_TRACK_TYPE_DISC;
-	caps->type.subtype.media = media;
-
-	BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-				    caps->flags,
-				    "Created");
-
-	self->priv->caps_list = g_slist_prepend (self->priv->caps_list, caps);
-
-	return g_slist_prepend (retval, caps);
-}
-
-GSList *
-brasero_caps_disc_new (BraseroMedia type)
-{
-	BraseroBurnCaps *self;
-	GSList *retval = NULL;
-	GSList *list;
-	GSList *iter;
-
-	self = brasero_burn_caps_get_default ();
-
-	list = brasero_media_get_all_list (type);
-	for (iter = list; iter; iter = iter->next) {
-		BraseroMedia medium;
-
-		medium = GPOINTER_TO_INT (iter->data);
-		retval = brasero_caps_disc_lookup_or_create (self, retval, medium);
-	}
-	g_slist_free (list);
-
-	g_object_unref (self);
-	return retval;
-}
-
-/**
- * these functions are to create links
- */
-
-static void
-brasero_caps_create_links (BraseroCaps *output,
-	 		   GSList *inputs,
-	 		   BraseroPlugin *plugin)
-{
-	for (; inputs; inputs = inputs->next) {
-		BraseroCaps *input;
-		BraseroCapsLink *link;
-
-		input = inputs->data;
-
-		if (output == input) {
-			BRASERO_BURN_LOG ("Same input and output for link. Dropping");
-			continue;
-		}
-
-		if (input->flags == output->flags
-		&&  input->type.type == output->type.type  
-		&&  input->type.subtype.media == output->type.subtype.media)
-			BRASERO_BURN_LOG ("Recursive link");
-
-		link = brasero_caps_find_link_for_input (output, input);
-
-#if 0
-
-		/* Mainly for extra debugging */
-		BRASERO_BURN_LOG_TYPE (&output->type, "Linking");
-		BRASERO_BURN_LOG_TYPE (&input->type, "to");
-		BRASERO_BURN_LOG ("with %s", brasero_plugin_get_name (plugin));
-
-#endif
-
-		if (!link) {
-			link = g_new0 (BraseroCapsLink, 1);
-			link->caps = input;
-			link->plugins = g_slist_prepend (NULL, plugin);
-
-			output->links = g_slist_prepend (output->links, link);
-		}
-		else
-			link->plugins = g_slist_prepend (link->plugins, plugin);
-	}
-}
-
-void
-brasero_plugin_link_caps (BraseroPlugin *plugin,
-			  GSList *outputs,
-			  GSList *inputs)
-{
-	/* we make sure the caps exists and if not we create them */
-	for (; outputs; outputs = outputs->next) {
-		BraseroCaps *output;
-
-		output = outputs->data;
-		brasero_caps_create_links (output, inputs, plugin);
-	}
-}
-
-void
-brasero_plugin_blank_caps (BraseroPlugin *plugin,
-			   GSList *caps_list)
-{
-	for (; caps_list; caps_list = caps_list->next) {
-		BraseroCaps *caps;
-		BraseroCapsLink *link;
-
-		caps = caps_list->data;
-
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-	
-		BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-					    caps->flags,
-					    "Adding blank caps for");
-
-		/* we need to find the link whose caps is NULL */
-		link = brasero_caps_find_link_for_input (caps, NULL);
-		if (!link) {
-			link = g_new0 (BraseroCapsLink, 1);
-			link->caps = NULL;
-			link->plugins = g_slist_prepend (NULL, plugin);
-
-			caps->links = g_slist_prepend (caps->links, link);
-		}
-		else
-			link->plugins = g_slist_prepend (link->plugins, plugin);
-	}
-}
-
-void
-brasero_plugin_process_caps (BraseroPlugin *plugin,
-			     GSList *caps_list)
-{
-	for (; caps_list; caps_list = caps_list->next) {
-		BraseroCaps *caps;
-
-		caps = caps_list->data;
-		caps->modifiers = g_slist_prepend (caps->modifiers, plugin);
-	}
-}
-
-void
-brasero_plugin_check_caps (BraseroPlugin *plugin,
-			   BraseroChecksumType type,
-			   GSList *caps_list)
-{
-	BraseroCapsTest *test = NULL;
-	BraseroBurnCaps *self;
-	GSList *iter;
-
-	/* Find the the BraseroCapsTest for this type; if none create it */
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->tests; iter; iter = iter->next) {
-		BraseroCapsTest *tmp;
-
-		tmp = iter->data;
-		if (tmp->type == type) {
-			test = tmp;
-			break;
-		}
-	}
-
-	if (!test) {
-		test = g_new0 (BraseroCapsTest, 1);
-		test->type = type;
-		self->priv->tests = g_slist_prepend (self->priv->tests, test);
-	}
-
-	g_object_unref (self);
-
-	for (; caps_list; caps_list = caps_list->next) {
-		GSList *links;
-		BraseroCaps *caps;
-		BraseroCapsLink *link;
-
-		caps = caps_list->data;
-
-		/* try to find a link for the above caps, if none create one */
-		link = NULL;
-		for (links = test->links; links; links = links->next) {
-			BraseroCapsLink *tmp;
-
-			tmp = links->data;
-			if (tmp->caps == caps) {
-				link = tmp;
-				break;
-			}
-		}
-
-		if (!link) {
-			link = g_new0 (BraseroCapsLink, 1);
-			link->caps = caps;
-			test->links = g_slist_prepend (test->links, link);
-		}
-
-		link->plugins = g_slist_prepend (link->plugins, plugin);
-	}
-}
-
-/**
- * This is to register a plugin group 
- * This function is only define here (though it's implemented in burn-plugin.c).
- */
-
-void
-brasero_plugin_set_group (BraseroPlugin *plugin, gint group_id);
-
-void
-brasero_plugin_register_group (BraseroPlugin *plugin,
-			       const gchar *name)
-{
-	guint retval;
-	BraseroBurnCaps *self;
-
-	if (!name) {
-		brasero_plugin_set_group (plugin, 0);
-		return;
-	}
-
-	self = brasero_burn_caps_get_default ();
-
-	if (!self->priv->groups)
-		self->priv->groups = g_hash_table_new_full (g_str_hash,
-							    g_str_equal,
-							    g_free,
-							    NULL);
-
-	retval = GPOINTER_TO_INT (g_hash_table_lookup (self->priv->groups, name));
-	if (retval) {
-		brasero_plugin_set_group (plugin, retval);
-		g_object_unref (self);
-		return;
-	}
-
-	g_hash_table_insert (self->priv->groups,
-			     g_strdup (name),
-			     GINT_TO_POINTER (g_hash_table_size (self->priv->groups) + 1));
-
-	/* see if we have a group id now */
-	if (!self->priv->group_id
-	&&   self->priv->group_str
-	&&  !strcmp (name, self->priv->group_str))
-		self->priv->group_id = g_hash_table_size (self->priv->groups) + 1;
-
-	brasero_plugin_set_group (plugin, g_hash_table_size (self->priv->groups) + 1);
-
-	g_object_unref (self);
-}
-
-/** 
- * This is to find out what are the capacities of a plugin
- * Declared in brasero-plugin-private.h
- */
-
-BraseroBurnResult
-brasero_plugin_can_burn (BraseroPlugin *plugin)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		for (links = caps->links; links; links = links->next) {
-			BraseroCapsLink *link;
-			GSList *plugins;
-
-			link = links->data;
-
-			/* see if the plugin is in the link by going through the list */
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *tmp;
-
-				tmp = plugins->data;
-				if (tmp == plugin) {
-					g_object_unref (self);
-					return BRASERO_BURN_OK;
-				}
-			}
-		}
-	}
-
-	g_object_unref (self);
-	return BRASERO_BURN_NOT_SUPPORTED;
-}
-
-BraseroBurnResult
-brasero_plugin_can_image (BraseroPlugin *plugin)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroTrackDataType destination;
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
-		&&  caps->type.type != BRASERO_TRACK_TYPE_STREAM
-		&&  caps->type.type != BRASERO_TRACK_TYPE_DATA)
-			continue;
-
-		destination = caps->type.type;
-		for (links = caps->links; links; links = links->next) {
-			BraseroCapsLink *link;
-			GSList *plugins;
-
-			link = links->data;
-			if (!link->caps
-			||   link->caps->type.type == destination)
-				continue;
-
-			/* see if the plugin is in the link by going through the list */
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *tmp;
-
-				tmp = plugins->data;
-				if (tmp == plugin) {
-					g_object_unref (self);
-					return BRASERO_BURN_OK;
-				}
-			}
-		}
-	}
-
-	g_object_unref (self);
-	return BRASERO_BURN_NOT_SUPPORTED;
-}
-
-BraseroBurnResult
-brasero_plugin_can_convert (BraseroPlugin *plugin)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroTrackDataType destination;
-		BraseroCaps *caps;
-		GSList *links;
-
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
-		&&  caps->type.type != BRASERO_TRACK_TYPE_STREAM)
-			continue;
-
-		destination = caps->type.type;
-		for (links = caps->links; links; links = links->next) {
-			BraseroCapsLink *link;
-			GSList *plugins;
-
-			link = links->data;
-			if (!link->caps
-			||   link->caps->type.type != destination)
-				continue;
-
-			/* see if the plugin is in the link by going through the list */
-			for (plugins = link->plugins; plugins; plugins = plugins->next) {
-				BraseroPlugin *tmp;
-
-				tmp = plugins->data;
-				if (tmp == plugin) {
-					g_object_unref (self);
-					return BRASERO_BURN_OK;
-				}
-			}
-		}
-	}
-
-	g_object_unref (self);
-
-	return BRASERO_BURN_NOT_SUPPORTED;
-}
-
-/**
- * Used to test what the library can do based on the medium type.
- * Returns BRASERO_MEDIUM_WRITABLE if the disc can be written
- * and / or BRASERO_MEDIUM_REWRITABLE if the disc can be erased.
- * Declared in burn-media.h.
- */
-
-BraseroMedia
-brasero_media_capabilities (BraseroMedia media)
-{
-	GSList *iter;
-	GSList *links;
-	BraseroMedia retval;
-	BraseroBurnCaps *self;
-	BraseroCaps *caps = NULL;
-
-	self = brasero_burn_caps_get_default ();
-
-	retval = BRASERO_MEDIUM_NONE;
-	BRASERO_BURN_LOG_DISC_TYPE (media, "checking media caps for");
-
-	/* we're only interested in DISC caps. There should be only one caps fitting */
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		caps = iter->data;
-		if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
-			continue;
-
-		if ((media & caps->type.subtype.media) == media)
-			break;
-
-		caps = NULL;
-	}
-
-	if (!caps) {
-		g_object_unref (self);
-		return BRASERO_MEDIUM_NONE;
-	}
-
-	/* check the links */
-	for (links = caps->links; links; links = links->next) {
-		GSList *plugins;
-		gboolean active;
-		BraseroCapsLink *link;
-
-		link = links->data;
-
-		/* this link must have at least one active plugin to be valid
-		 * plugins are not sorted but in this case we don't need them
-		 * to be. we just need one active if another is with a better
-		 * priority all the better. */
-		active = FALSE;
-		for (plugins = link->plugins; plugins; plugins = plugins->next) {
-			BraseroPlugin *plugin;
-
-			plugin = plugins->data;
-			if (brasero_plugin_get_active (plugin)) {
-				/* this link is valid */
-				active = TRUE;
-				break;
-			}
-		}
-
-		if (!active)
-			continue;
-
-		if (!link->caps) {
-			/* means that it can be blanked */
-			retval |= BRASERO_MEDIUM_REWRITABLE;
-			continue;
-		}
-
-		/* means it can be written. NOTE: if this disc has already some
-		 * data on it, it even means it can be appended */
-		retval |= BRASERO_MEDIUM_WRITABLE;
-	}
-
-	g_object_unref (self);
-	return retval;
-}
-
-/**
- * This function is declared in brasero-burn-lib.h
- * It can be used to determine whether or not brasero can do any checksuming.
- */
-
-gboolean
-brasero_burn_library_can_checksum (void)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-
-	if (self->priv->tests == NULL) {
-		g_object_unref (self);
-		return FALSE;
-	}
-
-	for (iter = self->priv->tests; iter; iter = iter->next) {
-		BraseroCapsTest *tmp;
-		GSList *links;
-
-		tmp = iter->data;
-		for (links = tmp->links; links; links = links->next) {
-			BraseroCapsLink *link;
-
-			link = links->data;
-			if (brasero_caps_link_active (link)) {
-				g_object_unref (self);
-				return TRUE;
-			}
-		}
-	}
-
-	g_object_unref (self);
-	return FALSE;
-}
-
-/**
- * This is declared in burn-basics.c. It's private stuff that needs to be
- * defined in this file. For debugging use only.
- */
-
-void
-brasero_caps_list_dump (void)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-
-		caps = iter->data;
-		BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
-					    caps->flags,
-					    "Created %i links pointing to",
-					    g_slist_length (caps->links));
-	}
-
-	g_object_unref (self);
-}
-
-
-/**
- * Declared in burn-track.h
- * This is to determine whether of not a track type is supported
- */
-
-BraseroBurnResult
-brasero_track_type_is_supported (BraseroTrackType *type)
-{
-	GSList *iter;
-	BraseroBurnCaps *self;
-
-	self = brasero_burn_caps_get_default ();
-
-	for (iter = self->priv->caps_list; iter; iter = iter->next) {
-		BraseroCaps *caps;
-
-		caps = iter->data;
-
-		if (brasero_caps_is_compatible_type (caps, type)
-		&&  brasero_burn_caps_is_input (self, caps)) {
-			g_object_unref (self);
-			return BRASERO_BURN_OK;
-		}
-	}
-
-	g_object_unref (self);
-	return BRASERO_BURN_ERR;
-}
-

Modified: trunk/libbrasero-burn/burn-caps.h
==============================================================================
--- trunk/libbrasero-burn/burn-caps.h	(original)
+++ trunk/libbrasero-burn/burn-caps.h	Sun Apr  5 08:45:48 2009
@@ -35,10 +35,8 @@
 #include <glib-object.h>
 
 #include "burn-basics.h"
-#include "brasero-medium.h"
-#include "brasero-session.h"
+#include "brasero-track.h"
 #include "burn-plugin.h"
-#include "burn-task.h"
 
 G_BEGIN_DECLS
 
@@ -49,7 +47,36 @@
 #define BRASERO_IS_BURNCAPS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), BRASERO_TYPE_BURNCAPS))
 #define BRASERO_BURNCAPS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), BRASERO_TYPE_BURNCAPS, BraseroBurnCapsClass))
 
+struct _BraseroCaps {
+	GSList *links;
+	GSList *modifiers;
+	BraseroTrackType type;
+	BraseroPluginIOFlag flags;
+};
+typedef struct _BraseroCaps BraseroCaps;
+
+struct _BraseroCapsLink {
+	GSList *plugins;
+	BraseroCaps *caps;
+};
+typedef struct _BraseroCapsLink BraseroCapsLink;
+
+struct _BraseroCapsTest {
+	GSList *links;
+	BraseroChecksumType type;
+};
+typedef struct _BraseroCapsTest BraseroCapsTest;
+
 typedef struct BraseroBurnCapsPrivate BraseroBurnCapsPrivate;
+struct BraseroBurnCapsPrivate {
+	GSList *caps_list;
+	GSList *tests;
+
+	GHashTable *groups;
+
+	gchar *group_str;
+	guint group_id;
+};
 
 typedef struct {
 	GObject parent;
@@ -64,22 +91,19 @@
 
 BraseroBurnCaps *brasero_burn_caps_get_default ();
 
-/**
- * Returns a GSList * of BraseroTask * for a given session
- */
-
-GSList *
-brasero_burn_caps_new_task (BraseroBurnCaps *caps,
-			    BraseroBurnSession *session,
-			    GError **error);
-BraseroTask *
-brasero_burn_caps_new_blanking_task (BraseroBurnCaps *caps,
-				     BraseroBurnSession *session,
-				     GError **error);
-BraseroTask *
-brasero_burn_caps_new_checksuming_task (BraseroBurnCaps *caps,
-					BraseroBurnSession *session,
-					GError **error);
+gboolean
+brasero_caps_link_active (BraseroCapsLink *link);
 
+gboolean
+brasero_burn_caps_is_input (BraseroBurnCaps *self,
+			    BraseroCaps *input);
+
+BraseroCaps *
+brasero_burn_caps_find_start_caps (BraseroBurnCaps *self,
+				   BraseroTrackType *output);
+
+gboolean
+brasero_caps_is_compatible_type (const BraseroCaps *caps,
+				 const BraseroTrackType *type);
 
 #endif /* BURN_CAPS_H */

Modified: trunk/libbrasero-burn/burn-debug.c
==============================================================================
--- trunk/libbrasero-burn/burn-debug.c	(original)
+++ trunk/libbrasero-burn/burn-debug.c	Sun Apr  5 08:45:48 2009
@@ -312,3 +312,4 @@
 
 	g_free (format_real);
 }
+

Modified: trunk/libbrasero-burn/burn-job.h
==============================================================================
--- trunk/libbrasero-burn/burn-job.h	(original)
+++ trunk/libbrasero-burn/burn-job.h	Sun Apr  5 08:45:48 2009
@@ -34,7 +34,6 @@
 #include <glib.h>
 #include <glib-object.h>
 
-#include "burn-basics.h"
 #include "brasero-track.h"
 
 G_BEGIN_DECLS

Modified: trunk/libbrasero-burn/burn-process.h
==============================================================================
--- trunk/libbrasero-burn/burn-process.h	(original)
+++ trunk/libbrasero-burn/burn-process.h	Sun Apr  5 08:45:48 2009
@@ -34,7 +34,6 @@
 #include <glib.h>
 #include <glib-object.h>
 
-#include "burn-basics.h"
 #include "burn-job.h"
 
 G_BEGIN_DECLS

Modified: trunk/libbrasero-burn/plugins/cdrdao/burn-toc2cue.c
==============================================================================
--- trunk/libbrasero-burn/plugins/cdrdao/burn-toc2cue.c	(original)
+++ trunk/libbrasero-burn/plugins/cdrdao/burn-toc2cue.c	Sun Apr  5 08:45:48 2009
@@ -38,7 +38,6 @@
 #include <glib/gstdio.h>
 #include <gmodule.h>
 
-#include "burn-basics.h"
 #include "burn-plugin.h"
 #include "burn-job.h"
 #include "burn-process.h"

Modified: trunk/libbrasero-burn/plugins/transcode/burn-normalize.c
==============================================================================
--- trunk/libbrasero-burn/plugins/transcode/burn-normalize.c	(original)
+++ trunk/libbrasero-burn/plugins/transcode/burn-normalize.c	Sun Apr  5 08:45:48 2009
@@ -34,7 +34,6 @@
 
 #include <gst/gst.h>
 
-#include "burn-basics.h"
 #include "burn-job.h"
 #include "burn-plugin.h"
 #include "burn-normalize.h"

Modified: trunk/libbrasero-burn/plugins/transcode/burn-vob.c
==============================================================================
--- trunk/libbrasero-burn/plugins/transcode/burn-vob.c	(original)
+++ trunk/libbrasero-burn/plugins/transcode/burn-vob.c	Sun Apr  5 08:45:48 2009
@@ -35,7 +35,6 @@
 #include <gst/gst.h>
 
 #include "brasero-tags.h"
-#include "burn-basics.h"
 #include "burn-job.h"
 #include "burn-plugin.h"
 #include "burn-vob.h"

Modified: trunk/libbrasero-media/brasero-media-private.h
==============================================================================
--- trunk/libbrasero-media/brasero-media-private.h	(original)
+++ trunk/libbrasero-media/brasero-media-private.h	Sun Apr  5 08:45:48 2009
@@ -44,9 +44,6 @@
 GSList *
 brasero_media_get_all_list (BraseroMedia type);
 
-BraseroMedia
-brasero_media_capabilities (BraseroMedia media);
-
 
 /**
  * For internal debugging purposes

Modified: trunk/libbrasero-media/brasero-media.c
==============================================================================
--- trunk/libbrasero-media/brasero-media.c	(original)
+++ trunk/libbrasero-media/brasero-media.c	Sun Apr  5 08:45:48 2009
@@ -38,6 +38,7 @@
 #include <glib/gi18n-lib.h>
 
 #include "brasero-media.h"
+#include "brasero-media-private.h"
 
 static gboolean debug = 0;
 

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Sun Apr  5 08:45:48 2009
@@ -1,6 +1,7 @@
 # List of source files containing translatable strings.
 [encoding: UTF-8]
 
+libbrasero-burn/brasero-caps-burn.c
 libbrasero-burn/brasero-track-image-cfg.c
 libbrasero-burn/brasero-burn-dialog.c
 libbrasero-burn/brasero-burn-options.c

Modified: trunk/src/brasero-data-session.c
==============================================================================
--- trunk/src/brasero-data-session.c	(original)
+++ trunk/src/brasero-data-session.c	Sun Apr  5 08:45:48 2009
@@ -383,7 +383,7 @@
 	BraseroMedia media_status;
 
 	media = brasero_medium_get_status (medium);
-	media_status = brasero_media_capabilities (media);
+	media_status = brasero_burn_library_get_media_capabilities (media);
 
 	return (media_status & BRASERO_MEDIUM_WRITABLE) &&
 	       (media & BRASERO_MEDIUM_HAS_DATA) &&



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