1
/***************************************************************************
4
* mar avr 18 20:58:42 2006
5
* Copyright 2006 Rouquier Philippe
6
* brasero-app@wanadoo.fr
7
***************************************************************************/
10
* Brasero is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* Brasero is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU Library General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to:
22
* The Free Software Foundation, Inc.,
23
* 51 Franklin Street, Fifth Floor
24
* Boston, MA 02110-1301, USA.
34
#include <glib-object.h>
35
#include <glib/gi18n.h>
37
#include <gconf/gconf-client.h>
39
#include "brasero-media-private.h"
41
#include "burn-basics.h"
42
#include "burn-debug.h"
43
#include "brasero-drive.h"
44
#include "brasero-medium.h"
45
#include "burn-session.h"
46
#include "burn-plugin.h"
47
#include "burn-plugin-private.h"
48
#include "burn-task.h"
49
#include "burn-caps.h"
51
#define BRASERO_ENGINE_GROUP_KEY "/apps/brasero/config/engine-group"
53
G_DEFINE_TYPE (BraseroBurnCaps, brasero_burn_caps, G_TYPE_OBJECT);
55
struct BraseroBurnCapsPrivate {
68
BraseroTrackType type;
69
BraseroPluginIOFlag flags;
71
typedef struct _BraseroCaps BraseroCaps;
73
struct _BraseroCapsLink {
77
typedef struct _BraseroCapsLink BraseroCapsLink;
79
struct _BraseroCapsTest {
81
BraseroChecksumType type;
83
typedef struct _BraseroCapsTest BraseroCapsTest;
85
#define SUBSTRACT(a, b) ((a) &= ~((b)&(a)))
87
static GObjectClass *parent_class = NULL;
88
static BraseroBurnCaps *default_caps = NULL;
91
* These two functions are not public API and defined in burn-medium.c
95
brasero_medium_support_flags (BraseroMedium *medium,
96
BraseroBurnFlag flags);
99
brasero_medium_supported_flags (BraseroMedium *self,
100
BraseroBurnFlag flags);
103
* This macro is used to determine whether or not blanking could change anything
104
* for the medium so that we can write to it.
106
#define BRASERO_BURN_CAPS_SHOULD_BLANK(media_MACRO, flags_MACRO) \
107
((media_MACRO & BRASERO_MEDIUM_UNFORMATTED) || \
108
((media_MACRO & (BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) && \
109
(flags_MACRO & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND)) == FALSE))
111
#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG(session) \
113
brasero_burn_session_log (session, "Unsupported type of task operation"); \
114
BRASERO_BURN_LOG ("Unsupported type of task operation"); \
118
#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES(session) \
120
brasero_burn_session_log (session, "Unsupported type of task operation"); \
121
BRASERO_BURN_LOG ("Unsupported type of task operation"); \
122
return BRASERO_BURN_NOT_SUPPORTED; \
125
#define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR(session, error) \
128
g_set_error (error, \
129
BRASERO_BURN_ERROR, \
130
BRASERO_BURN_ERROR_GENERAL, \
131
_("An internal error occured")); \
132
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session); \
136
brasero_caps_link_free (BraseroCapsLink *link)
138
g_slist_free (link->plugins);
143
brasero_caps_free (BraseroCaps *caps)
145
g_slist_foreach (caps->links, (GFunc) brasero_caps_link_free, NULL);
146
g_slist_free (caps->links);
151
brasero_burn_caps_finalize (GObject *object)
153
BraseroBurnCaps *cobj;
155
cobj = BRASERO_BURNCAPS (object);
159
if (cobj->priv->groups) {
160
g_hash_table_destroy (cobj->priv->groups);
161
cobj->priv->groups = NULL;
164
g_slist_foreach (cobj->priv->caps_list, (GFunc) brasero_caps_free, NULL);
165
g_slist_free (cobj->priv->caps_list);
168
G_OBJECT_CLASS (parent_class)->finalize (object);
172
brasero_burn_caps_class_init (BraseroBurnCapsClass *klass)
174
GObjectClass *object_class = G_OBJECT_CLASS (klass);
176
parent_class = g_type_class_peek_parent (klass);
177
object_class->finalize = brasero_burn_caps_finalize;
181
brasero_burn_caps_init (BraseroBurnCaps *obj)
185
obj->priv = g_new0 (BraseroBurnCapsPrivate, 1);
187
client = gconf_client_get_default ();
188
obj->priv->group_str = gconf_client_get_string (client,
189
BRASERO_ENGINE_GROUP_KEY,
191
g_object_unref (client);
195
brasero_burn_caps_get_default ()
198
default_caps = BRASERO_BURNCAPS (g_object_new (BRASERO_TYPE_BURNCAPS, NULL));
200
g_object_ref (default_caps);
205
/* that function receives all errors returned by the object and 'learns' from
206
* these errors what are the safest defaults for a particular system. It should
207
* also offer fallbacks if an error occurs through a signal */
208
static BraseroBurnResult
209
brasero_burn_caps_job_error_cb (BraseroJob *job,
210
BraseroBurnError error,
211
BraseroBurnCaps *caps)
214
GError *error = NULL;
217
/* This was originally to fix a bug in fedora 5 that prevents from
218
* sending SCSI commands as a normal user through cdrdao. There is a
219
* fallback fortunately with cdrecord and raw images but no on_the_fly
221
* That could be used as a hook to know how a job runs and give a
222
* "penalty" to job types being too often faulty. There could also be
223
* a dialog to ask the user if he wants to use another backend.
226
/* set it in GConf to remember that next time */
227
client = gconf_client_get_default ();
228
gconf_client_set_bool (client, GCONF_KEY_CDRDAO_DISABLED, TRUE, &error);
230
g_warning ("Can't write with GConf: %s", error->message);
231
g_error_free (error);
233
g_object_unref (client);
235
return BRASERO_BURN_ERR;
239
brasero_caps_is_compatible_type (const BraseroCaps *caps,
240
const BraseroTrackType *type)
242
if (caps->type.type != type->type)
245
switch (type->type) {
246
case BRASERO_TRACK_TYPE_DATA:
247
if ((caps->type.subtype.fs_type & type->subtype.fs_type) != type->subtype.fs_type)
251
case BRASERO_TRACK_TYPE_DISC:
252
if (type->subtype.media == BRASERO_MEDIUM_NONE)
255
/* Reminder: we now create every possible types */
256
if (caps->type.subtype.media != type->subtype.media)
260
case BRASERO_TRACK_TYPE_IMAGE:
261
if (type->subtype.img_format == BRASERO_IMAGE_FORMAT_NONE)
264
if ((caps->type.subtype.img_format & type->subtype.img_format) != type->subtype.img_format)
268
case BRASERO_TRACK_TYPE_AUDIO:
269
/* There is one small special case here with video. */
270
if ((caps->type.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|
271
BRASERO_VIDEO_FORMAT_VCD|
272
BRASERO_VIDEO_FORMAT_VIDEO_DVD))
273
&& !(type->subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|
274
BRASERO_VIDEO_FORMAT_VCD|
275
BRASERO_VIDEO_FORMAT_VIDEO_DVD)))
278
if ((caps->type.subtype.audio_format & type->subtype.audio_format) != type->subtype.audio_format)
290
brasero_caps_find_start_caps (BraseroTrackType *output)
293
BraseroBurnCaps *self;
295
self = brasero_burn_caps_get_default ();
296
for (iter = self->priv->caps_list; iter; iter = iter->next) {
301
if (!brasero_caps_is_compatible_type (caps, output))
304
if (caps->type.type == BRASERO_TRACK_TYPE_DISC
305
|| (caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE))
313
brasero_burn_caps_get_blanking_flags_real (BraseroBurnCaps *caps,
315
BraseroBurnFlag session_flags,
316
BraseroBurnFlag *supported,
317
BraseroBurnFlag *compulsory)
320
gboolean supported_media;
321
BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
322
BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
324
BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
325
if (media == BRASERO_MEDIUM_NONE) {
326
BRASERO_BURN_LOG ("Blanking not possible: no media");
328
*supported = BRASERO_BURN_FLAG_NONE;
330
*compulsory = BRASERO_BURN_FLAG_NONE;
331
return BRASERO_BURN_NOT_SUPPORTED;
334
supported_media = FALSE;
335
for (iter = caps->priv->caps_list; iter; iter = iter->next) {
340
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
343
if ((media & caps->type.subtype.media) != media)
346
for (links = caps->links; links; links = links->next) {
348
BraseroCapsLink *link;
352
if (link->caps != NULL)
355
supported_media = TRUE;
356
/* don't need the plugins to be sorted since we go
357
* through all the plugin list to get all blanking flags
359
for (plugins = link->plugins; plugins; plugins = plugins->next) {
360
BraseroPlugin *plugin;
361
BraseroBurnFlag supported_plugin;
362
BraseroBurnFlag compulsory_plugin;
364
plugin = plugins->data;
365
if (!brasero_plugin_get_active (plugin))
368
if (!brasero_plugin_get_blank_flags (plugin,
375
supported_flags |= supported_plugin;
376
compulsory_flags &= compulsory_plugin;
381
if (!supported_media) {
382
BRASERO_BURN_LOG ("media blanking not supported");
383
return BRASERO_BURN_NOT_SUPPORTED;
387
*supported = supported_flags;
389
*compulsory = compulsory_flags;
391
return BRASERO_BURN_OK;
395
brasero_burn_caps_get_blanking_flags (BraseroBurnCaps *caps,
396
BraseroBurnSession *session,
397
BraseroBurnFlag *supported,
398
BraseroBurnFlag *compulsory)
401
BraseroBurnFlag session_flags;
403
media = brasero_burn_session_get_dest_media (session);
404
BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
406
if (media == BRASERO_MEDIUM_NONE) {
407
BRASERO_BURN_LOG ("Blanking not possible: no media");
409
*supported = BRASERO_BURN_FLAG_NONE;
411
*compulsory = BRASERO_BURN_FLAG_NONE;
412
return BRASERO_BURN_NOT_SUPPORTED;
415
session_flags = brasero_burn_session_get_flags (session);
416
return brasero_burn_caps_get_blanking_flags_real (caps,
424
brasero_burn_caps_new_blanking_task (BraseroBurnCaps *self,
425
BraseroBurnSession *session,
430
BraseroBurnFlag flags;
431
BraseroTask *task = NULL;
433
media = brasero_burn_session_get_dest_media (session);
434
flags = brasero_burn_session_get_flags (session);
436
for (iter = self->priv->caps_list; iter; iter = iter->next) {
441
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
444
if ((media & caps->type.subtype.media) != media)
447
for (links = caps->links; links; links = links->next) {
449
BraseroCapsLink *link;
450
BraseroPlugin *candidate;
454
if (link->caps != NULL)
457
/* Go through all the plugins and find the best plugin
458
* for the task. It must :
460
* - have the highest priority
461
* - accept the flags */
463
for (plugins = link->plugins; plugins; plugins = plugins->next) {
464
BraseroPlugin *plugin;
466
plugin = plugins->data;
468
if (!brasero_plugin_get_active (plugin))
471
if (!brasero_plugin_check_blank_flags (plugin, media, flags))
474
if (self->priv->group_id > 0 && candidate) {
475
/* the candidate must be in the favourite group as much as possible */
476
if (brasero_plugin_get_group (candidate) != self->priv->group_id) {
477
if (brasero_plugin_get_group (plugin) == self->priv->group_id) {
482
else if (brasero_plugin_get_group (plugin) != self->priv->group_id)
488
else if (brasero_plugin_get_priority (plugin) >
489
brasero_plugin_get_priority (candidate))
497
type = brasero_plugin_get_gtype (candidate);
498
job = BRASERO_JOB (g_object_new (type,
501
g_signal_connect (job,
503
G_CALLBACK (brasero_burn_caps_job_error_cb),
506
task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
508
"action", BRASERO_TASK_ACTION_ERASE,
510
brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
516
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
520
brasero_burn_caps_can_blank_real (BraseroBurnCaps *self,
522
BraseroBurnFlag flags)
526
BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
527
if (media == BRASERO_MEDIUM_NONE) {
528
BRASERO_BURN_LOG ("no media => no blanking possible");
529
return BRASERO_BURN_NOT_SUPPORTED;
532
for (iter = self->priv->caps_list; iter; iter = iter->next) {
537
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
540
if ((media & caps->type.subtype.media) != media)
543
BRASERO_BURN_LOG_TYPE (&caps->type, "Searching links for caps");
545
for (links = caps->links; links; links = links->next) {
547
BraseroCapsLink *link;
551
if (link->caps != NULL)
554
BRASERO_BURN_LOG ("Searching plugins");
556
/* Go through all plugins for the link and stop if we
557
* find at least one active plugin that accepts the
558
* flags. No need for plugins to be sorted */
559
for (plugins = link->plugins; plugins; plugins = plugins->next) {
560
BraseroPlugin *plugin;
562
plugin = plugins->data;
563
if (!brasero_plugin_get_active (plugin))
566
if (brasero_plugin_check_blank_flags (plugin, media, flags)) {
567
BRASERO_BURN_LOG_DISC_TYPE (media, "Can blank");
568
return BRASERO_BURN_OK;
574
BRASERO_BURN_LOG_DISC_TYPE (media, "No blanking capabilities for");
576
return BRASERO_BURN_NOT_SUPPORTED;
580
brasero_burn_caps_can_blank (BraseroBurnCaps *self,
581
BraseroBurnSession *session)
584
BraseroBurnFlag flags;
586
media = brasero_burn_session_get_dest_media (session);
587
BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
589
if (media == BRASERO_MEDIUM_NONE) {
590
BRASERO_BURN_LOG ("no media => no blanking possible");
591
return BRASERO_BURN_NOT_SUPPORTED;
594
flags = brasero_burn_session_get_flags (session);
595
return brasero_burn_caps_can_blank_real (self, media, flags);
603
brasero_caps_link_get_record_flags (BraseroCapsLink *link,
605
BraseroBurnFlag session_flags,
606
BraseroBurnFlag *supported,
607
BraseroBurnFlag *compulsory_retval)
610
BraseroBurnFlag compulsory;
612
compulsory = BRASERO_BURN_FLAG_ALL;
614
/* Go through all plugins to get the supported/... record flags for link */
615
for (iter = link->plugins; iter; iter = iter->next) {
617
BraseroPlugin *plugin;
618
BraseroBurnFlag plugin_supported;
619
BraseroBurnFlag plugin_compulsory;
622
if (!brasero_plugin_get_active (plugin))
625
result = brasero_plugin_get_record_flags (plugin,
633
*supported |= plugin_supported;
634
compulsory &= plugin_compulsory;
637
*compulsory_retval = compulsory;
641
brasero_caps_link_get_data_flags (BraseroCapsLink *link,
643
BraseroBurnFlag session_flags,
644
BraseroBurnFlag *supported)
648
/* Go through all plugins the get the supported/... data flags for link */
649
for (iter = link->plugins; iter; iter = iter->next) {
651
BraseroPlugin *plugin;
652
BraseroBurnFlag plugin_supported;
653
BraseroBurnFlag plugin_compulsory;
656
if (!brasero_plugin_get_active (plugin))
659
result = brasero_plugin_get_image_flags (plugin,
664
*supported |= plugin_supported;
669
brasero_caps_link_active (BraseroCapsLink *link)
673
/* See if link is active by going through all plugins. There must be at
675
for (iter = link->plugins; iter; iter = iter->next) {
676
BraseroPlugin *plugin;
679
if (brasero_plugin_get_active (plugin))
687
brasero_caps_link_check_data_flags (BraseroCapsLink *link,
688
BraseroBurnFlag session_flags,
692
BraseroBurnFlag flags;
694
/* here we just make sure that at least one of the plugins in the link
695
* can comply with the flags (APPEND/MERGE) */
696
flags = session_flags & (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE);
698
/* If there are no image flags forget it */
699
if (flags == BRASERO_BURN_FLAG_NONE)
702
/* Go through all plugins; at least one must support image flags */
703
for (iter = link->plugins; iter; iter = iter->next) {
705
BraseroPlugin *plugin;
708
if (!brasero_plugin_get_active (plugin))
711
result = brasero_plugin_check_image_flags (plugin,
722
brasero_caps_link_check_record_flags (BraseroCapsLink *link,
723
BraseroBurnFlag session_flags,
727
BraseroBurnFlag flags;
729
flags = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
731
/* If there are no record flags forget it */
732
if (flags == BRASERO_BURN_FLAG_NONE)
735
/* Go through all plugins: at least one must support record flags */
736
for (iter = link->plugins; iter; iter = iter->next) {
738
BraseroPlugin *plugin;
741
if (!brasero_plugin_get_active (plugin))
744
result = brasero_plugin_check_record_flags (plugin,
755
brasero_caps_link_check_media_restrictions (BraseroCapsLink *link,
760
/* Go through all plugins: at least one must support media */
761
for (iter = link->plugins; iter; iter = iter->next) {
763
BraseroPlugin *plugin;
766
if (!brasero_plugin_get_active (plugin))
769
result = brasero_plugin_check_media_restrictions (plugin, media);
777
static BraseroPlugin *
778
brasero_caps_link_find_plugin (BraseroCapsLink *link,
780
BraseroBurnFlag session_flags,
781
BraseroTrackType *output,
785
BraseroPlugin *candidate;
787
/* Go through all plugins for a link and find the best one. It must:
789
* - be part of the group (as much as possible)
790
* - have the highest priority
791
* - support the flags */
793
for (iter = link->plugins; iter; iter = iter->next) {
794
BraseroPlugin *plugin;
798
if (!brasero_plugin_get_active (plugin))
801
if (output->type == BRASERO_TRACK_TYPE_DISC) {
804
result = brasero_plugin_check_record_flags (plugin,
811
if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
814
result = brasero_plugin_check_image_flags (plugin,
820
else if (!brasero_plugin_check_media_restrictions (plugin, media))
823
if (group_id > 0 && candidate) {
824
/* the candidate must be in the favourite group as much as possible */
825
if (brasero_plugin_get_group (candidate) != group_id) {
826
if (brasero_plugin_get_group (plugin) == group_id) {
831
else if (brasero_plugin_get_group (plugin) != group_id)
837
else if (brasero_plugin_get_priority (plugin) >
838
brasero_plugin_get_priority (candidate))
845
typedef struct _BraseroCapsLinkList BraseroCapsLinkList;
846
struct _BraseroCapsLinkList {
847
BraseroCapsLinkList *next;
848
BraseroCapsLink *link;
849
BraseroPlugin *plugin;
852
static BraseroCapsLinkList *
853
brasero_caps_link_list_insert (BraseroCapsLinkList *list,
854
BraseroCapsLinkList *node,
857
BraseroCapsLinkList *iter;
862
if (brasero_plugin_get_priority (node->plugin) >
863
brasero_plugin_get_priority (list->plugin)) {
868
if (brasero_plugin_get_priority (node->plugin) ==
869
brasero_plugin_get_priority (list->plugin)) {
875
node->next = list->next;
886
/* Need a node with at least the same priority. Stop if end is reached */
889
brasero_plugin_get_priority (node->plugin) <
890
brasero_plugin_get_priority (iter->next->plugin))
894
/* reached the end of the list, put it at the end */
898
else if (brasero_plugin_get_priority (node->plugin) <
899
brasero_plugin_get_priority (iter->next->plugin)) {
900
/* Put it at the end of the list */
902
iter->next->next = node;
904
else if (brasero_plugin_get_priority (node->plugin) >
905
brasero_plugin_get_priority (iter->next->plugin)) {
906
/* insert it before iter->next */
907
node->next = iter->next;
911
/* insert it before the link with the same priority */
912
node->next = iter->next;
916
/* insert it after the link with the same priority */
917
node->next = iter->next->next;
918
iter->next->next = node;
924
brasero_caps_find_best_link (BraseroCaps *caps,
927
BraseroBurnFlag session_flags,
929
BraseroTrackType *input,
930
BraseroPluginIOFlag io_flags)
933
GSList *results = NULL;
934
BraseroCapsLinkList *node = NULL;
935
BraseroCapsLinkList *list = NULL;
937
BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_best_link");
939
/* First, build a list of possible links and sort them out according to
940
* the priority based on the highest priority among their plugins. In
941
* this case, we can't sort links beforehand since according to the
942
* flags, input, output in the session the plugins will or will not
943
* be used. Moreover given the group_id thing the choice of plugin may
946
/* This is done to address possible issues namely:
947
* - growisofs can handle DATA right from the start but has a lower
948
* priority than libburn. In this case growisofs would be used every
949
* time for DATA despite its having a lower priority than libburn if we
950
* were looking for the best fit first
951
* - We don't want to follow the long path and have a useless (in this
952
* case) image converter plugin get included.
953
* ex: we would have: CDRDAO (input) toc2cue => (CUE) cdrdao => (DISC)
954
* instead of simply: CDRDAO (input) cdrdao => (DISC) */
956
for (iter = caps->links; iter; iter = iter->next) {
957
BraseroPlugin *plugin;
958
BraseroCapsLink *link;
963
/* skip blanking links */
965
BRASERO_BURN_LOG ("Blanking caps");
969
/* the link should not link to an already used caps */
970
if (g_slist_find (used_caps, link->caps)) {
971
BRASERO_BURN_LOG ("Already used caps");
975
/* see if that's a perfect fit;
976
* - it must have the same caps (type + subtype)
977
* - it must have the proper IO (file). */
978
fits = (link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) &&
979
brasero_caps_is_compatible_type (link->caps, input);
982
/* if it doesn't fit it must be at least connectable */
983
if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE) {
984
BRASERO_BURN_LOG ("Not connectable");
988
/* we can't go further than a DISC type, no need to keep it */
989
if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC) {
990
BRASERO_BURN_LOG ("Can't go further than DISC caps");
995
/* See if this link can be used. For a link to be followed it
997
* - have at least an active plugin
998
* - have at least a plugin accepting the record flags if caps type (output)
999
* is a disc (that means that the link is the recording part)
1000
* - have at least a plugin accepting the data flags if caps type (input)
1002
plugin = brasero_caps_link_find_plugin (link,
1008
BRASERO_BURN_LOG ("No plugin found");
1012
BRASERO_BURN_LOG ("Found candidate link");
1014
/* A plugin could be found which means that link can be used.
1015
* Insert it in the list at the right place.
1016
* The list is sorted according to priorities (starting with the
1017
* highest). If 2 links have the same priority put first the one
1018
* that has the correct input. */
1019
node = g_new0 (BraseroCapsLinkList, 1);
1020
node->plugin = plugin;
1023
list = brasero_caps_link_list_insert (list, node, fits);
1027
BRASERO_BURN_LOG ("No links found");
1031
used_caps = g_slist_prepend (used_caps, caps);
1033
/* Then, go through this list (starting with highest priority links)
1034
* The rule is we prefer the links with the highest priority; if two
1035
* links have the same priority and one of them leads to a caps
1036
* with the correct type then choose this one. */
1037
for (node = list; node; node = node->next) {
1038
guint search_group_id;
1040
/* see if that's a perfect fit; if so, then we're good.
1041
* - it must have the same caps (type + subtype)
1042
* - it must have the proper IO (file) */
1043
if ((node->link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
1044
&& brasero_caps_is_compatible_type (node->link->caps, input)) {
1045
results = g_slist_prepend (NULL, node->link);
1049
/* determine the group_id for the search */
1050
if (brasero_plugin_get_group (node->plugin) > 0 && group_id <= 0)
1051
search_group_id = brasero_plugin_get_group (node->plugin);
1053
search_group_id = group_id;
1055
/* It's not a perfect fit. First see if a plugin with the same
1056
* priority don't have the right input. Then see if we can reach
1057
* the right input by going through all previous nodes */
1058
results = brasero_caps_find_best_link (node->link->caps,
1066
results = g_slist_prepend (results, node->link);
1072
used_caps = g_slist_remove (used_caps, caps);
1073
for (node = list; node; node = list) {
1082
brasero_burn_caps_sort_modifiers (gconstpointer a,
1085
BraseroPlugin *plug_a = BRASERO_PLUGIN (a);
1086
BraseroPlugin *plug_b = BRASERO_PLUGIN (b);
1088
return brasero_plugin_get_priority (plug_a) -
1089
brasero_plugin_get_priority (plug_b);
1093
brasero_caps_add_processing_plugins_to_task (BraseroBurnSession *session,
1096
BraseroTrackType *io_type,
1097
BraseroPluginProcessFlag position)
1099
GSList *retval = NULL;
1103
if (position == BRASERO_PLUGIN_RUN_NEVER
1104
|| caps->type.type == BRASERO_TRACK_TYPE_DISC)
1107
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
1109
"Adding modifiers (position %i) (%i modifiers available) for",
1111
g_slist_length (caps->modifiers));
1113
/* Go through all plugins and add all possible modifiers. They must:
1115
* - accept the position flags */
1116
modifiers = g_slist_copy (caps->modifiers);
1117
modifiers = g_slist_sort (modifiers, brasero_burn_caps_sort_modifiers);
1119
for (iter = modifiers; iter; iter = iter->next) {
1120
BraseroPluginProcessFlag flags;
1121
BraseroPlugin *plugin;
1125
plugin = iter->data;
1126
if (!brasero_plugin_get_active (plugin))
1129
brasero_plugin_get_process_flags (plugin, &flags);
1130
if ((flags & position) != position)
1133
type = brasero_plugin_get_gtype (plugin);
1134
job = BRASERO_JOB (g_object_new (type,
1137
g_signal_connect (job,
1139
G_CALLBACK (brasero_burn_caps_job_error_cb),
1143
|| !(caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
1144
|| !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
1145
/* here the action taken is always to create an image */
1146
task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
1148
"action", BRASERO_BURN_ACTION_CREATING_IMAGE,
1150
retval = g_slist_prepend (retval, task);
1153
BRASERO_BURN_LOG ("%s (modifier) added to task",
1154
brasero_plugin_get_name (plugin));
1156
BRASERO_BURN_LOG_TYPE (io_type, "IO type");
1158
brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
1160
g_slist_free (modifiers);
1166
brasero_burn_caps_flags_check_for_drive (BraseroBurnSession *session)
1168
BraseroDrive *drive;
1169
BraseroMedium *medium;
1170
BraseroBurnFlag flags;
1172
drive = brasero_burn_session_get_burner (session);
1176
if (brasero_drive_is_fake (drive))
1179
medium = brasero_drive_get_medium (drive);
1183
flags = brasero_burn_session_get_flags (session);
1184
return brasero_medium_support_flags (medium, flags);
1188
brasero_burn_caps_new_task (BraseroBurnCaps *self,
1189
BraseroBurnSession *session,
1192
BraseroPluginProcessFlag position;
1193
BraseroBurnFlag session_flags;
1194
BraseroTrackType plugin_input;
1195
BraseroTask *blanking = NULL;
1196
BraseroPluginIOFlag flags;
1197
BraseroTask *task = NULL;
1198
BraseroTrackType output;
1199
BraseroTrackType input;
1200
BraseroCaps *last_caps;
1201
GSList *retval = NULL;
1202
GSList *iter, *list;
1206
/* determine the output and the flags for this task */
1207
if (brasero_burn_session_is_dest_file (session)) {
1208
media = BRASERO_MEDIUM_FILE;
1210
output.type = BRASERO_TRACK_TYPE_IMAGE;
1211
output.subtype.img_format = brasero_burn_session_get_output_format (session);
1214
media = brasero_burn_session_get_dest_media (session);
1216
output.type = BRASERO_TRACK_TYPE_DISC;
1217
output.subtype.media = media;
1220
if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
1221
flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
1223
flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
1225
BRASERO_BURN_LOG_WITH_TYPE (&output,
1227
"Creating recording/imaging task");
1229
/* search the start caps and try to get a list of links */
1230
last_caps = brasero_caps_find_start_caps (&output);
1232
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1234
brasero_burn_session_get_input_type (session, &input);
1235
BRASERO_BURN_LOG_WITH_TYPE (&input,
1236
BRASERO_PLUGIN_IO_NONE,
1239
if (!brasero_burn_caps_flags_check_for_drive (session))
1240
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG (session);
1242
session_flags = brasero_burn_session_get_flags (session);
1243
list = brasero_caps_find_best_link (last_caps,
1244
self->priv->group_id,
1251
/* we reached this point in two cases:
1252
* - if the disc cannot be handled
1253
* - if some flags are not handled
1254
* It is helpful only if:
1255
* - the disc was closed and no plugin can handle this type of
1256
* disc once closed (CD-R(W))
1257
* - there was the flag BLANK_BEFORE_WRITE set and no plugin can
1258
* handle this flag (means that the plugin should erase and
1259
* then write on its own. Basically that works only with
1260
* overwrite formatted discs, DVD+RW, ...) */
1261
if (output.type != BRASERO_TRACK_TYPE_DISC)
1262
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1264
/* output is a disc try with initial blanking */
1265
BRASERO_BURN_LOG ("failed to create proper task. Trying with initial blanking");
1267
/* apparently nothing can be done to reach our goal. Maybe that
1268
* is because we first have to blank the disc. If so add a blank
1269
* task to the others as a first step */
1270
if (!(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
1271
|| brasero_burn_caps_can_blank (self, session) != BRASERO_BURN_OK)
1272
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1274
/* retry with the same disc type but blank this time */
1275
media &= ~(BRASERO_MEDIUM_CLOSED|
1276
BRASERO_MEDIUM_APPENDABLE|
1277
BRASERO_MEDIUM_UNFORMATTED|
1278
BRASERO_MEDIUM_HAS_DATA|
1279
BRASERO_MEDIUM_HAS_AUDIO);
1280
media |= BRASERO_MEDIUM_BLANK;
1282
output.subtype.media = media;
1284
last_caps = brasero_caps_find_start_caps (&output);
1286
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1288
/* if the flag BLANK_BEFORE_WRITE was set then remove it since
1289
* we are actually blanking. Simply the record plugin won't have
1291
session_flags &= ~BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
1292
list = brasero_caps_find_best_link (last_caps,
1293
self->priv->group_id,
1300
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1302
BRASERO_BURN_LOG ("initial blank/erase task required")
1304
blanking = brasero_burn_caps_new_blanking_task (self, session, error);
1305
/* The problem here is that we shouldn't always prepend such a
1306
* task. For example when we copy a disc to another using the
1307
* same drive. In this case we should insert it before the last.
1308
* Now, that always work so that's what we do in all cases. Once
1309
* the whole list of tasks is created we insert this blanking
1310
* task just before the last one. Another advantage is that the
1311
* blanking of the disc is delayed as late as we can which means
1312
* in case of error we keep it intact as late as we can. */
1315
/* reverse the list of links to have them in the right order */
1316
list = g_slist_reverse (list);
1317
position = BRASERO_PLUGIN_RUN_PREPROCESSING;
1318
group_id = self->priv->group_id;
1320
brasero_burn_session_get_input_type (session, &plugin_input);
1321
for (iter = list; iter; iter = iter->next) {
1322
BraseroTrackType plugin_output;
1323
BraseroCapsLink *link;
1324
BraseroPlugin *plugin;
1331
/* determine the plugin output */
1333
BraseroCapsLink *next_link;
1335
next_link = iter->next->data;
1336
if (next_link == link) {
1337
/* That's a processing plugin so the output must
1338
* be the exact same as the input, which is not
1339
* necessarily the caps type referred to by the
1340
* link if the link is amongst the first. In
1341
* that case that's the session input. */
1342
memcpy (&plugin_output,
1344
sizeof (BraseroTrackType));
1347
memcpy (&plugin_output,
1348
&next_link->caps->type,
1349
sizeof (BraseroTrackType));
1353
memcpy (&plugin_output,
1355
sizeof (BraseroTrackType));
1357
/* first see if there are track processing plugins */
1358
result = brasero_caps_add_processing_plugins_to_task (session,
1363
retval = g_slist_concat (retval, result);
1365
/* create job from the best plugin in link */
1366
plugin = brasero_caps_link_find_plugin (link,
1374
BRASERO_BURN_ERROR_GENERAL,
1375
_("An internal error occured"));
1376
g_slist_foreach (retval, (GFunc) g_object_unref, NULL);
1377
g_slist_free (retval);
1378
g_slist_free (list);
1382
/* This is meant to have plugins in the same group id as much as
1384
if (brasero_plugin_get_group (plugin) > 0 && group_id <= 0)
1385
group_id = brasero_plugin_get_group (plugin);
1387
type = brasero_plugin_get_gtype (plugin);
1388
job = BRASERO_JOB (g_object_new (type,
1389
"output", &plugin_output,
1391
g_signal_connect (job,
1393
G_CALLBACK (brasero_burn_caps_job_error_cb),
1397
|| !(link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE)
1398
|| !BRASERO_BURN_SESSION_NO_TMP_FILE (session)) {
1399
/* only the last task will be doing the proper action
1400
* all other are only steps to take to reach the final
1402
BRASERO_BURN_LOG ("New task");
1403
task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
1405
"action", BRASERO_TASK_ACTION_NORMAL,
1407
retval = g_slist_append (retval, task);
1410
brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
1412
BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (plugin));
1413
BRASERO_BURN_LOG_TYPE (&plugin_input, "input");
1414
BRASERO_BURN_LOG_TYPE (&plugin_output, "output");
1416
position = BRASERO_PLUGIN_RUN_BEFORE_TARGET;
1418
/* the output of the plugin will become the input of the next */
1419
memcpy (&plugin_input, &plugin_output, sizeof (BraseroTrackType));
1421
g_slist_free (list);
1423
/* add the post processing plugins */
1424
list = brasero_caps_add_processing_plugins_to_task (session,
1428
BRASERO_PLUGIN_RUN_AFTER_TARGET);
1429
retval = g_slist_concat (retval, list);
1431
if (last_caps->type.type == BRASERO_TRACK_TYPE_DISC && blanking) {
1432
retval = g_slist_insert_before (retval,
1433
g_slist_last (retval),
1441
brasero_burn_caps_new_checksuming_task (BraseroBurnCaps *self,
1442
BraseroBurnSession *session,
1445
BraseroTrackType track_type;
1446
BraseroPlugin *candidate;
1447
BraseroCaps *last_caps;
1448
BraseroTrackType input;
1449
guint checksum_type;
1450
BraseroTrack *track;
1458
brasero_burn_session_get_input_type (session, &input);
1459
BRASERO_BURN_LOG_WITH_TYPE (&input,
1460
BRASERO_PLUGIN_IO_NONE,
1461
"Creating checksuming task with input");
1463
/* first find a checksuming job that can output the type of required
1464
* checksum. Then go through the caps to see if the input type can be
1468
tracks = brasero_burn_session_get_tracks (session);
1469
if (g_slist_length (tracks) != 1) {
1472
BRASERO_BURN_ERROR_GENERAL,
1473
_("Only one track at a time can be checked"));
1477
/* get the required checksum type */
1478
track = tracks->data;
1479
checksum_type = brasero_track_get_checksum_type (track);
1482
for (iter = self->priv->tests; iter; iter = iter->next) {
1483
BraseroCapsTest *test;
1489
/* check this caps test supports the right checksum type */
1490
if (test->type & checksum_type) {
1491
links = test->links;
1497
/* we failed to find and create a proper task */
1498
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1503
brasero_track_get_type (track, &track_type);
1504
for (iter = links; iter; iter = iter->next) {
1505
BraseroCapsLink *link;
1510
/* NOTE: that shouldn't happen */
1514
BRASERO_BURN_LOG_TYPE (&link->caps->type, "Trying link to");
1516
/* Make sure we have a candidate */
1518
for (plugins = link->plugins; plugins; plugins = plugins->next) {
1519
BraseroPlugin *plugin;
1521
plugin = plugins->data;
1522
if (!brasero_plugin_get_active (plugin))
1525
/* note for checksuming task there is no group possible */
1528
else if (brasero_plugin_get_priority (plugin) >
1529
brasero_plugin_get_priority (candidate))
1536
/* see if it can handle the input or if it can be linked to
1537
* another plugin that can */
1538
if (brasero_caps_is_compatible_type (link->caps, &input)) {
1539
/* this is the right caps */
1540
last_caps = link->caps;
1544
/* don't go any further if that's a DISC type */
1545
if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
1548
/* the caps itself is not the right one so we try to
1549
* go through its links to find the right caps. */
1550
list = brasero_caps_find_best_link (link->caps,
1551
self->priv->group_id,
1553
BRASERO_BURN_FLAG_NONE,
1554
BRASERO_MEDIUM_NONE,
1556
BRASERO_PLUGIN_IO_ACCEPT_PIPE);
1558
last_caps = link->caps;
1564
/* no link worked failure */
1565
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_ERROR (session, error);
1568
/* we made it. Create task */
1569
task = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK,
1571
"action", BRASERO_TASK_ACTION_CHECKSUM,
1574
list = g_slist_reverse (list);
1575
for (iter = list; iter; iter = iter->next) {
1578
BraseroCapsLink *link;
1579
BraseroPlugin *candidate_plugin;
1580
BraseroTrackType *plugin_output;
1584
/* determine the plugin output */
1586
BraseroCapsLink *next_link;
1588
next_link = iter->next->data;
1589
plugin_output = &next_link->caps->type;
1592
plugin_output = &last_caps->type;
1594
/* find the best plugin */
1595
candidate_plugin = NULL;
1596
for (plugins = link->plugins; plugins; plugins = plugins->next) {
1597
BraseroPlugin *plugin;
1599
plugin = plugins->data;
1601
if (!brasero_plugin_get_active (plugin))
1604
if (!candidate_plugin)
1605
candidate_plugin = plugin;
1606
else if (brasero_plugin_get_priority (plugin) >
1607
brasero_plugin_get_priority (candidate_plugin))
1608
candidate_plugin = plugin;
1611
/* create the object */
1612
type = brasero_plugin_get_gtype (candidate_plugin);
1613
job = BRASERO_JOB (g_object_new (type,
1614
"output", plugin_output,
1616
g_signal_connect (job,
1618
G_CALLBACK (brasero_burn_caps_job_error_cb),
1621
brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
1623
BRASERO_BURN_LOG ("%s added to task", brasero_plugin_get_name (candidate_plugin));
1625
g_slist_free (list);
1627
/* Create the candidate */
1628
job = BRASERO_JOB (g_object_new (brasero_plugin_get_gtype (candidate),
1631
g_signal_connect (job,
1633
G_CALLBACK (brasero_burn_caps_job_error_cb),
1635
brasero_task_add_item (task, BRASERO_TASK_ITEM (job));
1641
brasero_caps_find_link (BraseroCaps *caps,
1642
BraseroBurnFlag session_flags,
1645
BraseroTrackType *input,
1646
BraseroPluginIOFlag io_flags)
1650
BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "find_link");
1652
/* Here we only make sure we have at least one link working. For a link
1653
* to be followed it must first:
1654
* - link to a caps with correct io flags
1655
* - have at least a plugin accepting the record flags if caps type is
1656
* a disc (that means that the link is the recording part)
1659
* - link to a caps equal to the input
1660
* - link to a caps (linking itself to another caps, ...) accepting the
1664
for (iter = caps->links; iter; iter = iter->next) {
1665
BraseroCapsLink *link;
1673
/* check that the link has some active plugin */
1674
if (!brasero_caps_link_active (link))
1677
/* since this link contains recorders, check that at least one
1678
* of them can handle the record flags */
1680
&& caps->type.type == BRASERO_TRACK_TYPE_DISC
1681
&& !brasero_caps_link_check_record_flags (link, session_flags, media))
1684
/* first see if that's the perfect fit:
1685
* - it must have the same caps (type + subtype)
1686
* - it must have the proper IO */
1687
if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
1689
&& !brasero_caps_link_check_data_flags (link, session_flags, media))
1692
else if (!brasero_caps_link_check_media_restrictions (link, media))
1695
if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
1696
&& brasero_caps_is_compatible_type (link->caps, input))
1699
/* we can't go further than a DISC type */
1700
if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
1703
if ((link->caps->flags & io_flags) == BRASERO_PLUGIN_IO_NONE)
1706
/* try to see where the inputs of this caps leads to */
1707
result = brasero_caps_find_link (link->caps,
1721
brasero_caps_try_output (BraseroBurnFlag session_flags,
1723
BraseroTrackType *output,
1724
BraseroTrackType *input,
1725
BraseroPluginIOFlag flags)
1730
/* here we search the start caps */
1731
caps = brasero_caps_find_start_caps (output);
1733
BRASERO_BURN_LOG ("No caps available");
1737
if (output->type == BRASERO_TRACK_TYPE_DISC)
1738
media = output->subtype.media;
1740
media = BRASERO_MEDIUM_FILE;
1742
return brasero_caps_find_link (caps,
1751
brasero_caps_try_output_with_blanking (BraseroBurnCaps *self,
1752
BraseroBurnSession *session,
1753
BraseroTrackType *output,
1754
BraseroTrackType *input,
1755
BraseroPluginIOFlag io_flags,
1760
BraseroCaps *last_caps;
1761
BraseroBurnFlag session_flags = BRASERO_BURN_FLAG_NONE;
1764
session_flags = brasero_burn_session_get_flags (session);
1766
result = brasero_caps_try_output (session_flags,
1774
/* we reached this point in two cases:
1775
* - if the disc cannot be handled
1776
* - if some flags are not handled
1777
* It is helpful only if:
1778
* - the disc was closed and no plugin can handle this type of
1779
* disc once closed (CD-R(W))
1780
* - there was the flag BLANK_BEFORE_WRITE set and no plugin can
1781
* handle this flag (means that the plugin should erase and
1782
* then write on its own. Basically that works only with
1783
* overwrite formatted discs, DVD+RW, ...) */
1784
if (output->type != BRASERO_TRACK_TYPE_DISC)
1787
/* output is a disc try with initial blanking */
1788
BRASERO_BURN_LOG ("Support for input/output failed.");
1790
/* apparently nothing can be done to reach our goal. Maybe that
1791
* is because we first have to blank the disc. If so add a blank
1792
* task to the others as a first step */
1793
if ((use_flags && !(session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE))
1794
|| brasero_burn_caps_can_blank (self, session) != BRASERO_BURN_OK)
1797
BRASERO_BURN_LOG ("Trying with initial blanking");
1799
/* retry with the same disc type but blank this time */
1800
media = output->subtype.media;
1801
media &= ~(BRASERO_MEDIUM_CLOSED|
1802
BRASERO_MEDIUM_APPENDABLE|
1803
BRASERO_MEDIUM_UNFORMATTED|
1804
BRASERO_MEDIUM_HAS_DATA|
1805
BRASERO_MEDIUM_HAS_AUDIO);
1806
media |= BRASERO_MEDIUM_BLANK;
1807
output->subtype.media = media;
1809
last_caps = brasero_caps_find_start_caps (output);
1813
return brasero_caps_find_link (last_caps,
1822
brasero_burn_caps_is_input_supported (BraseroBurnCaps *self,
1823
BraseroBurnSession *session,
1824
BraseroTrackType *input,
1828
BraseroTrackType output;
1829
BraseroPluginIOFlag io_flags;
1831
if (use_flags && !brasero_burn_caps_flags_check_for_drive (session))
1832
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
1834
if (!brasero_burn_session_is_dest_file (session)) {
1835
output.type = BRASERO_TRACK_TYPE_DISC;
1836
output.subtype.media = brasero_burn_session_get_dest_media (session);
1838
/* NOTE: for the special case where a disc could be rewritten
1839
* and cannot be handled as such but needs prior blanking, we
1840
* handle that situation in previous function.*/
1843
output.type = BRASERO_TRACK_TYPE_IMAGE;
1844
output.subtype.img_format = brasero_burn_session_get_output_format (session);
1847
if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
1848
io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
1850
io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
1852
BRASERO_BURN_LOG_TYPE (input, "Checking support for input");
1853
BRASERO_BURN_LOG_TYPE (&output, "and output");
1856
BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
1858
result = brasero_caps_try_output_with_blanking (self,
1865
BRASERO_BURN_LOG_TYPE (input, "Input not supported");
1866
return BRASERO_BURN_NOT_SUPPORTED;
1869
return BRASERO_BURN_OK;
1873
brasero_burn_caps_is_output_supported (BraseroBurnCaps *self,
1874
BraseroBurnSession *session,
1875
BraseroTrackType *output)
1878
BraseroTrackType input;
1879
BraseroPluginIOFlag io_flags;
1881
/* Here, we can't check if the drive supports the flags since the output
1882
* is hypothetical. There is no real medium. So forget the following :
1883
* if (!brasero_burn_caps_flags_check_for_drive (session))
1884
* BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
1885
* The only thing we could do would be to check some known forbidden
1886
* flags for some media provided the output type is DISC. */
1888
/* Here flags don't matter as we don't record anything. Even the IOFlags
1889
* since that can be checked later with brasero_burn_caps_get_flags. */
1890
if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
1891
io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
1893
io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
1895
brasero_burn_session_get_input_type (session, &input);
1896
BRASERO_BURN_LOG_TYPE (output, "Checking support for output");
1897
BRASERO_BURN_LOG_TYPE (&input, "and input");
1898
BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
1900
result = brasero_caps_try_output_with_blanking (self,
1907
BRASERO_BURN_LOG_TYPE (output, "Output not supported");
1908
return BRASERO_BURN_NOT_SUPPORTED;
1911
return BRASERO_BURN_OK;
1915
* This is only to be used in case one wants to copy using the same drive.
1916
* It determines the possible middle image type.
1919
static BraseroBurnResult
1920
brasero_burn_caps_is_session_supported_same_src_dest (BraseroBurnCaps *self,
1921
BraseroBurnSession *session,
1925
BraseroTrackType input;
1926
BraseroTrackType output;
1927
BraseroImageFormat format;
1928
BraseroBurnFlag session_flags;
1930
BRASERO_BURN_LOG ("Checking disc copy support with same source and destination");
1932
/* To determine if a CD/DVD can be copied using the same source/dest,
1933
* we first determine if can be imaged and then if this image can be
1934
* burnt to whatever medium type. */
1935
memset (&input, 0, sizeof (BraseroTrackType));
1936
brasero_burn_session_get_input_type (session, &input);
1937
BRASERO_BURN_LOG_TYPE (&input, "input");
1940
/* NOTE: DAO can be a problem. So just in case remove it. It is
1941
* not really useful in this context. What we want here is to
1942
* know whether a medium can be used given the input; only 1
1943
* flag is important here (MERGE) and can have consequences. */
1944
session_flags = brasero_burn_session_get_flags (session);
1945
session_flags &= ~BRASERO_BURN_FLAG_DAO;
1947
BRASERO_BURN_LOG_FLAGS (session_flags, "flags");
1950
session_flags = BRASERO_BURN_FLAG_NONE;
1952
/* Find one available output format */
1953
format = BRASERO_IMAGE_FORMAT_CDRDAO;
1954
output.type = BRASERO_TRACK_TYPE_IMAGE;
1956
for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
1959
output.subtype.img_format = format;
1961
BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
1962
supported = brasero_caps_try_output_with_blanking (self,
1966
BRASERO_PLUGIN_IO_ACCEPT_FILE,
1971
/* This format can be used to create an image. Check if can be
1972
* burnt now. Just find at least one medium. */
1973
for (iter = self->priv->caps_list; iter; iter = iter->next) {
1979
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
1982
result = brasero_caps_find_link (caps,
1985
caps->type.subtype.media,
1987
BRASERO_PLUGIN_IO_ACCEPT_FILE);
1989
BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
1990
"Tested medium (%s)",
1991
result ? "working":"not working");
1994
return BRASERO_BURN_OK;
1998
return BRASERO_BURN_NOT_SUPPORTED;
2002
brasero_burn_caps_is_session_supported (BraseroBurnCaps *self,
2003
BraseroBurnSession *session,
2007
BraseroTrackType input;
2008
BraseroTrackType output;
2009
BraseroPluginIOFlag io_flags;
2012
if (brasero_burn_session_same_src_dest_drive (session))
2013
return brasero_burn_caps_is_session_supported_same_src_dest (self, session, use_flags);
2015
if (use_flags && !brasero_burn_caps_flags_check_for_drive (session))
2016
BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
2018
/* Here flags don't matter as we don't record anything.
2019
* Even the IOFlags since that can be checked later with
2020
* brasero_burn_caps_get_flags. */
2021
if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
2022
io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
2024
io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
2026
brasero_burn_session_get_input_type (session, &input);
2028
if (!brasero_burn_session_is_dest_file (session)) {
2029
output.type = BRASERO_TRACK_TYPE_DISC;
2030
output.subtype.media = brasero_burn_session_get_dest_media (session);
2032
/* NOTE: for the special case where a disc could be rewritten
2033
* and cannot be handled as such but needs prior blanking, we
2034
* handle that situation in previous function.*/
2037
output.type = BRASERO_TRACK_TYPE_IMAGE;
2038
output.subtype.img_format = brasero_burn_session_get_output_format (session);
2041
BRASERO_BURN_LOG_TYPE (&output, "Checking support for session output");
2042
BRASERO_BURN_LOG_TYPE (&input, "and input");
2045
BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
2047
result = brasero_caps_try_output_with_blanking (self,
2054
BRASERO_BURN_LOG_TYPE (&output, "Output not supported");
2055
return BRASERO_BURN_NOT_SUPPORTED;
2058
return BRASERO_BURN_OK;
2062
brasero_burn_caps_get_required_media_type (BraseroBurnCaps *self,
2063
BraseroBurnSession *session)
2065
BraseroMedia required_media = BRASERO_MEDIUM_NONE;
2066
BraseroBurnFlag session_flags;
2067
BraseroPluginIOFlag io_flags;
2068
BraseroTrackType input;
2071
if (brasero_burn_session_is_dest_file (session))
2072
return BRASERO_MEDIUM_FILE;
2074
/* we try to determine here what type of medium is allowed to be burnt
2075
* to whether a CD or a DVD. Appendable, blank are not properties being
2076
* determined here. We just want it to be writable in a broad sense. */
2077
brasero_burn_session_get_input_type (session, &input);
2078
BRASERO_BURN_LOG_TYPE (&input, "Determining required media type for input");
2080
/* NOTE: BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE is a problem here since it
2081
* is only used if needed. Likewise DAO can be a problem. So just in
2082
* case remove them. They are not really useful in this context. What we
2083
* want here is to know which media can be used given the input; only 1
2084
* flag is important here (MERGE) and can have consequences. */
2085
session_flags = brasero_burn_session_get_flags (session);
2086
session_flags &= ~BRASERO_BURN_FLAG_DAO;
2088
BRASERO_BURN_LOG_FLAGS (session_flags, "and flags");
2090
if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
2091
io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
2093
io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
2095
for (iter = self->priv->caps_list; iter; iter = iter->next) {
2101
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
2104
/* Put BRASERO_MEDIUM_NONE so we can always succeed */
2105
result = brasero_caps_find_link (caps,
2108
BRASERO_MEDIUM_NONE,
2112
BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
2114
result ? "working":"not working");
2119
/* This caps work, add its subtype */
2120
required_media |= caps->type.subtype.media;
2123
/* filter as we are only interested in these */
2124
required_media &= BRASERO_MEDIUM_WRITABLE|
2128
return required_media;
2132
brasero_burn_caps_get_default_output_format (BraseroBurnCaps *self,
2133
BraseroBurnSession *session)
2135
BraseroTrackType source;
2136
BraseroTrackType output;
2137
BraseroBurnResult result;
2139
if (!brasero_burn_session_is_dest_file (session))
2140
return BRASERO_IMAGE_FORMAT_NONE;
2142
brasero_burn_session_get_input_type (session, &source);
2143
if (source.type == BRASERO_TRACK_TYPE_NONE)
2144
return BRASERO_IMAGE_FORMAT_NONE;
2146
if (source.type == BRASERO_TRACK_TYPE_IMAGE)
2147
return source.subtype.img_format;
2149
output.type = BRASERO_TRACK_TYPE_IMAGE;
2150
output.subtype.img_format = BRASERO_IMAGE_FORMAT_NONE;
2152
if (source.type == BRASERO_TRACK_TYPE_AUDIO) {
2153
/* If that's AUDIO only without VIDEO then return */
2154
if (!(source.subtype.audio_format & (BRASERO_VIDEO_FORMAT_UNDEFINED|BRASERO_VIDEO_FORMAT_VCD|BRASERO_VIDEO_FORMAT_VIDEO_DVD)))
2155
return BRASERO_IMAGE_FORMAT_NONE;
2157
/* Otherwise try all possible image types */
2158
output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
2159
for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
2160
output.subtype.img_format >>= 1) {
2162
result = brasero_burn_caps_is_output_supported (self,
2165
if (result == BRASERO_BURN_OK)
2166
return output.subtype.img_format;
2169
return BRASERO_IMAGE_FORMAT_NONE;
2172
if (source.type == BRASERO_TRACK_TYPE_DATA
2173
|| (source.type == BRASERO_TRACK_TYPE_DISC
2174
&& (source.subtype.media & BRASERO_MEDIUM_DVD))) {
2175
output.subtype.img_format = BRASERO_IMAGE_FORMAT_BIN;
2176
result = brasero_burn_caps_is_output_supported (self,
2179
if (result != BRASERO_BURN_OK)
2180
return BRASERO_IMAGE_FORMAT_NONE;
2182
return BRASERO_IMAGE_FORMAT_BIN;
2185
/* for the input which are CDs there are lots of possible formats */
2186
output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
2187
for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
2188
output.subtype.img_format >>= 1) {
2190
result = brasero_burn_caps_is_output_supported (self,
2193
if (result == BRASERO_BURN_OK)
2194
return output.subtype.img_format;
2197
return BRASERO_IMAGE_FORMAT_NONE;
2200
static BraseroCapsLink *
2201
brasero_caps_find_link_for_input (BraseroCaps *caps,
2206
for (links = caps->links; links; links = links->next) {
2207
BraseroCapsLink *link;
2210
if (link->caps == input)
2218
brasero_caps_has_active_input (BraseroCaps *caps,
2223
for (links = caps->links; links; links = links->next) {
2224
BraseroCapsLink *link;
2227
if (link->caps != input)
2230
if (brasero_caps_link_active (link))
2238
brasero_burn_caps_is_input (BraseroBurnCaps *self,
2243
for (iter = self->priv->caps_list; iter; iter = iter->next) {
2250
if (brasero_caps_has_active_input (tmp, input))
2257
static BraseroPluginIOFlag
2258
brasero_caps_get_flags (BraseroCaps *caps,
2259
BraseroBurnFlag session_flags,
2261
BraseroTrackType *input,
2262
BraseroPluginIOFlag flags,
2263
BraseroBurnFlag *supported,
2264
BraseroBurnFlag *compulsory)
2267
BraseroPluginIOFlag retval = BRASERO_PLUGIN_IO_NONE;
2269
/* First we must know if this link leads somewhere. It must
2270
* accept the already existing flags. If it does, see if it
2271
* accepts the input and if not, if one of its ancestors does */
2272
for (iter = caps->links; iter; iter = iter->next) {
2273
BraseroBurnFlag data_supported = BRASERO_BURN_FLAG_NONE;
2274
BraseroBurnFlag rec_compulsory = BRASERO_BURN_FLAG_ALL;
2275
BraseroBurnFlag rec_supported = BRASERO_BURN_FLAG_NONE;
2276
BraseroPluginIOFlag io_flags;
2277
BraseroCapsLink *link;
2284
/* check that the link has some active plugin */
2285
if (!brasero_caps_link_active (link))
2288
if (caps->type.type == BRASERO_TRACK_TYPE_DISC) {
2289
BraseroBurnFlag tmp;
2291
brasero_caps_link_get_record_flags (link,
2297
/* see if that link can handle the record flags.
2298
* NOTE: compulsory are not a failure in this case. */
2299
tmp = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
2300
if ((tmp & rec_supported) != tmp)
2304
if (link->caps->type.type == BRASERO_TRACK_TYPE_DATA) {
2305
BraseroBurnFlag tmp;
2307
brasero_caps_link_get_data_flags (link,
2312
/* see if that link can handle the data flags.
2313
* NOTE: compulsory are not a failure in this case. */
2314
tmp = session_flags & (BRASERO_BURN_FLAG_APPEND|
2315
BRASERO_BURN_FLAG_MERGE);
2317
if ((tmp & data_supported) != tmp)
2320
else if (!brasero_caps_link_check_media_restrictions (link, media))
2323
/* see if that's the perfect fit */
2324
if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
2325
&& brasero_caps_is_compatible_type (link->caps, input)) {
2326
/* special case for input that handle output/input */
2327
if (caps->type.type == BRASERO_TRACK_TYPE_DISC)
2328
retval |= BRASERO_PLUGIN_IO_ACCEPT_PIPE;
2330
retval |= caps->flags;
2332
(*compulsory) &= rec_compulsory;
2333
(*supported) |= data_supported|rec_supported;
2337
if ((link->caps->flags & flags) == BRASERO_PLUGIN_IO_NONE)
2340
/* we can't go further than a DISC type */
2341
if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
2344
/* try to see where the inputs of this caps leads to */
2345
io_flags = brasero_caps_get_flags (link->caps,
2352
if (io_flags == BRASERO_PLUGIN_IO_NONE)
2355
retval |= (io_flags & flags);
2356
(*compulsory) &= rec_compulsory;
2357
(*supported) |= data_supported|rec_supported;
2363
static BraseroBurnFlag
2364
brasero_burn_caps_flags_update_for_drive (BraseroBurnFlag flags,
2365
BraseroBurnSession *session)
2367
BraseroDrive *drive;
2368
BraseroMedium *medium;
2370
drive = brasero_burn_session_get_burner (session);
2374
medium = brasero_drive_get_medium (drive);
2378
return brasero_medium_supported_flags (medium, flags);
2381
static BraseroBurnResult
2382
brasero_caps_get_flags_for_disc (BraseroBurnFlag session_flags,
2384
BraseroTrackType *input,
2385
BraseroBurnFlag *supported,
2386
BraseroBurnFlag *compulsory)
2388
BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
2389
BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
2390
BraseroPluginIOFlag io_flags;
2391
BraseroTrackType output;
2394
/* create the output to find first caps */
2395
output.type = BRASERO_TRACK_TYPE_DISC;
2396
output.subtype.media = media;
2398
caps = brasero_caps_find_start_caps (&output);
2400
BRASERO_BURN_LOG_DISC_TYPE (media, "FLAGS: no caps could be found for");
2401
return BRASERO_BURN_NOT_SUPPORTED;
2404
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
2406
"FLAGS: trying caps");
2408
io_flags = brasero_caps_get_flags (caps,
2412
BRASERO_PLUGIN_IO_ACCEPT_FILE|
2413
BRASERO_PLUGIN_IO_ACCEPT_PIPE,
2417
if (io_flags == BRASERO_PLUGIN_IO_NONE) {
2418
BRASERO_BURN_LOG ("FLAGS: not supported");
2419
return BRASERO_BURN_NOT_SUPPORTED;
2422
/* RAW write mode should (must) only be used in this case */
2423
if ((supported_flags & BRASERO_BURN_FLAG_RAW)
2424
&& input->type == BRASERO_TRACK_TYPE_IMAGE
2425
&& input->subtype.img_format == BRASERO_IMAGE_FORMAT_CLONE) {
2426
supported_flags &= ~BRASERO_BURN_FLAG_DAO;
2427
compulsory_flags &= ~BRASERO_BURN_FLAG_DAO;
2428
compulsory_flags |= BRASERO_BURN_FLAG_RAW;
2431
supported_flags &= ~BRASERO_BURN_FLAG_RAW;
2433
if ((supported_flags & BRASERO_BURN_FLAG_DAO)
2434
&& input->type == BRASERO_TRACK_TYPE_AUDIO
2435
&& (input->subtype.img_format & BRASERO_METADATA_INFO)) {
2436
/* In this case, DAO is compulsory if we want to write CD-TEXT */
2437
compulsory_flags |= BRASERO_BURN_FLAG_DAO;
2440
if (io_flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE) {
2441
supported_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
2443
if ((io_flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) == 0)
2444
compulsory_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
2447
*supported |= supported_flags;
2448
*compulsory |= compulsory_flags;
2450
return BRASERO_BURN_OK;
2453
static BraseroBurnResult
2454
brasero_burn_caps_get_flags_for_medium (BraseroBurnCaps *self,
2456
BraseroBurnFlag session_flags,
2457
BraseroTrackType *input,
2458
BraseroBurnFlag *supported_flags,
2459
BraseroBurnFlag *compulsory_flags)
2461
BraseroBurnResult result;
2463
/* See if medium is supported out of the box */
2464
result = brasero_caps_get_flags_for_disc (session_flags,
2470
/* see if we can add BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE. Add it when:
2471
* - media can be blanked, it has audio or data and we're not merging
2472
* - media is not formatted and it can be blanked/formatted */
2473
if (BRASERO_BURN_CAPS_SHOULD_BLANK (media, session_flags)
2474
&& brasero_burn_caps_can_blank_real (self, media, session_flags) == BRASERO_BURN_OK)
2475
(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
2476
else if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
2477
return BRASERO_BURN_NOT_SUPPORTED;
2479
if (((*supported_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
2480
BraseroBurnFlag blank_compulsory = BRASERO_BURN_FLAG_NONE;
2481
BraseroBurnFlag blank_supported = BRASERO_BURN_FLAG_NONE;
2483
/* If BLANK flag is supported then MERGE/APPEND can't be compulsory */
2484
(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
2486
/* we reached this point in two cases:
2487
* - if the disc cannot be handled
2488
* - if some flags are not handled
2489
* It is helpful only if:
2490
* - the disc was closed and no plugin can handle this type of
2491
* disc once closed (CD-R(W))
2492
* - there was the flag BLANK_BEFORE_WRITE set and no plugin can
2493
* handle this flag (means that the plugin should erase and
2494
* then write on its own. Basically that works only with
2495
* overwrite formatted discs, DVD+RW, ...) */
2497
/* What's above is not entirely true. In fact we always need to
2498
* check even if we first succeeded. There are some cases like
2499
* CDRW where it's useful.
2500
* Ex: a CDRW with data appendable can be either appended (then
2501
* no DAO possible) or blanked and written (DAO possible). */
2503
(*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
2505
/* result here is the result of the first operation, so if it
2506
* failed, BLANK before becomes compulsory. */
2507
if (result != BRASERO_BURN_OK)
2508
(*compulsory_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
2510
/* pretends it is blank and formatted to see if it would work.
2511
* If it works then that means that the BLANK_BEFORE_WRITE flag
2513
media &= ~(BRASERO_MEDIUM_CLOSED|
2514
BRASERO_MEDIUM_APPENDABLE|
2515
BRASERO_MEDIUM_UNFORMATTED|
2516
BRASERO_MEDIUM_HAS_DATA|
2517
BRASERO_MEDIUM_HAS_AUDIO);
2518
media |= BRASERO_MEDIUM_BLANK;
2519
result = brasero_caps_get_flags_for_disc (session_flags,
2525
/* if both attempts failed, drop it */
2526
if (result != BRASERO_BURN_OK
2527
&& (((*compulsory_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)))
2530
/* need to add blanking flags */
2531
brasero_burn_caps_get_blanking_flags_real (self,
2536
(*supported_flags) |= blank_supported;
2537
(*compulsory_flags) |= blank_compulsory;
2539
else if (result != BRASERO_BURN_OK)
2542
if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) {
2543
/* make sure we remove MERGE/APPEND from supported and
2544
* compulsory since that's not possible anymore */
2545
(*supported_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
2546
(*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
2549
/* FIXME! we should restart the whole process if
2550
* ((session_flags & compulsory_flags) != compulsory_flags) since that
2551
* means that some supported files could be excluded but were not */
2553
return BRASERO_BURN_OK;
2556
static BraseroBurnResult
2557
brasero_burn_caps_get_flags_same_src_dest (BraseroBurnCaps *self,
2558
BraseroBurnSession *session,
2559
BraseroBurnFlag *supported_ret,
2560
BraseroBurnFlag *compulsory_ret)
2563
gboolean copy_supported;
2564
BraseroTrackType input;
2565
BraseroTrackType output;
2566
BraseroImageFormat format;
2567
BraseroBurnFlag session_flags;
2568
BraseroBurnFlag supported_final = BRASERO_BURN_FLAG_NONE;
2569
BraseroBurnFlag compulsory_final = BRASERO_BURN_FLAG_ALL;
2571
BRASERO_BURN_LOG ("Retrieving disc copy flags with same source and destination");
2573
/* To determine if a CD/DVD can be copied using the same source/dest,
2574
* we first determine if can be imaged and then what are the flags when
2575
* we can burn it to a particular medium type. */
2576
memset (&input, 0, sizeof (BraseroTrackType));
2577
brasero_burn_session_get_input_type (session, &input);
2578
BRASERO_BURN_LOG_TYPE (&input, "input");
2580
session_flags = brasero_burn_session_get_flags (session);
2581
BRASERO_BURN_LOG_FLAGS (session_flags, "(FLAGS) Session flags");
2583
/* Check the current flags are possible */
2584
if (session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_NO_TMP_FILES))
2585
return BRASERO_BURN_NOT_SUPPORTED;
2587
/* Check flags for all available format */
2588
format = BRASERO_IMAGE_FORMAT_CDRDAO;
2589
output.type = BRASERO_TRACK_TYPE_IMAGE;
2591
copy_supported = FALSE;
2592
for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
2593
BraseroBurnResult result;
2594
gboolean format_supported;
2596
/* check this image type is possible given the current flags */
2597
if (format != BRASERO_IMAGE_FORMAT_CLONE
2598
&& (session_flags & BRASERO_BURN_FLAG_RAW))
2601
output.subtype.img_format = format;
2603
/* NOTE: there is no need to get the flags here since there are
2604
* no specific DISC => IMAGE flags. We just want to know if that
2606
BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
2607
format_supported = brasero_caps_try_output_with_blanking (self,
2611
BRASERO_PLUGIN_IO_ACCEPT_FILE,
2613
if (!format_supported) {
2614
BRASERO_BURN_LOG_TYPE (&output, "Format not supported");
2618
/* This format can be used to create an image. Check if can be
2619
* burnt now. Just find at least one medium. */
2620
format_supported = FALSE;
2621
for (iter = self->priv->caps_list; iter; iter = iter->next) {
2622
BraseroBurnFlag compulsory;
2623
BraseroBurnFlag supported;
2627
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
2630
/* Merge all available flags for each possible medium type */
2631
supported = BRASERO_BURN_FLAG_NONE;
2632
compulsory = BRASERO_BURN_FLAG_NONE;
2633
result = brasero_burn_caps_get_flags_for_medium (self,
2634
caps->type.subtype.media,
2639
if (result != BRASERO_BURN_OK)
2642
format_supported = TRUE;
2643
supported_final |= supported;
2644
compulsory_final &= compulsory;
2647
BRASERO_BURN_LOG_TYPE (&output, "Format supported %i", format_supported);
2648
if (format_supported)
2649
copy_supported = TRUE;
2652
if (!copy_supported)
2653
return BRASERO_BURN_NOT_SUPPORTED;
2655
*supported_ret |= supported_final;
2656
*compulsory_ret |= compulsory_final;
2658
return BRASERO_BURN_OK;
2662
brasero_burn_caps_get_flags (BraseroBurnCaps *self,
2663
BraseroBurnSession *session,
2664
BraseroBurnFlag *supported,
2665
BraseroBurnFlag *compulsory)
2668
BraseroTrackType input;
2669
BraseroBurnResult result;
2671
BraseroBurnFlag session_flags;
2672
/* FIXME: what's the meaning of NOGRACE when outputting ? */
2673
BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_NONE;
2674
BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_DONT_OVERWRITE|
2675
BRASERO_BURN_FLAG_CHECK_SIZE|
2676
BRASERO_BURN_FLAG_NOGRACE;
2678
g_return_val_if_fail (BRASERO_IS_BURNCAPS (self), BRASERO_BURN_ERR);
2680
brasero_burn_session_get_input_type (session, &input);
2681
BRASERO_BURN_LOG_WITH_TYPE (&input,
2682
BRASERO_PLUGIN_IO_NONE,
2683
"FLAGS: searching available flags for input");
2685
if (brasero_burn_session_is_dest_file (session)) {
2686
BRASERO_BURN_LOG ("FLAGS: image required");
2688
/* In this case no APPEND/MERGE is possible */
2689
if (input.type == BRASERO_TRACK_TYPE_DISC)
2690
supported_flags |= BRASERO_BURN_FLAG_EJECT;
2692
*supported = supported_flags;
2693
*compulsory = compulsory_flags;
2695
BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2696
BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2697
return BRASERO_BURN_OK;
2700
supported_flags |= BRASERO_BURN_FLAG_EJECT;
2703
if (brasero_burn_session_same_src_dest_drive (session)) {
2704
result = brasero_burn_caps_get_flags_same_src_dest (self,
2709
/* These flags are of course never possible */
2710
supported_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
2711
BRASERO_BURN_FLAG_MERGE);
2712
compulsory_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
2713
BRASERO_BURN_FLAG_MERGE);
2715
if (result == BRASERO_BURN_OK) {
2716
BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2717
BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2719
*supported = supported_flags;
2720
*compulsory = compulsory_flags;
2723
BRASERO_BURN_LOG ("No available flags for copy");
2728
session_flags = brasero_burn_session_get_flags (session);
2729
BRASERO_BURN_LOG_FLAGS (session_flags, "FLAGS (session):");
2732
* - drive must support flags
2733
* - MERGE and BLANK are not possible together.
2734
* - APPEND and MERGE are compatible. MERGE wins
2735
* - APPEND and BLANK are incompatible */
2736
if (!brasero_burn_caps_flags_check_for_drive (session)) {
2737
BRASERO_BURN_LOG ("Session flags not supported by drive");
2738
return BRASERO_BURN_ERR;
2741
if ((session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
2742
&& (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE))
2743
return BRASERO_BURN_NOT_SUPPORTED;
2745
/* Let's get flags for recording */
2746
media = brasero_burn_session_get_dest_media (session);
2747
result = brasero_burn_caps_get_flags_for_medium (self,
2754
if (result != BRASERO_BURN_OK)
2757
supported_flags = brasero_burn_caps_flags_update_for_drive (supported_flags,
2761
*supported = supported_flags;
2764
*compulsory = compulsory_flags;
2766
BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2767
BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2768
return BRASERO_BURN_OK;
2772
* the following functions are used to register new caps
2776
brasero_burn_caps_sort (gconstpointer a, gconstpointer b)
2778
const BraseroCaps *caps_a = a;
2779
const BraseroCaps *caps_b = b;
2782
/* First put DISC (the most used caps) then IMAGE type; these two types
2783
* are the ones that most often searched. At the end of the list we put
2785
* Another (sub)rule is that for DATA, DISC, AUDIO we put a caps that is
2786
* encompassed by another before.
2789
result = caps_b->type.type - caps_a->type.type;
2793
switch (caps_a->type.type) {
2794
case BRASERO_TRACK_TYPE_DISC:
2795
if (BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) !=
2796
BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media))
2797
return ((gint32) BRASERO_MEDIUM_TYPE (caps_a->type.subtype.media) -
2798
(gint32) BRASERO_MEDIUM_TYPE (caps_b->type.subtype.media));
2800
if ((caps_a->type.subtype.media & BRASERO_MEDIUM_DVD)
2801
&& BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) !=
2802
BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media))
2803
return ((gint32) BRASERO_MEDIUM_SUBTYPE (caps_a->type.subtype.media) -
2804
(gint32) BRASERO_MEDIUM_SUBTYPE (caps_b->type.subtype.media));
2806
if (BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) !=
2807
BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media))
2808
return BRASERO_MEDIUM_ATTR (caps_a->type.subtype.media) -
2809
BRASERO_MEDIUM_ATTR (caps_b->type.subtype.media);
2811
if (BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) !=
2812
BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media))
2813
return BRASERO_MEDIUM_STATUS (caps_a->type.subtype.media) -
2814
BRASERO_MEDIUM_STATUS (caps_b->type.subtype.media);
2816
return (BRASERO_MEDIUM_INFO (caps_a->type.subtype.media) -
2817
BRASERO_MEDIUM_INFO (caps_b->type.subtype.media));
2819
case BRASERO_TRACK_TYPE_IMAGE:
2820
/* This way BIN subtype is always sorted at the end */
2821
return caps_a->type.subtype.img_format - caps_b->type.subtype.img_format;
2823
case BRASERO_TRACK_TYPE_AUDIO:
2824
if (caps_a->type.subtype.audio_format != caps_b->type.subtype.audio_format) {
2825
result = (caps_a->type.subtype.audio_format & caps_b->type.subtype.audio_format);
2826
if (result == caps_a->type.subtype.audio_format)
2828
else if (result == caps_b->type.subtype.audio_format)
2831
return (gint32) caps_a->type.subtype.audio_format -
2832
(gint32) caps_b->type.subtype.audio_format;
2836
case BRASERO_TRACK_TYPE_DATA:
2837
result = (caps_a->type.subtype.fs_type & caps_b->type.subtype.fs_type);
2838
if (result == caps_a->type.subtype.fs_type)
2840
else if (result == caps_b->type.subtype.fs_type)
2843
return (caps_a->type.subtype.fs_type - caps_b->type.subtype.fs_type);
2852
static BraseroCapsLink *
2853
brasero_caps_link_copy (BraseroCapsLink *link)
2855
BraseroCapsLink *retval;
2857
retval = g_new0 (BraseroCapsLink, 1);
2858
retval->plugins = g_slist_copy (link->plugins);
2859
retval->caps = link->caps;
2865
brasero_caps_link_list_duplicate (BraseroCaps *dest, BraseroCaps *src)
2869
for (iter = src->links; iter; iter = iter->next) {
2870
BraseroCapsLink *link;
2873
dest->links = g_slist_prepend (dest->links, brasero_caps_link_copy (link));
2877
static BraseroCaps *
2878
brasero_caps_copy (BraseroCaps *caps)
2880
BraseroCaps *retval;
2882
retval = g_new0 (BraseroCaps, 1);
2883
retval->flags = caps->flags;
2884
memcpy (&retval->type, &caps->type, sizeof (BraseroTrackType));
2885
retval->modifiers = g_slist_copy (caps->modifiers);
2891
brasero_caps_replicate_modifiers (BraseroCaps *dest, BraseroCaps *src)
2895
for (iter = src->modifiers; iter; iter = iter->next) {
2896
BraseroPlugin *plugin;
2898
plugin = iter->data;
2900
if (g_slist_find (dest->modifiers, plugin))
2903
dest->modifiers = g_slist_prepend (dest->modifiers, plugin);
2908
brasero_caps_replicate_links (BraseroCaps *dest, BraseroCaps *src)
2910
BraseroBurnCaps *self;
2913
self = brasero_burn_caps_get_default ();
2915
brasero_caps_link_list_duplicate (dest, src);
2917
for (iter = self->priv->caps_list; iter; iter = iter->next) {
2918
BraseroCaps *iter_caps;
2921
iter_caps = iter->data;
2922
if (iter_caps == src)
2925
for (links = iter_caps->links; links; links = links->next) {
2926
BraseroCapsLink *link;
2929
if (link->caps == src) {
2930
BraseroCapsLink *copy;
2932
copy = brasero_caps_link_copy (link);
2934
iter_caps->links = g_slist_prepend (iter_caps->links, copy);
2941
brasero_caps_replicate_tests (BraseroCaps *dest, BraseroCaps *src)
2943
BraseroBurnCaps *self;
2946
self = brasero_burn_caps_get_default ();
2948
for (iter = self->priv->tests; iter; iter = iter->next) {
2949
BraseroCapsTest *test;
2953
for (links = test->links; links; links = links->next) {
2954
BraseroCapsLink *link;
2957
if (link->caps == src) {
2958
BraseroCapsLink *copy;
2960
copy = brasero_caps_link_copy (link);
2962
test->links = g_slist_prepend (test->links, copy);
2968
static BraseroCaps *
2969
brasero_caps_copy_deep (BraseroCaps *caps)
2971
BraseroCaps *retval;
2972
BraseroBurnCaps *self;
2974
self = brasero_burn_caps_get_default ();
2976
retval = brasero_caps_copy (caps);
2977
brasero_caps_replicate_links (retval, caps);
2978
brasero_caps_replicate_tests (retval, caps);
2983
brasero_caps_list_check_io (GSList *list, BraseroPluginIOFlag flags)
2986
BraseroBurnCaps *self;
2988
self = brasero_burn_caps_get_default ();
2990
/* in this function we create the caps with the missing IO. All in the
2991
* list have something in common with flags. */
2992
for (iter = list; iter; iter = iter->next) {
2994
BraseroPluginIOFlag common;
2997
common = caps->flags & flags;
2998
if (common != caps->flags) {
2999
BraseroCaps *new_caps;
3001
/* (common == flags) && common != caps->flags
3002
* caps->flags encompasses flags: Split the caps in two
3003
* and only keep the interesting part */
3004
caps->flags &= ~common;
3006
/* this caps has changed and needs to be sorted again */
3007
self->priv->caps_list = g_slist_sort (self->priv->caps_list,
3008
brasero_burn_caps_sort);
3010
new_caps = brasero_caps_copy_deep (caps);
3011
new_caps->flags = common;
3013
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3015
brasero_burn_caps_sort);
3017
list = g_slist_prepend (list, new_caps);
3019
else if (common != flags) {
3020
GSList *node, *next;
3021
BraseroPluginIOFlag complement = flags;
3023
complement &= ~common;
3024
for (node = list; node; node = next) {
3033
if (caps->type.type != tmp->type.type
3034
|| caps->type.subtype.media != tmp->type.subtype.media)
3037
/* substract the flags and relocate them at the
3038
* head of the list since we don't need to look
3040
complement &= ~(tmp->flags);
3041
list = g_slist_remove (list, tmp);
3042
list = g_slist_prepend (list, tmp);
3045
if (complement != BRASERO_PLUGIN_IO_NONE) {
3046
BraseroCaps *new_caps;
3048
/* common == caps->flags && common != flags.
3049
* Flags encompasses caps->flags. So we need to
3050
* create a new caps for this type with the
3051
* substraction of flags if the other part isn't
3053
new_caps = brasero_caps_copy (caps);
3054
new_caps->flags = flags & (~common);
3055
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3057
brasero_burn_caps_sort);
3059
list = g_slist_prepend (list, new_caps);
3068
brasero_caps_image_new (BraseroPluginIOFlag flags,
3069
BraseroImageFormat format)
3071
BraseroImageFormat remaining_format;
3072
BraseroBurnCaps *self;
3073
GSList *retval = NULL;
3076
BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_IMAGE,
3079
"New caps required");
3081
self = brasero_burn_caps_get_default ();
3083
remaining_format = format;
3085
/* We have to search all caps with or related to the format */
3086
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3088
BraseroImageFormat common;
3089
BraseroPluginIOFlag common_io;
3092
if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE)
3095
common_io = caps->flags & flags;
3096
if (common_io == BRASERO_PLUGIN_IO_NONE)
3099
common = (caps->type.subtype.img_format & format);
3100
if (common == BRASERO_IMAGE_FORMAT_NONE)
3103
if (common != caps->type.subtype.img_format) {
3104
/* img_format encompasses format. Split it in two and
3105
* keep caps with common format */
3106
SUBSTRACT (caps->type.subtype.img_format, common);
3107
self->priv->caps_list = g_slist_sort (self->priv->caps_list,
3108
brasero_burn_caps_sort);
3110
caps = brasero_caps_copy_deep (caps);
3111
caps->type.subtype.img_format = common;
3113
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3115
brasero_burn_caps_sort);
3118
retval = g_slist_prepend (retval, caps);
3119
remaining_format &= ~common;
3122
/* Now we make sure that all these new or already
3123
* existing caps have the proper IO Flags */
3124
retval = brasero_caps_list_check_io (retval, flags);
3126
if (remaining_format != BRASERO_IMAGE_FORMAT_NONE) {
3129
caps = g_new0 (BraseroCaps, 1);
3130
caps->flags = flags;
3131
caps->type.subtype.img_format = remaining_format;
3132
caps->type.type = BRASERO_TRACK_TYPE_IMAGE;
3134
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3136
brasero_burn_caps_sort);
3137
retval = g_slist_prepend (retval, caps);
3139
BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
3146
brasero_caps_audio_new (BraseroPluginIOFlag flags,
3147
BraseroAudioFormat format)
3150
GSList *retval = NULL;
3151
BraseroBurnCaps *self;
3152
GSList *encompassing = NULL;
3153
gboolean have_the_one = FALSE;
3155
BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_AUDIO,
3158
"New caps required");
3160
self = brasero_burn_caps_get_default ();
3162
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3164
BraseroAudioFormat common;
3165
BraseroPluginIOFlag common_io;
3166
BraseroAudioFormat common_audio;
3167
BraseroAudioFormat common_video;
3171
if (caps->type.type != BRASERO_TRACK_TYPE_AUDIO)
3174
common_io = (flags & caps->flags);
3175
if (common_io == BRASERO_PLUGIN_IO_NONE)
3178
if (caps->type.subtype.audio_format == format) {
3179
/* that's the perfect fit */
3180
have_the_one = TRUE;
3181
retval = g_slist_prepend (retval, caps);
3185
/* Search caps strictly encompassed or encompassing our format
3186
* NOTE: make sure that if there is a VIDEO stream in one of
3187
* them, the other does have a VIDEO stream too. */
3188
common_audio = BRASERO_AUDIO_CAPS_AUDIO (caps->type.subtype.audio_format) &
3189
BRASERO_AUDIO_CAPS_AUDIO (format);
3190
if (common_audio == BRASERO_AUDIO_FORMAT_NONE
3191
&& (BRASERO_AUDIO_CAPS_AUDIO (caps->type.subtype.audio_format)
3192
|| BRASERO_AUDIO_CAPS_AUDIO (format)))
3195
common_video = BRASERO_AUDIO_CAPS_VIDEO (caps->type.subtype.audio_format) &
3196
BRASERO_AUDIO_CAPS_VIDEO (format);
3198
if (common_video == BRASERO_AUDIO_FORMAT_NONE
3199
&& (BRASERO_AUDIO_CAPS_VIDEO (caps->type.subtype.audio_format)
3200
|| BRASERO_AUDIO_CAPS_VIDEO (format)))
3203
/* Likewise... that must be common */
3204
if ((caps->type.subtype.audio_format & BRASERO_METADATA_INFO) != (format & BRASERO_METADATA_INFO))
3207
common = common_audio|common_video|(format & BRASERO_METADATA_INFO);
3209
/* encompassed caps just add it to retval */
3210
if (caps->type.subtype.audio_format == common)
3211
retval = g_slist_prepend (retval, caps);
3213
/* encompassing caps keep it if we need to create perfect fit */
3214
if (format == common)
3215
encompassing = g_slist_prepend (encompassing, caps);
3218
/* Now we make sure that all these new or already
3219
* existing caps have the proper IO Flags */
3220
retval = brasero_caps_list_check_io (retval, flags);
3222
if (!have_the_one) {
3225
caps = g_new0 (BraseroCaps, 1);
3226
caps->flags = flags;
3227
caps->type.subtype.audio_format = format;
3228
caps->type.type = BRASERO_TRACK_TYPE_AUDIO;
3231
for (iter = encompassing; iter; iter = iter->next) {
3232
BraseroCaps *iter_caps;
3234
iter_caps = iter->data;
3235
brasero_caps_replicate_links (caps, iter_caps);
3236
brasero_caps_replicate_tests (caps, iter_caps);
3237
brasero_caps_replicate_modifiers (caps, iter_caps);
3241
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3243
brasero_burn_caps_sort);
3244
retval = g_slist_prepend (retval, caps);
3246
BRASERO_BURN_LOG_TYPE (&caps->type, "Created new caps");
3249
g_slist_free (encompassing);
3254
brasero_caps_data_new (BraseroImageFS fs_type)
3257
GSList *retval = NULL;
3258
BraseroBurnCaps *self;
3259
GSList *encompassing = NULL;
3260
gboolean have_the_one = FALSE;
3262
BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_DATA,
3264
BRASERO_PLUGIN_IO_NONE,
3265
"New caps required");
3266
self = brasero_burn_caps_get_default ();
3268
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3270
BraseroImageFS common;
3274
if (caps->type.type != BRASERO_TRACK_TYPE_DATA)
3277
if (caps->type.subtype.fs_type == fs_type) {
3278
/* that's the perfect fit */
3279
have_the_one = TRUE;
3280
retval = g_slist_prepend (retval, caps);
3284
/* search caps strictly encompassing our format ... */
3285
common = caps->type.subtype.fs_type & fs_type;
3286
if (common == BRASERO_IMAGE_FS_NONE)
3289
/* encompassed caps just add it to retval */
3290
if (caps->type.subtype.fs_type == common)
3291
retval = g_slist_prepend (retval, caps);
3293
/* encompassing caps keep it if we need to create perfect fit */
3294
if (fs_type == common)
3295
encompassing = g_slist_prepend (encompassing, caps);
3298
if (!have_the_one) {
3301
caps = g_new0 (BraseroCaps, 1);
3302
caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
3303
caps->type.type = BRASERO_TRACK_TYPE_DATA;
3304
caps->type.subtype.fs_type = fs_type;
3307
for (iter = encompassing; iter; iter = iter->next) {
3308
BraseroCaps *iter_caps;
3310
iter_caps = iter->data;
3311
brasero_caps_replicate_links (caps, iter_caps);
3312
brasero_caps_replicate_tests (caps, iter_caps);
3313
brasero_caps_replicate_modifiers (caps, iter_caps);
3317
self->priv->caps_list = g_slist_insert_sorted (self->priv->caps_list,
3319
brasero_burn_caps_sort);
3320
retval = g_slist_prepend (retval, caps);
3323
g_slist_free (encompassing);
3328
brasero_caps_disc_lookup_or_create (GSList *retval,
3335
brasero_burn_caps_get_default ();
3337
for (iter = default_caps->priv->caps_list; iter; iter = iter->next) {
3340
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
3343
if (caps->type.subtype.media == media) {
3344
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
3347
return g_slist_prepend (retval, caps);
3351
caps = g_new0 (BraseroCaps, 1);
3352
caps->flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
3353
caps->type.type = BRASERO_TRACK_TYPE_DISC;
3354
caps->type.subtype.media = media;
3356
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
3360
default_caps->priv->caps_list = g_slist_prepend (default_caps->priv->caps_list, caps);
3361
return g_slist_prepend (retval, caps);
3365
brasero_caps_disc_new (BraseroMedia type)
3367
GSList *retval = NULL;
3371
list = brasero_media_get_all_list (type);
3372
for (iter = list; iter; iter = iter->next) {
3373
BraseroMedia medium;
3375
medium = GPOINTER_TO_INT (iter->data);
3376
retval = brasero_caps_disc_lookup_or_create (retval, medium);
3378
g_slist_free (list);
3384
* these functions are to create links
3388
brasero_caps_create_links (BraseroCaps *output,
3390
BraseroPlugin *plugin)
3392
for (; inputs; inputs = inputs->next) {
3394
BraseroCapsLink *link;
3396
input = inputs->data;
3398
if (output == input) {
3399
BRASERO_BURN_LOG ("Same input and output for link. Dropping");
3403
if (input->flags == output->flags
3404
&& input->type.type == output->type.type
3405
&& input->type.subtype.media == output->type.subtype.media)
3406
BRASERO_BURN_LOG ("Recursive link");
3408
link = brasero_caps_find_link_for_input (output, input);
3412
/* Mainly for extra debugging */
3413
BRASERO_BURN_LOG_TYPE (&output->type, "Linking");
3414
BRASERO_BURN_LOG_TYPE (&input->type, "to");
3415
BRASERO_BURN_LOG ("with %s", brasero_plugin_get_name (plugin));
3420
link = g_new0 (BraseroCapsLink, 1);
3422
link->plugins = g_slist_prepend (NULL, plugin);
3424
output->links = g_slist_prepend (output->links, link);
3427
link->plugins = g_slist_prepend (link->plugins, plugin);
3432
brasero_plugin_link_caps (BraseroPlugin *plugin,
3436
/* we make sure the caps exists and if not we create them */
3437
for (; outputs; outputs = outputs->next) {
3438
BraseroCaps *output;
3440
output = outputs->data;
3441
brasero_caps_create_links (output, inputs, plugin);
3446
brasero_plugin_blank_caps (BraseroPlugin *plugin,
3449
for (; caps_list; caps_list = caps_list->next) {
3451
BraseroCapsLink *link;
3453
caps = caps_list->data;
3455
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
3458
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
3460
"Adding blank caps for");
3462
/* we need to find the link whose caps is NULL */
3463
link = brasero_caps_find_link_for_input (caps, NULL);
3465
link = g_new0 (BraseroCapsLink, 1);
3467
link->plugins = g_slist_prepend (NULL, plugin);
3469
caps->links = g_slist_prepend (caps->links, link);
3472
link->plugins = g_slist_prepend (link->plugins, plugin);
3477
brasero_plugin_process_caps (BraseroPlugin *plugin,
3480
for (; caps_list; caps_list = caps_list->next) {
3483
caps = caps_list->data;
3484
caps->modifiers = g_slist_prepend (caps->modifiers, plugin);
3489
brasero_plugin_check_caps (BraseroPlugin *plugin,
3490
BraseroChecksumType type,
3493
BraseroCapsTest *test = NULL;
3494
BraseroBurnCaps *self;
3497
/* Find the the BraseroCapsTest for this type; if none create it */
3498
self = brasero_burn_caps_get_default ();
3499
for (iter = self->priv->tests; iter; iter = iter->next) {
3500
BraseroCapsTest *tmp;
3503
if (tmp->type == type) {
3510
test = g_new0 (BraseroCapsTest, 1);
3512
self->priv->tests = g_slist_prepend (self->priv->tests, test);
3515
g_object_unref (self);
3517
for (; caps_list; caps_list = caps_list->next) {
3520
BraseroCapsLink *link;
3522
caps = caps_list->data;
3524
/* try to find a link for the above caps, if none create one */
3526
for (links = test->links; links; links = links->next) {
3527
BraseroCapsLink *tmp;
3530
if (tmp->caps == caps) {
3537
link = g_new0 (BraseroCapsLink, 1);
3539
test->links = g_slist_prepend (test->links, link);
3542
link->plugins = g_slist_prepend (link->plugins, plugin);
3547
* This is to register a plugin group
3548
* This function is only define here (though it's implemented in burn-plugin.c).
3552
brasero_plugin_set_group (BraseroPlugin *plugin, gint group_id);
3555
brasero_plugin_register_group (BraseroPlugin *plugin,
3559
BraseroBurnCaps *self;
3562
brasero_plugin_set_group (plugin, 0);
3566
self = brasero_burn_caps_get_default ();
3568
if (!self->priv->groups)
3569
self->priv->groups = g_hash_table_new_full (g_str_hash,
3574
retval = GPOINTER_TO_INT (g_hash_table_lookup (self->priv->groups, name));
3576
brasero_plugin_set_group (plugin, retval);
3580
g_hash_table_insert (self->priv->groups,
3582
GINT_TO_POINTER (g_hash_table_size (self->priv->groups) + 1));
3584
/* see if we have a group id now */
3585
if (!self->priv->group_id
3586
&& self->priv->group_str
3587
&& !strcmp (name, self->priv->group_str))
3588
self->priv->group_id = g_hash_table_size (self->priv->groups) + 1;
3590
brasero_plugin_set_group (plugin, g_hash_table_size (self->priv->groups) + 1);
3594
* This is to find out what are the capacities of a plugin
3595
* Declared in brasero-plugin-private.h
3599
brasero_plugin_can_burn (BraseroPlugin *plugin)
3602
BraseroBurnCaps *self;
3604
self = brasero_burn_caps_get_default ();
3606
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3611
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
3614
for (links = caps->links; links; links = links->next) {
3615
BraseroCapsLink *link;
3620
/* see if the plugin is in the link by going through the list */
3621
for (plugins = link->plugins; plugins; plugins = plugins->next) {
3624
tmp = plugins->data;
3626
return BRASERO_BURN_OK;
3631
return BRASERO_BURN_NOT_SUPPORTED;
3635
brasero_plugin_can_image (BraseroPlugin *plugin)
3638
BraseroBurnCaps *self;
3640
self = brasero_burn_caps_get_default ();
3641
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3642
BraseroTrackDataType destination;
3647
if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
3648
&& caps->type.type != BRASERO_TRACK_TYPE_AUDIO
3649
&& caps->type.type != BRASERO_TRACK_TYPE_DATA)
3652
destination = caps->type.type;
3653
for (links = caps->links; links; links = links->next) {
3654
BraseroCapsLink *link;
3659
|| link->caps->type.type == destination)
3662
/* see if the plugin is in the link by going through the list */
3663
for (plugins = link->plugins; plugins; plugins = plugins->next) {
3666
tmp = plugins->data;
3668
return BRASERO_BURN_OK;
3673
return BRASERO_BURN_NOT_SUPPORTED;
3677
brasero_plugin_can_convert (BraseroPlugin *plugin)
3680
BraseroBurnCaps *self;
3682
self = brasero_burn_caps_get_default ();
3683
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3684
BraseroTrackDataType destination;
3689
if (caps->type.type != BRASERO_TRACK_TYPE_IMAGE
3690
&& caps->type.type != BRASERO_TRACK_TYPE_AUDIO)
3693
destination = caps->type.type;
3694
for (links = caps->links; links; links = links->next) {
3695
BraseroCapsLink *link;
3700
|| link->caps->type.type != destination)
3703
/* see if the plugin is in the link by going through the list */
3704
for (plugins = link->plugins; plugins; plugins = plugins->next) {
3707
tmp = plugins->data;
3709
return BRASERO_BURN_OK;
3714
return BRASERO_BURN_NOT_SUPPORTED;
3718
* Used to test what the library can do based on the medium type.
3719
* Returns BRASERO_MEDIUM_WRITABLE if the disc can be written
3720
* and / or BRASERO_MEDIUM_REWRITABLE if the disc can be erased.
3721
* Declared in burn-media.h.
3725
brasero_media_capabilities (BraseroMedia media)
3729
BraseroMedia retval;
3730
BraseroBurnCaps *self;
3731
BraseroCaps *caps = NULL;
3733
self = brasero_burn_caps_get_default ();
3735
retval = BRASERO_MEDIUM_NONE;
3736
BRASERO_BURN_LOG_DISC_TYPE (media, "checking media caps for");
3738
/* we're only interested in DISC caps. There should be only one caps fitting */
3739
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3741
if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
3744
if ((media & caps->type.subtype.media) == media)
3751
return BRASERO_MEDIUM_NONE;
3753
/* check the links */
3754
for (links = caps->links; links; links = links->next) {
3757
BraseroCapsLink *link;
3761
/* this link must have at least one active plugin to be valid
3762
* plugins are not sorted but in this case we don't need them
3763
* to be. we just need one active if another is with a better
3764
* priority all the better. */
3766
for (plugins = link->plugins; plugins; plugins = plugins->next) {
3767
BraseroPlugin *plugin;
3769
plugin = plugins->data;
3770
if (brasero_plugin_get_active (plugin)) {
3771
/* this link is valid */
3781
/* means that it can be blanked */
3782
retval |= BRASERO_MEDIUM_REWRITABLE;
3786
/* means it can be written. NOTE: if this disc has already some
3787
* data on it, it even means it can be appended */
3788
retval |= BRASERO_MEDIUM_WRITABLE;
3795
* This function is declared in burn-basics.h
3796
* It can be used to determine whether or not brasero can do any checksuming.
3800
brasero_burn_library_can_checksum (void)
3803
BraseroBurnCaps *self;
3805
self = brasero_burn_caps_get_default ();
3807
if (self->priv->tests == NULL)
3810
for (iter = self->priv->tests; iter; iter = iter->next) {
3811
BraseroCapsTest *tmp;
3815
for (links = tmp->links; links; links = links->next) {
3816
BraseroCapsLink *link;
3819
if (brasero_caps_link_active (link))
3828
* This is declared in burn-basics.c. It's private stuff that needs to be
3829
* defined in this file. For debugging use only.
3833
brasero_caps_list_dump (void)
3836
BraseroBurnCaps *self;
3838
self = brasero_burn_caps_get_default ();
3839
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3843
BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
3845
"Created %i links pointing to",
3846
g_slist_length (caps->links));
3852
* Declared in burn-track.h
3853
* This is to determine whether of not a track type is supported
3857
brasero_track_type_is_supported (BraseroTrackType *type)
3860
BraseroBurnCaps *self;
3862
self = brasero_burn_caps_get_default ();
3864
for (iter = self->priv->caps_list; iter; iter = iter->next) {
3869
if (brasero_caps_is_compatible_type (caps, type)
3870
&& brasero_burn_caps_is_input (self, caps))
3871
return BRASERO_BURN_OK;
3874
return BRASERO_BURN_ERR;