brasero r2209 - in trunk: . libbrasero-burn libbrasero-burn/plugins/cdrdao libbrasero-burn/plugins/transcode libbrasero-media po src
- From: philippr svn gnome org
- To: svn-commits-list gnome org
- Subject: brasero r2209 - in trunk: . libbrasero-burn libbrasero-burn/plugins/cdrdao libbrasero-burn/plugins/transcode libbrasero-media po src
- Date: Sun, 5 Apr 2009 08:45:48 +0000 (UTC)
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]