1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Libbrasero-burn
4 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5 *
6 * Libbrasero-burn is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12 * GStreamer plugins to be used and distributed together with GStreamer
13 * and Libbrasero-burn. This permission is above and beyond the permissions granted
14 * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15 * you may extend this exception to your version of the code, but you are not
16 * obligated to do so. If you do not wish to do so, delete this exception
17 * statement from your version.
18 *
19 * Libbrasero-burn is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to:
26 * The Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor
28 * Boston, MA 02110-1301, USA.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #include <string.h>
36
37 #include <glib.h>
38 #include <glib/gi18n.h>
39
40 #include "burn-caps.h"
41 #include "burn-debug.h"
42 #include "brasero-plugin.h"
43 #include "brasero-plugin-private.h"
44 #include "brasero-plugin-information.h"
45 #include "brasero-session-helper.h"
46
47 #define BRASERO_BURN_CAPS_SHOULD_BLANK(media_MACRO, flags_MACRO) \
48 ((media_MACRO & BRASERO_MEDIUM_UNFORMATTED) || \
49 ((media_MACRO & (BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) && \
50 (flags_MACRO & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND)) == FALSE))
51
52 #define BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES(session) \
53 { \
54 brasero_burn_session_log (session, "Unsupported type of task operation"); \
55 BRASERO_BURN_LOG ("Unsupported type of task operation"); \
56 return BRASERO_BURN_NOT_SUPPORTED; \
57 }
58
59 static BraseroBurnResult
brasero_burn_caps_get_blanking_flags_real(BraseroBurnCaps * caps,gboolean ignore_errors,BraseroMedia media,BraseroBurnFlag session_flags,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)60 brasero_burn_caps_get_blanking_flags_real (BraseroBurnCaps *caps,
61 gboolean ignore_errors,
62 BraseroMedia media,
63 BraseroBurnFlag session_flags,
64 BraseroBurnFlag *supported,
65 BraseroBurnFlag *compulsory)
66 {
67 GSList *iter;
68 gboolean supported_media;
69 BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
70 BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
71
72 BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
73 if (media == BRASERO_MEDIUM_NONE) {
74 BRASERO_BURN_LOG ("Blanking not possible: no media");
75 if (supported)
76 *supported = BRASERO_BURN_FLAG_NONE;
77 if (compulsory)
78 *compulsory = BRASERO_BURN_FLAG_NONE;
79 return BRASERO_BURN_NOT_SUPPORTED;
80 }
81
82 supported_media = FALSE;
83 for (iter = caps->priv->caps_list; iter; iter = iter->next) {
84 BraseroMedia caps_media;
85 BraseroCaps *caps;
86 GSList *links;
87
88 caps = iter->data;
89 if (!brasero_track_type_get_has_medium (&caps->type))
90 continue;
91
92 caps_media = brasero_track_type_get_medium_type (&caps->type);
93 if ((media & caps_media) != media)
94 continue;
95
96 for (links = caps->links; links; links = links->next) {
97 GSList *plugins;
98 BraseroCapsLink *link;
99
100 link = links->data;
101
102 if (link->caps != NULL)
103 continue;
104
105 supported_media = TRUE;
106 /* don't need the plugins to be sorted since we go
107 * through all the plugin list to get all blanking flags
108 * available. */
109 for (plugins = link->plugins; plugins; plugins = plugins->next) {
110 BraseroPlugin *plugin;
111 BraseroBurnFlag supported_plugin;
112 BraseroBurnFlag compulsory_plugin;
113
114 plugin = plugins->data;
115 if (!brasero_plugin_get_active (plugin, ignore_errors))
116 continue;
117
118 if (!brasero_plugin_get_blank_flags (plugin,
119 media,
120 session_flags,
121 &supported_plugin,
122 &compulsory_plugin))
123 continue;
124
125 supported_flags |= supported_plugin;
126 compulsory_flags &= compulsory_plugin;
127 }
128 }
129 }
130
131 if (!supported_media) {
132 BRASERO_BURN_LOG ("media blanking not supported");
133 return BRASERO_BURN_NOT_SUPPORTED;
134 }
135
136 /* This is a special case that is in MMC specs:
137 * DVD-RW sequential must be fully blanked
138 * if we really want multisession support. */
139 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW)
140 && (session_flags & BRASERO_BURN_FLAG_MULTI)) {
141 if (compulsory_flags & BRASERO_BURN_FLAG_FAST_BLANK) {
142 BRASERO_BURN_LOG ("fast media blanking only supported but multisession required for DVDRW");
143 return BRASERO_BURN_NOT_SUPPORTED;
144 }
145
146 supported_flags &= ~BRASERO_BURN_FLAG_FAST_BLANK;
147
148 BRASERO_BURN_LOG ("removed fast blank for a DVDRW with multisession");
149 }
150
151 if (supported)
152 *supported = supported_flags;
153 if (compulsory)
154 *compulsory = compulsory_flags;
155
156 return BRASERO_BURN_OK;
157 }
158
159 /**
160 * brasero_burn_session_get_blank_flags:
161 * @session: a #BraseroBurnSession
162 * @supported: a #BraseroBurnFlag
163 * @compulsory: a #BraseroBurnFlag
164 *
165 * Given the various parameters stored in @session,
166 * stores in @supported and @compulsory, the flags
167 * that can be used (@supported) and must be used
168 * (@compulsory) when blanking the medium in the
169 * #BraseroDrive (set with brasero_burn_session_set_burner ()).
170 *
171 * Return value: a #BraseroBurnResult.
172 * BRASERO_BURN_OK if the retrieval was successful.
173 * BRASERO_BURN_ERR otherwise.
174 **/
175
176 BraseroBurnResult
brasero_burn_session_get_blank_flags(BraseroBurnSession * session,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)177 brasero_burn_session_get_blank_flags (BraseroBurnSession *session,
178 BraseroBurnFlag *supported,
179 BraseroBurnFlag *compulsory)
180 {
181 BraseroMedia media;
182 BraseroBurnCaps *self;
183 BraseroBurnResult result;
184 BraseroBurnFlag session_flags;
185
186 media = brasero_burn_session_get_dest_media (session);
187 BRASERO_BURN_LOG_DISC_TYPE (media, "Getting blanking flags for");
188
189 if (media == BRASERO_MEDIUM_NONE) {
190 BRASERO_BURN_LOG ("Blanking not possible: no media");
191 if (supported)
192 *supported = BRASERO_BURN_FLAG_NONE;
193 if (compulsory)
194 *compulsory = BRASERO_BURN_FLAG_NONE;
195 return BRASERO_BURN_NOT_SUPPORTED;
196 }
197
198 session_flags = brasero_burn_session_get_flags (session);
199
200 self = brasero_burn_caps_get_default ();
201 result = brasero_burn_caps_get_blanking_flags_real (self,
202 brasero_burn_session_get_strict_support (session) == FALSE,
203 media,
204 session_flags,
205 supported,
206 compulsory);
207 g_object_unref (self);
208
209 return result;
210 }
211
212 static BraseroBurnResult
brasero_burn_caps_can_blank_real(BraseroBurnCaps * self,gboolean ignore_plugin_errors,BraseroMedia media,BraseroBurnFlag flags)213 brasero_burn_caps_can_blank_real (BraseroBurnCaps *self,
214 gboolean ignore_plugin_errors,
215 BraseroMedia media,
216 BraseroBurnFlag flags)
217 {
218 GSList *iter;
219
220 BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
221 if (media == BRASERO_MEDIUM_NONE) {
222 BRASERO_BURN_LOG ("no media => no blanking possible");
223 return BRASERO_BURN_NOT_SUPPORTED;
224 }
225
226 /* This is a special case from MMC: DVD-RW sequential
227 * can only be multisession is they were fully blanked
228 * so if there are the two flags, abort. */
229 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW)
230 && (flags & BRASERO_BURN_FLAG_MULTI)
231 && (flags & BRASERO_BURN_FLAG_FAST_BLANK)) {
232 BRASERO_BURN_LOG ("fast media blanking only supported but multisession required for DVD-RW");
233 return BRASERO_BURN_NOT_SUPPORTED;
234 }
235
236 for (iter = self->priv->caps_list; iter; iter = iter->next) {
237 BraseroCaps *caps;
238 GSList *links;
239
240 caps = iter->data;
241 if (caps->type.type != BRASERO_TRACK_TYPE_DISC)
242 continue;
243
244 if ((media & brasero_track_type_get_medium_type (&caps->type)) != media)
245 continue;
246
247 BRASERO_BURN_LOG_TYPE (&caps->type, "Searching links for caps");
248
249 for (links = caps->links; links; links = links->next) {
250 GSList *plugins;
251 BraseroCapsLink *link;
252
253 link = links->data;
254
255 if (link->caps != NULL)
256 continue;
257
258 BRASERO_BURN_LOG ("Searching plugins");
259
260 /* Go through all plugins for the link and stop if we
261 * find at least one active plugin that accepts the
262 * flags. No need for plugins to be sorted */
263 for (plugins = link->plugins; plugins; plugins = plugins->next) {
264 BraseroPlugin *plugin;
265
266 plugin = plugins->data;
267 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
268 continue;
269
270 if (brasero_plugin_check_blank_flags (plugin, media, flags)) {
271 BRASERO_BURN_LOG_DISC_TYPE (media, "Can blank");
272 return BRASERO_BURN_OK;
273 }
274 }
275 }
276 }
277
278 BRASERO_BURN_LOG_DISC_TYPE (media, "No blanking capabilities for");
279
280 return BRASERO_BURN_NOT_SUPPORTED;
281 }
282
283 /**
284 * brasero_burn_session_can_blank:
285 * @session: a #BraseroBurnSession
286 *
287 * Given the various parameters stored in @session, this
288 * function checks whether the medium in the
289 * #BraseroDrive (set with brasero_burn_session_set_burner ())
290 * can be blanked.
291 *
292 * Return value: a #BraseroBurnResult.
293 * BRASERO_BURN_OK if it is possible.
294 * BRASERO_BURN_ERR otherwise.
295 **/
296
297 BraseroBurnResult
brasero_burn_session_can_blank(BraseroBurnSession * session)298 brasero_burn_session_can_blank (BraseroBurnSession *session)
299 {
300 BraseroMedia media;
301 BraseroBurnFlag flags;
302 BraseroBurnCaps *self;
303 BraseroBurnResult result;
304
305 self = brasero_burn_caps_get_default ();
306
307 media = brasero_burn_session_get_dest_media (session);
308 BRASERO_BURN_LOG_DISC_TYPE (media, "Testing blanking caps for");
309
310 if (media == BRASERO_MEDIUM_NONE) {
311 BRASERO_BURN_LOG ("no media => no blanking possible");
312 g_object_unref (self);
313 return BRASERO_BURN_NOT_SUPPORTED;
314 }
315
316 flags = brasero_burn_session_get_flags (session);
317 result = brasero_burn_caps_can_blank_real (self,
318 brasero_burn_session_get_strict_support (session) == FALSE,
319 media,
320 flags);
321 g_object_unref (self);
322
323 return result;
324 }
325
326 static void
brasero_caps_link_get_record_flags(BraseroCapsLink * link,gboolean ignore_plugin_errors,BraseroMedia media,BraseroBurnFlag session_flags,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory_retval)327 brasero_caps_link_get_record_flags (BraseroCapsLink *link,
328 gboolean ignore_plugin_errors,
329 BraseroMedia media,
330 BraseroBurnFlag session_flags,
331 BraseroBurnFlag *supported,
332 BraseroBurnFlag *compulsory_retval)
333 {
334 GSList *iter;
335 BraseroBurnFlag compulsory;
336
337 compulsory = BRASERO_BURN_FLAG_ALL;
338
339 /* Go through all plugins to get the supported/... record flags for link */
340 for (iter = link->plugins; iter; iter = iter->next) {
341 gboolean result;
342 BraseroPlugin *plugin;
343 BraseroBurnFlag plugin_supported;
344 BraseroBurnFlag plugin_compulsory;
345
346 plugin = iter->data;
347 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
348 continue;
349
350 result = brasero_plugin_get_record_flags (plugin,
351 media,
352 session_flags,
353 &plugin_supported,
354 &plugin_compulsory);
355 if (!result)
356 continue;
357
358 *supported |= plugin_supported;
359 compulsory &= plugin_compulsory;
360 }
361
362 *compulsory_retval = compulsory;
363 }
364
365 static void
brasero_caps_link_get_data_flags(BraseroCapsLink * link,gboolean ignore_plugin_errors,BraseroMedia media,BraseroBurnFlag session_flags,BraseroBurnFlag * supported)366 brasero_caps_link_get_data_flags (BraseroCapsLink *link,
367 gboolean ignore_plugin_errors,
368 BraseroMedia media,
369 BraseroBurnFlag session_flags,
370 BraseroBurnFlag *supported)
371 {
372 GSList *iter;
373
374 /* Go through all plugins the get the supported/... data flags for link */
375 for (iter = link->plugins; iter; iter = iter->next) {
376 BraseroPlugin *plugin;
377 BraseroBurnFlag plugin_supported;
378 BraseroBurnFlag plugin_compulsory;
379
380 plugin = iter->data;
381 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
382 continue;
383
384 brasero_plugin_get_image_flags (plugin,
385 media,
386 session_flags,
387 &plugin_supported,
388 &plugin_compulsory);
389 *supported |= plugin_supported;
390 }
391 }
392
393 static gboolean
brasero_caps_link_check_data_flags(BraseroCapsLink * link,gboolean ignore_plugin_errors,BraseroBurnFlag session_flags,BraseroMedia media)394 brasero_caps_link_check_data_flags (BraseroCapsLink *link,
395 gboolean ignore_plugin_errors,
396 BraseroBurnFlag session_flags,
397 BraseroMedia media)
398 {
399 GSList *iter;
400 BraseroBurnFlag flags;
401
402 /* here we just make sure that at least one of the plugins in the link
403 * can comply with the flags (APPEND/MERGE) */
404 flags = session_flags & (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE);
405
406 /* If there are no image flags forget it */
407 if (flags == BRASERO_BURN_FLAG_NONE)
408 return TRUE;
409
410 /* Go through all plugins; at least one must support image flags */
411 for (iter = link->plugins; iter; iter = iter->next) {
412 gboolean result;
413 BraseroPlugin *plugin;
414
415 plugin = iter->data;
416 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
417 continue;
418
419 result = brasero_plugin_check_image_flags (plugin,
420 media,
421 session_flags);
422 if (result)
423 return TRUE;
424 }
425
426 return FALSE;
427 }
428
429 static gboolean
brasero_caps_link_check_record_flags(BraseroCapsLink * link,gboolean ignore_plugin_errors,BraseroBurnFlag session_flags,BraseroMedia media)430 brasero_caps_link_check_record_flags (BraseroCapsLink *link,
431 gboolean ignore_plugin_errors,
432 BraseroBurnFlag session_flags,
433 BraseroMedia media)
434 {
435 GSList *iter;
436 BraseroBurnFlag flags;
437
438 flags = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
439
440 /* If there are no record flags forget it */
441 if (flags == BRASERO_BURN_FLAG_NONE)
442 return TRUE;
443
444 /* Go through all plugins: at least one must support record flags */
445 for (iter = link->plugins; iter; iter = iter->next) {
446 gboolean result;
447 BraseroPlugin *plugin;
448
449 plugin = iter->data;
450 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
451 continue;
452
453 result = brasero_plugin_check_record_flags (plugin,
454 media,
455 session_flags);
456 if (result)
457 return TRUE;
458 }
459
460 return FALSE;
461 }
462
463 static gboolean
brasero_caps_link_check_media_restrictions(BraseroCapsLink * link,gboolean ignore_plugin_errors,BraseroMedia media)464 brasero_caps_link_check_media_restrictions (BraseroCapsLink *link,
465 gboolean ignore_plugin_errors,
466 BraseroMedia media)
467 {
468 GSList *iter;
469
470 /* Go through all plugins: at least one must support media */
471 for (iter = link->plugins; iter; iter = iter->next) {
472 gboolean result;
473 BraseroPlugin *plugin;
474
475 plugin = iter->data;
476 if (!brasero_plugin_get_active (plugin, ignore_plugin_errors))
477 continue;
478
479 result = brasero_plugin_check_media_restrictions (plugin, media);
480 if (result)
481 return TRUE;
482 }
483
484 return FALSE;
485 }
486
487 static BraseroBurnResult
brasero_caps_report_plugin_error(BraseroPlugin * plugin,BraseroForeachPluginErrorCb callback,gpointer user_data)488 brasero_caps_report_plugin_error (BraseroPlugin *plugin,
489 BraseroForeachPluginErrorCb callback,
490 gpointer user_data)
491 {
492 GSList *errors;
493
494 errors = brasero_plugin_get_errors (plugin);
495 if (!errors)
496 return BRASERO_BURN_ERR;
497
498 do {
499 BraseroPluginError *error;
500 BraseroBurnResult result;
501
502 error = errors->data;
503 result = callback (error->type, error->detail, user_data);
504 if (result == BRASERO_BURN_RETRY) {
505 /* Something has been done
506 * to fix the error like an install
507 * so reload the errors */
508 brasero_plugin_check_plugin_ready (plugin);
509 errors = brasero_plugin_get_errors (plugin);
510 continue;
511 }
512
513 if (result != BRASERO_BURN_OK)
514 return result;
515
516 errors = errors->next;
517 } while (errors);
518
519 return BRASERO_BURN_OK;
520 }
521
522 struct _BraseroFindLinkCtx {
523 BraseroMedia media;
524 BraseroTrackType *input;
525 BraseroPluginIOFlag io_flags;
526 BraseroBurnFlag session_flags;
527
528 BraseroForeachPluginErrorCb callback;
529 gpointer user_data;
530
531 guint ignore_plugin_errors:1;
532 guint check_session_flags:1;
533 };
534 typedef struct _BraseroFindLinkCtx BraseroFindLinkCtx;
535
536 static void
brasero_caps_find_link_set_ctx(BraseroBurnSession * session,BraseroFindLinkCtx * ctx,BraseroTrackType * input)537 brasero_caps_find_link_set_ctx (BraseroBurnSession *session,
538 BraseroFindLinkCtx *ctx,
539 BraseroTrackType *input)
540 {
541 ctx->input = input;
542
543 if (ctx->check_session_flags) {
544 ctx->session_flags = brasero_burn_session_get_flags (session);
545
546 if (BRASERO_BURN_SESSION_NO_TMP_FILE (session))
547 ctx->io_flags = BRASERO_PLUGIN_IO_ACCEPT_PIPE;
548 else
549 ctx->io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
550 }
551 else
552 ctx->io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE|
553 BRASERO_PLUGIN_IO_ACCEPT_PIPE;
554
555 if (!ctx->callback)
556 ctx->ignore_plugin_errors = (brasero_burn_session_get_strict_support (session) == FALSE);
557 else
558 ctx->ignore_plugin_errors = TRUE;
559 }
560
561 static BraseroBurnResult
brasero_caps_find_link(BraseroCaps * caps,BraseroFindLinkCtx * ctx)562 brasero_caps_find_link (BraseroCaps *caps,
563 BraseroFindLinkCtx *ctx)
564 {
565 GSList *iter;
566
567 BRASERO_BURN_LOG_WITH_TYPE (&caps->type, BRASERO_PLUGIN_IO_NONE, "Found link (with %i links):", g_slist_length (caps->links));
568
569 /* Here we only make sure we have at least one link working. For a link
570 * to be followed it must first:
571 * - link to a caps with correct io flags
572 * - have at least a plugin accepting the record flags if caps type is
573 * a disc (that means that the link is the recording part)
574 *
575 * and either:
576 * - link to a caps equal to the input
577 * - link to a caps (linking itself to another caps, ...) accepting the
578 * input
579 */
580
581 for (iter = caps->links; iter; iter = iter->next) {
582 BraseroCapsLink *link;
583 BraseroBurnResult result;
584
585 link = iter->data;
586
587 if (!link->caps)
588 continue;
589
590 /* check that the link has some active plugin */
591 if (!brasero_caps_link_active (link, ctx->ignore_plugin_errors))
592 continue;
593
594 /* since this link contains recorders, check that at least one
595 * of them can handle the record flags */
596 if (ctx->check_session_flags && brasero_track_type_get_has_medium (&caps->type)) {
597 if (!brasero_caps_link_check_record_flags (link, ctx->ignore_plugin_errors, ctx->session_flags, ctx->media))
598 continue;
599
600 if (brasero_caps_link_check_recorder_flags_for_input (link, ctx->session_flags) != BRASERO_BURN_OK)
601 continue;
602 }
603
604 /* first see if that's the perfect fit:
605 * - it must have the same caps (type + subtype)
606 * - it must have the proper IO */
607 if (brasero_track_type_get_has_data (&link->caps->type)) {
608 if (ctx->check_session_flags
609 && !brasero_caps_link_check_data_flags (link, ctx->ignore_plugin_errors, ctx->session_flags, ctx->media))
610 continue;
611 }
612 else if (!brasero_caps_link_check_media_restrictions (link, ctx->ignore_plugin_errors, ctx->media))
613 continue;
614
615 if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
616 && brasero_caps_is_compatible_type (link->caps, ctx->input)) {
617 if (ctx->callback) {
618 BraseroPlugin *plugin;
619
620 /* If we are supposed to report/signal that the plugin
621 * could be used but only if some more elements are
622 * installed */
623 plugin = brasero_caps_link_need_download (link);
624 if (plugin)
625 return brasero_caps_report_plugin_error (plugin, ctx->callback, ctx->user_data);
626 }
627 return BRASERO_BURN_OK;
628 }
629
630 /* we can't go further than a DISC type */
631 if (brasero_track_type_get_has_medium (&link->caps->type))
632 continue;
633
634 if ((link->caps->flags & ctx->io_flags) == BRASERO_PLUGIN_IO_NONE)
635 continue;
636
637 /* try to see where the inputs of this caps leads to */
638 result = brasero_caps_find_link (link->caps, ctx);
639 if (result == BRASERO_BURN_CANCEL)
640 return result;
641
642 if (result == BRASERO_BURN_OK) {
643 if (ctx->callback) {
644 BraseroPlugin *plugin;
645
646 /* If we are supposed to report/signal that the plugin
647 * could be used but only if some more elements are
648 * installed */
649 plugin = brasero_caps_link_need_download (link);
650 if (plugin)
651 return brasero_caps_report_plugin_error (plugin, ctx->callback, ctx->user_data);
652 }
653 return BRASERO_BURN_OK;
654 }
655 }
656
657 return BRASERO_BURN_NOT_SUPPORTED;
658 }
659
660 static BraseroBurnResult
brasero_caps_try_output(BraseroBurnCaps * self,BraseroFindLinkCtx * ctx,BraseroTrackType * output)661 brasero_caps_try_output (BraseroBurnCaps *self,
662 BraseroFindLinkCtx *ctx,
663 BraseroTrackType *output)
664 {
665 BraseroCaps *caps;
666
667 /* here we search the start caps */
668 caps = brasero_burn_caps_find_start_caps (self, output);
669 if (!caps) {
670 BRASERO_BURN_LOG ("No caps available");
671 return BRASERO_BURN_NOT_SUPPORTED;
672 }
673
674 /* Here flags don't matter as we don't record anything.
675 * Even the IOFlags since that can be checked later with
676 * brasero_burn_caps_get_flags. */
677 if (brasero_track_type_get_has_medium (output))
678 ctx->media = brasero_track_type_get_medium_type (output);
679 else
680 ctx->media = BRASERO_MEDIUM_FILE;
681
682 return brasero_caps_find_link (caps, ctx);
683 }
684
685 static BraseroBurnResult
brasero_caps_try_output_with_blanking(BraseroBurnCaps * self,BraseroBurnSession * session,BraseroFindLinkCtx * ctx,BraseroTrackType * output)686 brasero_caps_try_output_with_blanking (BraseroBurnCaps *self,
687 BraseroBurnSession *session,
688 BraseroFindLinkCtx *ctx,
689 BraseroTrackType *output)
690 {
691 gboolean result;
692 BraseroCaps *last_caps;
693
694 result = brasero_caps_try_output (self, ctx, output);
695 if (result == BRASERO_BURN_OK
696 || result == BRASERO_BURN_CANCEL)
697 return result;
698
699 /* we reached this point in two cases:
700 * - if the disc cannot be handled
701 * - if some flags are not handled
702 * It is helpful only if:
703 * - the disc was closed and no plugin can handle this type of
704 * disc once closed (CD-R(W))
705 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
706 * handle this flag (means that the plugin should erase and
707 * then write on its own. Basically that works only with
708 * overwrite formatted discs, DVD+RW, ...) */
709 if (!brasero_track_type_get_has_medium (output))
710 return BRASERO_BURN_NOT_SUPPORTED;
711
712 /* output is a disc try with initial blanking */
713 BRASERO_BURN_LOG ("Support for input/output failed.");
714
715 /* apparently nothing can be done to reach our goal. Maybe that
716 * is because we first have to blank the disc. If so add a blank
717 * task to the others as a first step */
718 if ((ctx->check_session_flags
719 && !(ctx->session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE))
720 || brasero_burn_session_can_blank (session) != BRASERO_BURN_OK)
721 return BRASERO_BURN_NOT_SUPPORTED;
722
723 BRASERO_BURN_LOG ("Trying with initial blanking");
724
725 /* retry with the same disc type but blank this time */
726 ctx->media = brasero_track_type_get_medium_type (output);
727 ctx->media &= ~(BRASERO_MEDIUM_CLOSED|
728 BRASERO_MEDIUM_APPENDABLE|
729 BRASERO_MEDIUM_UNFORMATTED|
730 BRASERO_MEDIUM_HAS_DATA|
731 BRASERO_MEDIUM_HAS_AUDIO);
732 ctx->media |= BRASERO_MEDIUM_BLANK;
733 brasero_track_type_set_medium_type (output, ctx->media);
734
735 last_caps = brasero_burn_caps_find_start_caps (self, output);
736 if (!last_caps)
737 return BRASERO_BURN_NOT_SUPPORTED;
738
739 return brasero_caps_find_link (last_caps, ctx);
740 }
741
742 /**
743 * brasero_burn_session_input_supported:
744 * @session: a #BraseroBurnSession
745 * @input: a #BraseroTrackType
746 * @check_flags: a #gboolean
747 *
748 * Given the various parameters stored in @session, this
749 * function checks whether a session with the data type
750 * @type could be burnt to the medium in the #BraseroDrive (set
751 * through brasero_burn_session_set_burner ()).
752 * If @check_flags is %TRUE, then flags are taken into account
753 * and are not if it is %FALSE.
754 *
755 * Return value: a #BraseroBurnResult.
756 * BRASERO_BURN_OK if it is possible.
757 * BRASERO_BURN_ERR otherwise.
758 **/
759
760 BraseroBurnResult
brasero_burn_session_input_supported(BraseroBurnSession * session,BraseroTrackType * input,gboolean check_flags)761 brasero_burn_session_input_supported (BraseroBurnSession *session,
762 BraseroTrackType *input,
763 gboolean check_flags)
764 {
765 BraseroBurnCaps *self;
766 BraseroBurnResult result;
767 BraseroTrackType output;
768 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
769
770 result = brasero_burn_session_get_output_type (session, &output);
771 if (result != BRASERO_BURN_OK)
772 return result;
773
774 BRASERO_BURN_LOG_TYPE (input, "Checking support for input");
775 BRASERO_BURN_LOG_TYPE (&output, "and output");
776
777 ctx.check_session_flags = check_flags;
778 brasero_caps_find_link_set_ctx (session, &ctx, input);
779
780 if (check_flags) {
781 result = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session),
782 ctx.session_flags);
783
784 if (!result)
785 BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
786
787 BRASERO_BURN_LOG_FLAGS (ctx.session_flags, "with flags");
788 }
789
790 self = brasero_burn_caps_get_default ();
791 result = brasero_caps_try_output_with_blanking (self,
792 session,
793 &ctx,
794 &output);
795 g_object_unref (self);
796
797 if (result != BRASERO_BURN_OK) {
798 BRASERO_BURN_LOG_TYPE (input, "Input not supported");
799 return result;
800 }
801
802 return BRASERO_BURN_OK;
803 }
804
805 /**
806 * brasero_burn_session_output_supported:
807 * @session: a #BraseroBurnSession *
808 * @output: a #BraseroTrackType *
809 *
810 * Make sure that the image type or medium type defined in @output can be
811 * created/burnt given the parameters and the current data set in @session.
812 *
813 * Return value: BRASERO_BURN_OK if the medium type or the image type can be used as an output.
814 **/
815 BraseroBurnResult
brasero_burn_session_output_supported(BraseroBurnSession * session,BraseroTrackType * output)816 brasero_burn_session_output_supported (BraseroBurnSession *session,
817 BraseroTrackType *output)
818 {
819 BraseroBurnCaps *self;
820 BraseroTrackType input;
821 BraseroBurnResult result;
822 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
823
824 /* Here, we can't check if the drive supports the flags since the output
825 * is hypothetical. There is no real medium. So forget the following :
826 * if (!brasero_burn_caps_flags_check_for_drive (session))
827 * BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
828 * The only thing we could do would be to check some known forbidden
829 * flags for some media provided the output type is DISC. */
830
831 brasero_burn_session_get_input_type (session, &input);
832 brasero_caps_find_link_set_ctx (session, &ctx, &input);
833
834 BRASERO_BURN_LOG_TYPE (output, "Checking support for output");
835 BRASERO_BURN_LOG_TYPE (&input, "and input");
836 BRASERO_BURN_LOG_FLAGS (brasero_burn_session_get_flags (session), "with flags");
837
838 self = brasero_burn_caps_get_default ();
839 result = brasero_caps_try_output_with_blanking (self,
840 session,
841 &ctx,
842 output);
843 g_object_unref (self);
844
845 if (result != BRASERO_BURN_OK) {
846 BRASERO_BURN_LOG_TYPE (output, "Output not supported");
847 return result;
848 }
849
850 return BRASERO_BURN_OK;
851 }
852
853 /**
854 * This is only to be used in case one wants to copy using the same drive.
855 * It determines the possible middle image type.
856 */
857
858 static BraseroBurnResult
brasero_burn_caps_is_session_supported_same_src_dest(BraseroBurnCaps * self,BraseroBurnSession * session,BraseroFindLinkCtx * ctx,BraseroTrackType * tmp_type)859 brasero_burn_caps_is_session_supported_same_src_dest (BraseroBurnCaps *self,
860 BraseroBurnSession *session,
861 BraseroFindLinkCtx *ctx,
862 BraseroTrackType *tmp_type)
863 {
864 GSList *iter;
865 BraseroDrive *burner;
866 BraseroTrackType input;
867 BraseroBurnResult result;
868 BraseroTrackType output;
869 BraseroImageFormat format;
870
871 BRASERO_BURN_LOG ("Checking disc copy support with same source and destination");
872
873 /* To determine if a CD/DVD can be copied using the same source/dest,
874 * we first determine if can be imaged and then if this image can be
875 * burnt to whatever medium type. */
876 brasero_caps_find_link_set_ctx (session, ctx, &input);
877 ctx->io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
878
879 memset (&input, 0, sizeof (BraseroTrackType));
880 brasero_burn_session_get_input_type (session, &input);
881 BRASERO_BURN_LOG_TYPE (&input, "input");
882
883 if (ctx->check_session_flags) {
884 /* NOTE: DAO can be a problem. So just in case remove it. It is
885 * not really useful in this context. What we want here is to
886 * know whether a medium can be used given the input; only 1
887 * flag is important here (MERGE) and can have consequences. */
888 ctx->session_flags &= ~BRASERO_BURN_FLAG_DAO;
889 BRASERO_BURN_LOG_FLAGS (ctx->session_flags, "flags");
890 }
891
892 burner = brasero_burn_session_get_burner (session);
893
894 /* First see if it works with a stream type */
895 brasero_track_type_set_has_stream (&output);
896
897 /* FIXME! */
898 brasero_track_type_set_stream_format (&output,
899 BRASERO_AUDIO_FORMAT_RAW|
900 BRASERO_METADATA_INFO);
901
902 BRASERO_BURN_LOG_TYPE (&output, "Testing stream type");
903 result = brasero_caps_try_output (self, ctx, &output);
904 if (result == BRASERO_BURN_CANCEL)
905 return result;
906
907 if (result == BRASERO_BURN_OK) {
908 BRASERO_BURN_LOG ("Stream type seems to be supported as output");
909
910 /* This format can be used to create an image. Check if can be
911 * burnt now. Just find at least one medium. */
912 for (iter = self->priv->caps_list; iter; iter = iter->next) {
913 BraseroBurnResult result;
914 BraseroMedia media;
915 BraseroCaps *caps;
916
917 caps = iter->data;
918
919 if (!brasero_track_type_get_has_medium (&caps->type))
920 continue;
921
922 media = brasero_track_type_get_medium_type (&caps->type);
923 /* Audio is only supported by CDs */
924 if ((media & BRASERO_MEDIUM_CD) == 0)
925 continue;
926
927 /* This type of disc cannot be burnt; skip them */
928 if (media & BRASERO_MEDIUM_ROM)
929 continue;
930
931 /* Make sure this is supported by the drive */
932 if (!brasero_drive_can_write_media (burner, media))
933 continue;
934
935 ctx->media = media;
936 result = brasero_caps_find_link (caps, ctx);
937 BRASERO_BURN_LOG_DISC_TYPE (media,
938 "Tested medium (%s)",
939 result == BRASERO_BURN_OK ? "working":"not working");
940
941 if (result == BRASERO_BURN_OK) {
942 if (tmp_type) {
943 brasero_track_type_set_has_stream (tmp_type);
944 brasero_track_type_set_stream_format (tmp_type, brasero_track_type_get_stream_format (&output));
945 }
946
947 return BRASERO_BURN_OK;
948 }
949
950 if (result == BRASERO_BURN_CANCEL)
951 return result;
952 }
953 }
954 else
955 BRASERO_BURN_LOG ("Stream format not supported as output");
956
957 /* Find one available output format */
958 format = BRASERO_IMAGE_FORMAT_CDRDAO;
959 brasero_track_type_set_has_image (&output);
960
961 for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
962 brasero_track_type_set_image_format (&output, format);
963
964 BRASERO_BURN_LOG_TYPE (&output, "Testing temporary image format");
965
966 /* Don't need to try blanking here (saves
967 * a few lines of debug) since that is an
968 * image */
969 result = brasero_caps_try_output (self, ctx, &output);
970 if (result == BRASERO_BURN_CANCEL)
971 return result;
972
973 if (result != BRASERO_BURN_OK)
974 continue;
975
976 /* This format can be used to create an image. Check if can be
977 * burnt now. Just find at least one medium. */
978 for (iter = self->priv->caps_list; iter; iter = iter->next) {
979 BraseroBurnResult result;
980 BraseroMedia media;
981 BraseroCaps *caps;
982
983 caps = iter->data;
984
985 if (!brasero_track_type_get_has_medium (&caps->type))
986 continue;
987
988 media = brasero_track_type_get_medium_type (&caps->type);
989
990 /* This type of disc cannot be burnt; skip them */
991 if (media & BRASERO_MEDIUM_ROM)
992 continue;
993
994 /* These three types only work with CDs. Skip the rest. */
995 if ((format == BRASERO_IMAGE_FORMAT_CDRDAO
996 || format == BRASERO_IMAGE_FORMAT_CLONE
997 || format == BRASERO_IMAGE_FORMAT_CUE)
998 && (media & BRASERO_MEDIUM_CD) == 0)
999 continue;
1000
1001 /* Make sure this is supported by the drive */
1002 if (!brasero_drive_can_write_media (burner, media))
1003 continue;
1004
1005 ctx->media = media;
1006 result = brasero_caps_find_link (caps, ctx);
1007 BRASERO_BURN_LOG_DISC_TYPE (media,
1008 "Tested medium (%s)",
1009 result == BRASERO_BURN_OK ? "working":"not working");
1010
1011 if (result == BRASERO_BURN_OK) {
1012 if (tmp_type) {
1013 brasero_track_type_set_has_image (tmp_type);
1014 brasero_track_type_set_image_format (tmp_type, brasero_track_type_get_image_format (&output));
1015 }
1016
1017 return BRASERO_BURN_OK;
1018 }
1019
1020 if (result == BRASERO_BURN_CANCEL)
1021 return result;
1022 }
1023 }
1024
1025 return BRASERO_BURN_NOT_SUPPORTED;
1026 }
1027
1028 BraseroBurnResult
brasero_burn_session_get_tmp_image_type_same_src_dest(BraseroBurnSession * session,BraseroTrackType * image_type)1029 brasero_burn_session_get_tmp_image_type_same_src_dest (BraseroBurnSession *session,
1030 BraseroTrackType *image_type)
1031 {
1032 BraseroBurnCaps *self;
1033 BraseroBurnResult result;
1034 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
1035
1036 g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
1037
1038 self = brasero_burn_caps_get_default ();
1039 result = brasero_burn_caps_is_session_supported_same_src_dest (self,
1040 session,
1041 &ctx,
1042 image_type);
1043 g_object_unref (self);
1044 return result;
1045 }
1046
1047 static BraseroBurnResult
brasero_burn_session_supported(BraseroBurnSession * session,BraseroFindLinkCtx * ctx)1048 brasero_burn_session_supported (BraseroBurnSession *session,
1049 BraseroFindLinkCtx *ctx)
1050 {
1051 gboolean result;
1052 BraseroBurnCaps *self;
1053 BraseroTrackType input;
1054 BraseroTrackType output;
1055
1056 /* Special case */
1057 if (brasero_burn_session_same_src_dest_drive (session)) {
1058 BraseroBurnResult res;
1059
1060 self = brasero_burn_caps_get_default ();
1061 res = brasero_burn_caps_is_session_supported_same_src_dest (self, session, ctx, NULL);
1062 g_object_unref (self);
1063
1064 return res;
1065 }
1066
1067 result = brasero_burn_session_get_output_type (session, &output);
1068 if (result != BRASERO_BURN_OK)
1069 BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
1070
1071 brasero_burn_session_get_input_type (session, &input);
1072 brasero_caps_find_link_set_ctx (session, ctx, &input);
1073
1074 BRASERO_BURN_LOG_TYPE (&output, "Checking support for session. Ouput is ");
1075 BRASERO_BURN_LOG_TYPE (&input, "and input is");
1076
1077 if (ctx->check_session_flags) {
1078 result = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session), ctx->session_flags);
1079 if (!result)
1080 BRASERO_BURN_CAPS_NOT_SUPPORTED_LOG_RES (session);
1081
1082 BRASERO_BURN_LOG_FLAGS (ctx->session_flags, "with flags");
1083 }
1084
1085 self = brasero_burn_caps_get_default ();
1086 result = brasero_caps_try_output_with_blanking (self,
1087 session,
1088 ctx,
1089 &output);
1090 g_object_unref (self);
1091
1092 if (result != BRASERO_BURN_OK) {
1093 BRASERO_BURN_LOG_TYPE (&output, "Session not supported");
1094 return result;
1095 }
1096
1097 BRASERO_BURN_LOG_TYPE (&output, "Session supported");
1098 return BRASERO_BURN_OK;
1099 }
1100
1101 /**
1102 * brasero_burn_session_can_burn:
1103 * @session: a #BraseroBurnSession
1104 * @check_flags: a #gboolean
1105 *
1106 * Given the various parameters stored in @session, this
1107 * function checks whether the data contained in @session
1108 * can be burnt to the medium in the #BraseroDrive (set
1109 * through brasero_burn_session_set_burner ()).
1110 * If @check_flags determine the behavior of this function.
1111 *
1112 * Return value: a #BraseroBurnResult.
1113 * BRASERO_BURN_OK if it is possible.
1114 * BRASERO_BURN_ERR otherwise.
1115 **/
1116
1117 BraseroBurnResult
brasero_burn_session_can_burn(BraseroBurnSession * session,gboolean check_flags)1118 brasero_burn_session_can_burn (BraseroBurnSession *session,
1119 gboolean check_flags)
1120 {
1121 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
1122
1123 g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
1124
1125 ctx.check_session_flags = check_flags;
1126
1127 return brasero_burn_session_supported (session, &ctx);
1128 }
1129
1130 /**
1131 * brasero_session_foreach_plugin_error:
1132 * @session: a #BraseroBurnSession.
1133 * @callback: a #BraseroSessionPluginErrorCb.
1134 * @user_data: a #gpointer. The data passed to @callback.
1135 *
1136 * Call @callback for each error in plugins.
1137 *
1138 * Return value: a #BraseroBurnResult.
1139 * BRASERO_BURN_OK if it is possible.
1140 * BRASERO_BURN_ERR otherwise.
1141 **/
1142
1143 BraseroBurnResult
brasero_session_foreach_plugin_error(BraseroBurnSession * session,BraseroForeachPluginErrorCb callback,gpointer user_data)1144 brasero_session_foreach_plugin_error (BraseroBurnSession *session,
1145 BraseroForeachPluginErrorCb callback,
1146 gpointer user_data)
1147 {
1148 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
1149
1150 g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
1151
1152 ctx.callback = callback;
1153 ctx.user_data = user_data;
1154
1155 return brasero_burn_session_supported (session, &ctx);
1156 }
1157
1158 /**
1159 * brasero_burn_session_get_required_media_type:
1160 * @session: a #BraseroBurnSession
1161 *
1162 * Return the medium types that could be used to burn
1163 * @session.
1164 *
1165 * Return value: a #BraseroMedia
1166 **/
1167
1168 BraseroMedia
brasero_burn_session_get_required_media_type(BraseroBurnSession * session)1169 brasero_burn_session_get_required_media_type (BraseroBurnSession *session)
1170 {
1171 BraseroMedia required_media = BRASERO_MEDIUM_NONE;
1172 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
1173 BraseroTrackType input;
1174 BraseroBurnCaps *self;
1175 GSList *iter;
1176
1177 if (brasero_burn_session_is_dest_file (session))
1178 return BRASERO_MEDIUM_FILE;
1179
1180 /* we try to determine here what type of medium is allowed to be burnt
1181 * to whether a CD or a DVD. Appendable, blank are not properties being
1182 * determined here. We just want it to be writable in a broad sense. */
1183 ctx.check_session_flags = TRUE;
1184 brasero_burn_session_get_input_type (session, &input);
1185 brasero_caps_find_link_set_ctx (session, &ctx, &input);
1186 BRASERO_BURN_LOG_TYPE (&input, "Determining required media type for input");
1187
1188 /* NOTE: BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE is a problem here since it
1189 * is only used if needed. Likewise DAO can be a problem. So just in
1190 * case remove them. They are not really useful in this context. What we
1191 * want here is to know which media can be used given the input; only 1
1192 * flag is important here (MERGE) and can have consequences. */
1193 ctx.session_flags &= ~BRASERO_BURN_FLAG_DAO;
1194 BRASERO_BURN_LOG_FLAGS (ctx.session_flags, "and flags");
1195
1196 self = brasero_burn_caps_get_default ();
1197 for (iter = self->priv->caps_list; iter; iter = iter->next) {
1198 BraseroCaps *caps;
1199 gboolean result;
1200
1201 caps = iter->data;
1202
1203 if (!brasero_track_type_get_has_medium (&caps->type))
1204 continue;
1205
1206 /* Put BRASERO_MEDIUM_NONE so we can always succeed */
1207 result = brasero_caps_find_link (caps, &ctx);
1208 BRASERO_BURN_LOG_DISC_TYPE (caps->type.subtype.media,
1209 "Tested (%s)",
1210 result == BRASERO_BURN_OK ? "working":"not working");
1211
1212 if (result == BRASERO_BURN_CANCEL) {
1213 g_object_unref (self);
1214 return result;
1215 }
1216
1217 if (result != BRASERO_BURN_OK)
1218 continue;
1219
1220 /* This caps work, add its subtype */
1221 required_media |= brasero_track_type_get_medium_type (&caps->type);
1222 }
1223
1224 /* filter as we are only interested in these */
1225 required_media &= BRASERO_MEDIUM_WRITABLE|
1226 BRASERO_MEDIUM_CD|
1227 BRASERO_MEDIUM_DVD;
1228
1229 g_object_unref (self);
1230 return required_media;
1231 }
1232
1233 /**
1234 * brasero_burn_session_get_possible_output_formats:
1235 * @session: a #BraseroBurnSession
1236 * @formats: a #BraseroImageFormat
1237 *
1238 * Returns the disc image types that could be set to create
1239 * an image given the current state of @session.
1240 *
1241 * Return value: a #guint. The number of formats available.
1242 **/
1243
1244 guint
brasero_burn_session_get_possible_output_formats(BraseroBurnSession * session,BraseroImageFormat * formats)1245 brasero_burn_session_get_possible_output_formats (BraseroBurnSession *session,
1246 BraseroImageFormat *formats)
1247 {
1248 guint num = 0;
1249 BraseroImageFormat format;
1250 BraseroTrackType *output = NULL;
1251
1252 g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), 0);
1253
1254 /* see how many output format are available */
1255 format = BRASERO_IMAGE_FORMAT_CDRDAO;
1256 (*formats) = BRASERO_IMAGE_FORMAT_NONE;
1257
1258 output = brasero_track_type_new ();
1259 brasero_track_type_set_has_image (output);
1260
1261 for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
1262 BraseroBurnResult result;
1263
1264 brasero_track_type_set_image_format (output, format);
1265 result = brasero_burn_session_output_supported (session, output);
1266 if (result == BRASERO_BURN_OK) {
1267 (*formats) |= format;
1268 num ++;
1269 }
1270 }
1271
1272 brasero_track_type_free (output);
1273
1274 return num;
1275 }
1276
1277 /**
1278 * brasero_burn_session_get_default_output_format:
1279 * @session: a #BraseroBurnSession
1280 *
1281 * Returns the default disc image type that should be set to create
1282 * an image given the current state of @session.
1283 *
1284 * Return value: a #BraseroImageFormat
1285 **/
1286
1287 BraseroImageFormat
brasero_burn_session_get_default_output_format(BraseroBurnSession * session)1288 brasero_burn_session_get_default_output_format (BraseroBurnSession *session)
1289 {
1290 BraseroBurnCaps *self;
1291 BraseroBurnResult result;
1292 BraseroTrackType source = { BRASERO_TRACK_TYPE_NONE, { 0, }};
1293 BraseroTrackType output = { BRASERO_TRACK_TYPE_NONE, { 0, }};
1294
1295 self = brasero_burn_caps_get_default ();
1296
1297 if (!brasero_burn_session_is_dest_file (session)) {
1298 g_object_unref (self);
1299 return BRASERO_IMAGE_FORMAT_NONE;
1300 }
1301
1302 brasero_burn_session_get_input_type (session, &source);
1303 if (brasero_track_type_is_empty (&source)) {
1304 g_object_unref (self);
1305 return BRASERO_IMAGE_FORMAT_NONE;
1306 }
1307
1308 if (brasero_track_type_get_has_image (&source)) {
1309 g_object_unref (self);
1310 return brasero_track_type_get_image_format (&source);
1311 }
1312
1313 brasero_track_type_set_has_image (&output);
1314 brasero_track_type_set_image_format (&output, BRASERO_IMAGE_FORMAT_NONE);
1315
1316 if (brasero_track_type_get_has_stream (&source)) {
1317 /* Otherwise try all possible image types */
1318 output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
1319 for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
1320 output.subtype.img_format >>= 1) {
1321
1322 result = brasero_burn_session_output_supported (session,
1323 &output);
1324 if (result == BRASERO_BURN_OK) {
1325 g_object_unref (self);
1326 return brasero_track_type_get_image_format (&output);
1327 }
1328 }
1329
1330 g_object_unref (self);
1331 return BRASERO_IMAGE_FORMAT_NONE;
1332 }
1333
1334 if (brasero_track_type_get_has_data (&source)
1335 || (brasero_track_type_get_has_medium (&source)
1336 && (brasero_track_type_get_medium_type (&source) & BRASERO_MEDIUM_DVD))) {
1337 brasero_track_type_set_image_format (&output, BRASERO_IMAGE_FORMAT_BIN);
1338 result = brasero_burn_session_output_supported (session, &output);
1339 g_object_unref (self);
1340
1341 if (result != BRASERO_BURN_OK)
1342 return BRASERO_IMAGE_FORMAT_NONE;
1343
1344 return BRASERO_IMAGE_FORMAT_BIN;
1345 }
1346
1347 /* for the input which are CDs there are lots of possible formats */
1348 output.subtype.img_format = BRASERO_IMAGE_FORMAT_CDRDAO;
1349 for (; output.subtype.img_format != BRASERO_IMAGE_FORMAT_NONE;
1350 output.subtype.img_format >>= 1) {
1351
1352 result = brasero_burn_session_output_supported (session, &output);
1353 if (result == BRASERO_BURN_OK) {
1354 g_object_unref (self);
1355 return brasero_track_type_get_image_format (&output);
1356 }
1357 }
1358
1359 g_object_unref (self);
1360 return BRASERO_IMAGE_FORMAT_NONE;
1361 }
1362
1363 static BraseroBurnResult
brasero_caps_set_flags_from_recorder_input(BraseroTrackType * input,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)1364 brasero_caps_set_flags_from_recorder_input (BraseroTrackType *input,
1365 BraseroBurnFlag *supported,
1366 BraseroBurnFlag *compulsory)
1367 {
1368 if (brasero_track_type_get_has_image (input)) {
1369 BraseroImageFormat format;
1370
1371 format = brasero_track_type_get_image_format (input);
1372 if (format == BRASERO_IMAGE_FORMAT_CUE
1373 || format == BRASERO_IMAGE_FORMAT_CDRDAO) {
1374 if ((*supported) & BRASERO_BURN_FLAG_DAO)
1375 (*compulsory) |= BRASERO_BURN_FLAG_DAO;
1376 else
1377 return BRASERO_BURN_NOT_SUPPORTED;
1378 }
1379 else if (format == BRASERO_IMAGE_FORMAT_CLONE) {
1380 /* RAW write mode should (must) only be used in this case */
1381 if ((*supported) & BRASERO_BURN_FLAG_RAW) {
1382 (*supported) &= ~BRASERO_BURN_FLAG_DAO;
1383 (*compulsory) &= ~BRASERO_BURN_FLAG_DAO;
1384 (*compulsory) |= BRASERO_BURN_FLAG_RAW;
1385 }
1386 else
1387 return BRASERO_BURN_NOT_SUPPORTED;
1388 }
1389 else
1390 (*supported) &= ~BRASERO_BURN_FLAG_RAW;
1391 }
1392
1393 return BRASERO_BURN_OK;
1394 }
1395
1396 static BraseroPluginIOFlag
brasero_caps_get_flags(BraseroCaps * caps,gboolean ignore_plugin_errors,BraseroBurnFlag session_flags,BraseroMedia media,BraseroTrackType * input,BraseroPluginIOFlag flags,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)1397 brasero_caps_get_flags (BraseroCaps *caps,
1398 gboolean ignore_plugin_errors,
1399 BraseroBurnFlag session_flags,
1400 BraseroMedia media,
1401 BraseroTrackType *input,
1402 BraseroPluginIOFlag flags,
1403 BraseroBurnFlag *supported,
1404 BraseroBurnFlag *compulsory)
1405 {
1406 GSList *iter;
1407 BraseroPluginIOFlag retval = BRASERO_PLUGIN_IO_NONE;
1408
1409 /* First we must know if this link leads somewhere. It must
1410 * accept the already existing flags. If it does, see if it
1411 * accepts the input and if not, if one of its ancestors does */
1412 for (iter = caps->links; iter; iter = iter->next) {
1413 BraseroBurnFlag data_supported = BRASERO_BURN_FLAG_NONE;
1414 BraseroBurnFlag rec_compulsory = BRASERO_BURN_FLAG_ALL;
1415 BraseroBurnFlag rec_supported = BRASERO_BURN_FLAG_NONE;
1416 BraseroPluginIOFlag io_flags;
1417 BraseroCapsLink *link;
1418
1419 link = iter->data;
1420
1421 if (!link->caps)
1422 continue;
1423
1424 /* check that the link has some active plugin */
1425 if (!brasero_caps_link_active (link, ignore_plugin_errors))
1426 continue;
1427
1428 if (brasero_track_type_get_has_medium (&caps->type)) {
1429 BraseroBurnFlag tmp;
1430 BraseroBurnResult result;
1431
1432 brasero_caps_link_get_record_flags (link,
1433 ignore_plugin_errors,
1434 media,
1435 session_flags,
1436 &rec_supported,
1437 &rec_compulsory);
1438
1439 /* see if that link can handle the record flags.
1440 * NOTE: compulsory are not a failure in this case. */
1441 tmp = session_flags & BRASERO_PLUGIN_BURN_FLAG_MASK;
1442 if ((tmp & rec_supported) != tmp)
1443 continue;
1444
1445 /* This is the recording plugin, check its input as
1446 * some flags depend on it. */
1447 result = brasero_caps_set_flags_from_recorder_input (&link->caps->type,
1448 &rec_supported,
1449 &rec_compulsory);
1450 if (result != BRASERO_BURN_OK)
1451 continue;
1452 }
1453
1454 if (brasero_track_type_get_has_data (&link->caps->type)) {
1455 BraseroBurnFlag tmp;
1456
1457 brasero_caps_link_get_data_flags (link,
1458 ignore_plugin_errors,
1459 media,
1460 session_flags,
1461 &data_supported);
1462
1463 /* see if that link can handle the data flags.
1464 * NOTE: compulsory are not a failure in this case. */
1465 tmp = session_flags & (BRASERO_BURN_FLAG_APPEND|
1466 BRASERO_BURN_FLAG_MERGE);
1467
1468 if ((tmp & data_supported) != tmp)
1469 continue;
1470 }
1471 else if (!brasero_caps_link_check_media_restrictions (link, ignore_plugin_errors, media))
1472 continue;
1473
1474 /* see if that's the perfect fit */
1475 if ((link->caps->flags & BRASERO_PLUGIN_IO_ACCEPT_FILE)
1476 && brasero_caps_is_compatible_type (link->caps, input)) {
1477 /* special case for input that handle output/input */
1478 if (caps->type.type == BRASERO_TRACK_TYPE_DISC)
1479 retval |= BRASERO_PLUGIN_IO_ACCEPT_PIPE;
1480 else
1481 retval |= caps->flags;
1482
1483 (*compulsory) &= rec_compulsory;
1484 (*supported) |= data_supported|rec_supported;
1485 continue;
1486 }
1487
1488 if ((link->caps->flags & flags) == BRASERO_PLUGIN_IO_NONE)
1489 continue;
1490
1491 /* we can't go further than a DISC type */
1492 if (link->caps->type.type == BRASERO_TRACK_TYPE_DISC)
1493 continue;
1494
1495 /* try to see where the inputs of this caps leads to */
1496 io_flags = brasero_caps_get_flags (link->caps,
1497 ignore_plugin_errors,
1498 session_flags,
1499 media,
1500 input,
1501 flags,
1502 supported,
1503 compulsory);
1504 if (io_flags == BRASERO_PLUGIN_IO_NONE)
1505 continue;
1506
1507 (*compulsory) &= rec_compulsory;
1508 retval |= (io_flags & flags);
1509 (*supported) |= data_supported|rec_supported;
1510 }
1511
1512 return retval;
1513 }
1514
1515 static void
brasero_medium_supported_flags(BraseroMedium * medium,BraseroBurnFlag * supported_flags,BraseroBurnFlag * compulsory_flags)1516 brasero_medium_supported_flags (BraseroMedium *medium,
1517 BraseroBurnFlag *supported_flags,
1518 BraseroBurnFlag *compulsory_flags)
1519 {
1520 BraseroMedia media;
1521
1522 media = brasero_medium_get_status (medium);
1523
1524 /* This is always FALSE */
1525 if (media & BRASERO_MEDIUM_PLUS)
1526 (*supported_flags) &= ~BRASERO_BURN_FLAG_DUMMY;
1527
1528 /* Simulation is only possible according to write modes. This mode is
1529 * mostly used by cdrecord/wodim for CLONE images. */
1530 else if (media & BRASERO_MEDIUM_DVD) {
1531 if (!brasero_medium_can_use_dummy_for_sao (medium))
1532 (*supported_flags) &= ~BRASERO_BURN_FLAG_DUMMY;
1533 }
1534 else if ((*supported_flags) & BRASERO_BURN_FLAG_DAO) {
1535 if (!brasero_medium_can_use_dummy_for_sao (medium))
1536 (*supported_flags) &= ~BRASERO_BURN_FLAG_DUMMY;
1537 }
1538 else if (!brasero_medium_can_use_dummy_for_tao (medium))
1539 (*supported_flags) &= ~BRASERO_BURN_FLAG_DUMMY;
1540
1541 /* The following is only true if we won't _have_ to blank
1542 * the disc since a CLOSED disc is not able for tao/sao.
1543 * so if BLANK_BEFORE_RIGHT is TRUE then we leave
1544 * the benefit of the doubt, but flags should be rechecked
1545 * after the drive was blanked. */
1546 if (((*compulsory_flags) & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) == 0
1547 && !BRASERO_MEDIUM_RANDOM_WRITABLE (media)
1548 && !brasero_medium_can_use_tao (medium)) {
1549 (*supported_flags) &= ~BRASERO_BURN_FLAG_MULTI;
1550
1551 if (brasero_medium_can_use_sao (medium))
1552 (*compulsory_flags) |= BRASERO_BURN_FLAG_DAO;
1553 else
1554 (*supported_flags) &= ~BRASERO_BURN_FLAG_DAO;
1555 }
1556
1557 if (!brasero_medium_can_use_burnfree (medium))
1558 (*supported_flags) &= ~BRASERO_BURN_FLAG_BURNPROOF;
1559 }
1560
1561 static void
brasero_burn_caps_flags_update_for_drive(BraseroBurnSession * session,BraseroBurnFlag * supported_flags,BraseroBurnFlag * compulsory_flags)1562 brasero_burn_caps_flags_update_for_drive (BraseroBurnSession *session,
1563 BraseroBurnFlag *supported_flags,
1564 BraseroBurnFlag *compulsory_flags)
1565 {
1566 BraseroDrive *drive;
1567 BraseroMedium *medium;
1568
1569 drive = brasero_burn_session_get_burner (session);
1570 if (!drive)
1571 return;
1572
1573 medium = brasero_drive_get_medium (drive);
1574 if (!medium)
1575 return;
1576
1577 brasero_medium_supported_flags (medium,
1578 supported_flags,
1579 compulsory_flags);
1580 }
1581
1582 static BraseroBurnResult
brasero_caps_get_flags_for_disc(BraseroBurnCaps * self,gboolean ignore_plugin_errors,BraseroBurnFlag session_flags,BraseroMedia media,BraseroTrackType * input,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)1583 brasero_caps_get_flags_for_disc (BraseroBurnCaps *self,
1584 gboolean ignore_plugin_errors,
1585 BraseroBurnFlag session_flags,
1586 BraseroMedia media,
1587 BraseroTrackType *input,
1588 BraseroBurnFlag *supported,
1589 BraseroBurnFlag *compulsory)
1590 {
1591 BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_NONE;
1592 BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_ALL;
1593 BraseroPluginIOFlag io_flags;
1594 BraseroTrackType output;
1595 BraseroCaps *caps;
1596
1597 /* create the output to find first caps */
1598 brasero_track_type_set_has_medium (&output);
1599 brasero_track_type_set_medium_type (&output, media);
1600
1601 caps = brasero_burn_caps_find_start_caps (self, &output);
1602 if (!caps) {
1603 BRASERO_BURN_LOG_DISC_TYPE (media, "FLAGS: no caps could be found for");
1604 return BRASERO_BURN_NOT_SUPPORTED;
1605 }
1606
1607 BRASERO_BURN_LOG_WITH_TYPE (&caps->type,
1608 caps->flags,
1609 "FLAGS: trying caps");
1610
1611 io_flags = brasero_caps_get_flags (caps,
1612 ignore_plugin_errors,
1613 session_flags,
1614 media,
1615 input,
1616 BRASERO_PLUGIN_IO_ACCEPT_FILE|
1617 BRASERO_PLUGIN_IO_ACCEPT_PIPE,
1618 &supported_flags,
1619 &compulsory_flags);
1620
1621 if (io_flags == BRASERO_PLUGIN_IO_NONE) {
1622 BRASERO_BURN_LOG ("FLAGS: not supported");
1623 return BRASERO_BURN_NOT_SUPPORTED;
1624 }
1625
1626 /* NOTE: DO NOT TEST the input image here. What should be tested is the
1627 * type of the input right before the burner plugin. See:
1628 * brasero_burn_caps_set_flags_from_recorder_input())
1629 * For example in the following situation: AUDIO => CUE => BURNER the
1630 * DAO flag would not be set otherwise. */
1631
1632 if (brasero_track_type_get_has_stream (input)) {
1633 BraseroStreamFormat format;
1634
1635 format = brasero_track_type_get_stream_format (input);
1636 if (format & BRASERO_METADATA_INFO) {
1637 /* In this case, DAO is compulsory if we want to write CD-TEXT */
1638 if (supported_flags & BRASERO_BURN_FLAG_DAO)
1639 compulsory_flags |= BRASERO_BURN_FLAG_DAO;
1640 else
1641 return BRASERO_BURN_NOT_SUPPORTED;
1642 }
1643 }
1644
1645 if (compulsory_flags & BRASERO_BURN_FLAG_DAO) {
1646 /* unlikely */
1647 compulsory_flags &= ~BRASERO_BURN_FLAG_RAW;
1648 supported_flags &= ~BRASERO_BURN_FLAG_RAW;
1649 }
1650
1651 if (io_flags & BRASERO_PLUGIN_IO_ACCEPT_PIPE) {
1652 supported_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
1653
1654 if ((io_flags & BRASERO_PLUGIN_IO_ACCEPT_FILE) == 0)
1655 compulsory_flags |= BRASERO_BURN_FLAG_NO_TMP_FILES;
1656 }
1657
1658 *supported |= supported_flags;
1659 *compulsory |= compulsory_flags;
1660
1661 return BRASERO_BURN_OK;
1662 }
1663
1664 static BraseroBurnResult
brasero_burn_caps_get_flags_for_medium(BraseroBurnCaps * self,BraseroBurnSession * session,BraseroMedia media,BraseroBurnFlag session_flags,BraseroTrackType * input,BraseroBurnFlag * supported_flags,BraseroBurnFlag * compulsory_flags)1665 brasero_burn_caps_get_flags_for_medium (BraseroBurnCaps *self,
1666 BraseroBurnSession *session,
1667 BraseroMedia media,
1668 BraseroBurnFlag session_flags,
1669 BraseroTrackType *input,
1670 BraseroBurnFlag *supported_flags,
1671 BraseroBurnFlag *compulsory_flags)
1672 {
1673 BraseroBurnResult result;
1674 gboolean can_blank = FALSE;
1675
1676 /* See if medium is supported out of the box */
1677 result = brasero_caps_get_flags_for_disc (self,
1678 brasero_burn_session_get_strict_support (session) == FALSE,
1679 session_flags,
1680 media,
1681 input,
1682 supported_flags,
1683 compulsory_flags);
1684
1685 /* see if we can add BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE. Add it when:
1686 * - media can be blanked, it has audio or data and we're not merging
1687 * - media is not formatted and it can be blanked/formatted */
1688 if (brasero_burn_caps_can_blank_real (self, brasero_burn_session_get_strict_support (session) == FALSE, media, session_flags) == BRASERO_BURN_OK)
1689 can_blank = TRUE;
1690 else if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)
1691 return BRASERO_BURN_NOT_SUPPORTED;
1692
1693 if (can_blank) {
1694 gboolean first_success;
1695 BraseroBurnFlag blank_compulsory = BRASERO_BURN_FLAG_NONE;
1696 BraseroBurnFlag blank_supported = BRASERO_BURN_FLAG_NONE;
1697
1698 /* we reached this point in two cases:
1699 * - if the disc cannot be handled
1700 * - if some flags are not handled
1701 * It is helpful only if:
1702 * - the disc was closed and no plugin can handle this type of
1703 * disc once closed (CD-R(W))
1704 * - there was the flag BLANK_BEFORE_WRITE set and no plugin can
1705 * handle this flag (means that the plugin should erase and
1706 * then write on its own. Basically that works only with
1707 * overwrite formatted discs, DVD+RW, ...) */
1708
1709 /* What's above is not entirely true. In fact we always need to
1710 * check even if we first succeeded. There are some cases like
1711 * CDRW where it's useful.
1712 * Ex: a CDRW with data appendable can be either appended (then
1713 * no DAO possible) or blanked and written (DAO possible). */
1714
1715 /* result here is the result of the first operation, so if it
1716 * failed, BLANK before becomes compulsory. */
1717 first_success = (result == BRASERO_BURN_OK);
1718
1719 /* pretends it is blank and formatted to see if it would work.
1720 * If it works then that means that the BLANK_BEFORE_WRITE flag
1721 * is compulsory. */
1722 media &= ~(BRASERO_MEDIUM_CLOSED|
1723 BRASERO_MEDIUM_APPENDABLE|
1724 BRASERO_MEDIUM_UNFORMATTED|
1725 BRASERO_MEDIUM_HAS_DATA|
1726 BRASERO_MEDIUM_HAS_AUDIO);
1727 media |= BRASERO_MEDIUM_BLANK;
1728 result = brasero_caps_get_flags_for_disc (self,
1729 brasero_burn_session_get_strict_support (session) == FALSE,
1730 session_flags,
1731 media,
1732 input,
1733 supported_flags,
1734 compulsory_flags);
1735
1736 /* if both attempts failed, drop it */
1737 if (result != BRASERO_BURN_OK) {
1738 /* See if we entirely failed */
1739 if (!first_success)
1740 return result;
1741
1742 /* we tried with a blank medium but did not
1743 * succeed. So that means the flags BLANK.
1744 * is not supported */
1745 }
1746 else {
1747 (*supported_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
1748
1749 if (!first_success)
1750 (*compulsory_flags) |= BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE;
1751
1752 /* If BLANK flag is supported then MERGE/APPEND can't be compulsory */
1753 (*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
1754
1755 /* need to add blanking flags */
1756 brasero_burn_caps_get_blanking_flags_real (self,
1757 brasero_burn_session_get_strict_support (session) == FALSE,
1758 media,
1759 session_flags,
1760 &blank_supported,
1761 &blank_compulsory);
1762 (*supported_flags) |= blank_supported;
1763 (*compulsory_flags) |= blank_compulsory;
1764 }
1765
1766 }
1767 else if (result != BRASERO_BURN_OK)
1768 return result;
1769
1770 /* These are a special case for DVDRW sequential */
1771 if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_DVDRW)) {
1772 /* That's a way to give priority to MULTI over FAST
1773 * and leave the possibility to always use MULTI. */
1774 if (session_flags & BRASERO_BURN_FLAG_MULTI)
1775 (*supported_flags) &= ~BRASERO_BURN_FLAG_FAST_BLANK;
1776 else if ((session_flags & BRASERO_BURN_FLAG_FAST_BLANK)
1777 && (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
1778 /* We should be able to handle this case differently but unfortunately
1779 * there are buggy firmwares that won't report properly the supported
1780 * mode writes */
1781 if (!((*supported_flags) & BRASERO_BURN_FLAG_DAO))
1782 return BRASERO_BURN_NOT_SUPPORTED;
1783
1784 (*compulsory_flags) |= BRASERO_BURN_FLAG_DAO;
1785 }
1786 }
1787
1788 if (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) {
1789 /* make sure we remove MERGE/APPEND from supported and
1790 * compulsory since that's not possible anymore */
1791 (*supported_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
1792 (*compulsory_flags) &= ~(BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND);
1793 }
1794
1795 /* FIXME! we should restart the whole process if
1796 * ((session_flags & compulsory_flags) != compulsory_flags) since that
1797 * means that some supported files could be excluded but were not */
1798
1799 return BRASERO_BURN_OK;
1800 }
1801
1802 static BraseroBurnResult
brasero_burn_caps_get_flags_same_src_dest_for_types(BraseroBurnCaps * self,BraseroBurnSession * session,BraseroTrackType * input,BraseroTrackType * output,BraseroBurnFlag * supported_ret,BraseroBurnFlag * compulsory_ret)1803 brasero_burn_caps_get_flags_same_src_dest_for_types (BraseroBurnCaps *self,
1804 BraseroBurnSession *session,
1805 BraseroTrackType *input,
1806 BraseroTrackType *output,
1807 BraseroBurnFlag *supported_ret,
1808 BraseroBurnFlag *compulsory_ret)
1809 {
1810 GSList *iter;
1811 gboolean type_supported;
1812 BraseroBurnResult result;
1813 BraseroBurnFlag session_flags;
1814 BraseroFindLinkCtx ctx = { 0, NULL, 0, };
1815 BraseroBurnFlag supported_final = BRASERO_BURN_FLAG_NONE;
1816 BraseroBurnFlag compulsory_final = BRASERO_BURN_FLAG_ALL;
1817
1818 /* NOTE: there is no need to get the flags here since there are
1819 * no specific DISC => IMAGE flags. We just want to know if that
1820 * is possible. */
1821 BRASERO_BURN_LOG_TYPE (output, "Testing temporary image format");
1822
1823 brasero_caps_find_link_set_ctx (session, &ctx, input);
1824 ctx.io_flags = BRASERO_PLUGIN_IO_ACCEPT_FILE;
1825
1826 /* Here there is no need to try blanking as there
1827 * is no disc (saves a few debug lines) */
1828 result = brasero_caps_try_output (self, &ctx, output);
1829 if (result != BRASERO_BURN_OK) {
1830 BRASERO_BURN_LOG_TYPE (output, "Format not supported");
1831 return result;
1832 }
1833
1834 session_flags = brasero_burn_session_get_flags (session);
1835
1836 /* This format can be used to create an image. Check if can be
1837 * burnt now. Just find at least one medium. */
1838 type_supported = FALSE;
1839 for (iter = self->priv->caps_list; iter; iter = iter->next) {
1840 BraseroBurnFlag compulsory;
1841 BraseroBurnFlag supported;
1842 BraseroBurnResult result;
1843 BraseroMedia media;
1844 BraseroCaps *caps;
1845
1846 caps = iter->data;
1847 if (!brasero_track_type_get_has_medium (&caps->type))
1848 continue;
1849
1850 media = brasero_track_type_get_medium_type (&caps->type);
1851
1852 /* This type of disc cannot be burnt; skip them */
1853 if (media & BRASERO_MEDIUM_ROM)
1854 continue;
1855
1856 if ((media & BRASERO_MEDIUM_CD) == 0) {
1857 if (brasero_track_type_get_has_image (output)) {
1858 BraseroImageFormat format;
1859
1860 format = brasero_track_type_get_image_format (output);
1861 /* These three types only work with CDs. */
1862 if (format == BRASERO_IMAGE_FORMAT_CDRDAO
1863 || format == BRASERO_IMAGE_FORMAT_CLONE
1864 || format == BRASERO_IMAGE_FORMAT_CUE)
1865 continue;
1866 }
1867 else if (brasero_track_type_get_has_stream (output))
1868 continue;
1869 }
1870
1871 /* Merge all available flags for each possible medium type */
1872 supported = BRASERO_BURN_FLAG_NONE;
1873 compulsory = BRASERO_BURN_FLAG_NONE;
1874
1875 result = brasero_caps_get_flags_for_disc (self,
1876 brasero_burn_session_get_strict_support (session) == FALSE,
1877 session_flags,
1878 media,
1879 output,
1880 &supported,
1881 &compulsory);
1882
1883 if (result != BRASERO_BURN_OK)
1884 continue;
1885
1886 type_supported = TRUE;
1887 supported_final |= supported;
1888 compulsory_final &= compulsory;
1889 }
1890
1891 BRASERO_BURN_LOG_TYPE (output, "Format supported %i", type_supported);
1892 if (!type_supported)
1893 return BRASERO_BURN_NOT_SUPPORTED;
1894
1895 *supported_ret = supported_final;
1896 *compulsory_ret = compulsory_final;
1897 return BRASERO_BURN_OK;
1898 }
1899
1900 static BraseroBurnResult
brasero_burn_caps_get_flags_same_src_dest(BraseroBurnCaps * self,BraseroBurnSession * session,BraseroBurnFlag * supported_ret,BraseroBurnFlag * compulsory_ret)1901 brasero_burn_caps_get_flags_same_src_dest (BraseroBurnCaps *self,
1902 BraseroBurnSession *session,
1903 BraseroBurnFlag *supported_ret,
1904 BraseroBurnFlag *compulsory_ret)
1905 {
1906 BraseroTrackType input;
1907 BraseroBurnResult result;
1908 gboolean copy_supported;
1909 BraseroTrackType output;
1910 BraseroImageFormat format;
1911 BraseroBurnFlag session_flags;
1912 BraseroBurnFlag supported_final = BRASERO_BURN_FLAG_NONE;
1913 BraseroBurnFlag compulsory_final = BRASERO_BURN_FLAG_ALL;
1914
1915 BRASERO_BURN_LOG ("Retrieving disc copy flags with same source and destination");
1916
1917 /* To determine if a CD/DVD can be copied using the same source/dest,
1918 * we first determine if can be imaged and then what are the flags when
1919 * we can burn it to a particular medium type. */
1920 memset (&input, 0, sizeof (BraseroTrackType));
1921 brasero_burn_session_get_input_type (session, &input);
1922 BRASERO_BURN_LOG_TYPE (&input, "input");
1923
1924 session_flags = brasero_burn_session_get_flags (session);
1925 BRASERO_BURN_LOG_FLAGS (session_flags, "(FLAGS) Session flags");
1926
1927 /* Check the current flags are possible */
1928 if (session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_NO_TMP_FILES))
1929 return BRASERO_BURN_NOT_SUPPORTED;
1930
1931 /* Check for stream type */
1932 brasero_track_type_set_has_stream (&output);
1933 /* FIXME! */
1934 brasero_track_type_set_stream_format (&output,
1935 BRASERO_AUDIO_FORMAT_RAW|
1936 BRASERO_METADATA_INFO);
1937
1938 result = brasero_burn_caps_get_flags_same_src_dest_for_types (self,
1939 session,
1940 &input,
1941 &output,
1942 &supported_final,
1943 &compulsory_final);
1944 if (result == BRASERO_BURN_CANCEL)
1945 return result;
1946
1947 copy_supported = (result == BRASERO_BURN_OK);
1948
1949 /* Check flags for all available format */
1950 format = BRASERO_IMAGE_FORMAT_CDRDAO;
1951 brasero_track_type_set_has_image (&output);
1952 for (; format > BRASERO_IMAGE_FORMAT_NONE; format >>= 1) {
1953 BraseroBurnFlag supported;
1954 BraseroBurnFlag compulsory;
1955
1956 /* check if this image type is possible given the current flags */
1957 if (format != BRASERO_IMAGE_FORMAT_CLONE
1958 && (session_flags & BRASERO_BURN_FLAG_RAW))
1959 continue;
1960
1961 brasero_track_type_set_image_format (&output, format);
1962
1963 supported = BRASERO_BURN_FLAG_NONE;
1964 compulsory = BRASERO_BURN_FLAG_NONE;
1965 result = brasero_burn_caps_get_flags_same_src_dest_for_types (self,
1966 session,
1967 &input,
1968 &output,
1969 &supported,
1970 &compulsory);
1971 if (result == BRASERO_BURN_CANCEL)
1972 return result;
1973
1974 if (result != BRASERO_BURN_OK)
1975 continue;
1976
1977 copy_supported = TRUE;
1978 supported_final |= supported;
1979 compulsory_final &= compulsory;
1980 }
1981
1982 if (!copy_supported)
1983 return BRASERO_BURN_NOT_SUPPORTED;
1984
1985 *supported_ret |= supported_final;
1986 *compulsory_ret |= compulsory_final;
1987
1988 /* we also add these two flags as being supported
1989 * since they could be useful and can't be tested
1990 * until the disc is inserted which it is not at the
1991 * moment */
1992 (*supported_ret) |= (BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE|
1993 BRASERO_BURN_FLAG_FAST_BLANK);
1994
1995 if (brasero_track_type_get_medium_type (&input) & BRASERO_MEDIUM_HAS_AUDIO) {
1996 /* This is a special case for audio discs.
1997 * Since they may contain CD-TEXT and
1998 * since CD-TEXT can only be written with
1999 * DAO then we must make sure the user
2000 * can't use MULTI since then DAO is
2001 * impossible. */
2002 (*compulsory_ret) |= BRASERO_BURN_FLAG_DAO;
2003
2004 /* This is just to make sure */
2005 (*supported_ret) &= (~BRASERO_BURN_FLAG_MULTI);
2006 (*compulsory_ret) &= (~BRASERO_BURN_FLAG_MULTI);
2007 }
2008
2009 return BRASERO_BURN_OK;
2010 }
2011
2012 /**
2013 * This is meant to use as internal API
2014 */
2015 BraseroBurnResult
brasero_caps_session_get_image_flags(BraseroTrackType * input,BraseroTrackType * output,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)2016 brasero_caps_session_get_image_flags (BraseroTrackType *input,
2017 BraseroTrackType *output,
2018 BraseroBurnFlag *supported,
2019 BraseroBurnFlag *compulsory)
2020 {
2021 BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_NONE;
2022 BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_CHECK_SIZE|BRASERO_BURN_FLAG_NOGRACE;
2023
2024 BRASERO_BURN_LOG ("FLAGS: image required");
2025
2026 /* In this case no APPEND/MERGE is possible */
2027 if (brasero_track_type_get_has_medium (input))
2028 supported_flags |= BRASERO_BURN_FLAG_EJECT;
2029
2030 *supported = supported_flags;
2031 *compulsory = compulsory_flags;
2032
2033 BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2034 BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2035
2036 return BRASERO_BURN_OK;
2037 }
2038
2039 /**
2040 * brasero_burn_session_get_burn_flags:
2041 * @session: a #BraseroBurnSession
2042 * @supported: a #BraseroBurnFlag or NULL
2043 * @compulsory: a #BraseroBurnFlag or NULL
2044 *
2045 * Given the various parameters stored in @session, this function
2046 * stores:
2047 * - the flags that can be used (@supported)
2048 * - the flags that must be used (@compulsory)
2049 * when writing @session to a disc.
2050 *
2051 * Return value: a #BraseroBurnResult.
2052 * BRASERO_BURN_OK if the retrieval was successful.
2053 * BRASERO_BURN_ERR otherwise.
2054 **/
2055
2056 BraseroBurnResult
brasero_burn_session_get_burn_flags(BraseroBurnSession * session,BraseroBurnFlag * supported,BraseroBurnFlag * compulsory)2057 brasero_burn_session_get_burn_flags (BraseroBurnSession *session,
2058 BraseroBurnFlag *supported,
2059 BraseroBurnFlag *compulsory)
2060 {
2061 gboolean res;
2062 BraseroMedia media;
2063 BraseroBurnCaps *self;
2064 BraseroTrackType *input;
2065 BraseroBurnResult result;
2066
2067 BraseroBurnFlag session_flags;
2068 /* FIXME: what's the meaning of NOGRACE when outputting ? */
2069 BraseroBurnFlag compulsory_flags = BRASERO_BURN_FLAG_NONE;
2070 BraseroBurnFlag supported_flags = BRASERO_BURN_FLAG_CHECK_SIZE|
2071 BRASERO_BURN_FLAG_NOGRACE;
2072
2073 self = brasero_burn_caps_get_default ();
2074
2075 input = brasero_track_type_new ();
2076 brasero_burn_session_get_input_type (session, input);
2077 BRASERO_BURN_LOG_WITH_TYPE (input,
2078 BRASERO_PLUGIN_IO_NONE,
2079 "FLAGS: searching available flags for input");
2080
2081 if (brasero_burn_session_is_dest_file (session)) {
2082 BraseroTrackType *output;
2083
2084 BRASERO_BURN_LOG ("FLAGS: image required");
2085
2086 output = brasero_track_type_new ();
2087 brasero_burn_session_get_output_type (session, output);
2088 brasero_caps_session_get_image_flags (input, output, supported, compulsory);
2089 brasero_track_type_free (output);
2090
2091 brasero_track_type_free (input);
2092 g_object_unref (self);
2093 return BRASERO_BURN_OK;
2094 }
2095
2096 supported_flags |= BRASERO_BURN_FLAG_EJECT;
2097
2098 /* special case */
2099 if (brasero_burn_session_same_src_dest_drive (session)) {
2100 BRASERO_BURN_LOG ("Same source and destination");
2101 result = brasero_burn_caps_get_flags_same_src_dest (self,
2102 session,
2103 &supported_flags,
2104 &compulsory_flags);
2105
2106 /* These flags are of course never possible */
2107 supported_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
2108 BRASERO_BURN_FLAG_MERGE);
2109 compulsory_flags &= ~(BRASERO_BURN_FLAG_NO_TMP_FILES|
2110 BRASERO_BURN_FLAG_MERGE);
2111
2112 if (result == BRASERO_BURN_OK) {
2113 BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2114 BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2115
2116 *supported = supported_flags;
2117 *compulsory = compulsory_flags;
2118 }
2119 else
2120 BRASERO_BURN_LOG ("No available flags for copy");
2121
2122 brasero_track_type_free (input);
2123 g_object_unref (self);
2124 return result;
2125 }
2126
2127 session_flags = brasero_burn_session_get_flags (session);
2128 BRASERO_BURN_LOG_FLAGS (session_flags, "FLAGS (session):");
2129
2130 /* sanity check:
2131 * - drive must support flags
2132 * - MERGE and BLANK are not possible together.
2133 * - APPEND and MERGE are compatible. MERGE wins
2134 * - APPEND and BLANK are incompatible */
2135 res = brasero_check_flags_for_drive (brasero_burn_session_get_burner (session), session_flags);
2136 if (!res) {
2137 BRASERO_BURN_LOG ("Session flags not supported by drive");
2138 brasero_track_type_free (input);
2139 g_object_unref (self);
2140 return BRASERO_BURN_ERR;
2141 }
2142
2143 if ((session_flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
2144 && (session_flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE)) {
2145 brasero_track_type_free (input);
2146 g_object_unref (self);
2147 return BRASERO_BURN_NOT_SUPPORTED;
2148 }
2149
2150 /* Let's get flags for recording */
2151 media = brasero_burn_session_get_dest_media (session);
2152 result = brasero_burn_caps_get_flags_for_medium (self,
2153 session,
2154 media,
2155 session_flags,
2156 input,
2157 &supported_flags,
2158 &compulsory_flags);
2159
2160 brasero_track_type_free (input);
2161 g_object_unref (self);
2162
2163 if (result != BRASERO_BURN_OK)
2164 return result;
2165
2166 brasero_burn_caps_flags_update_for_drive (session,
2167 &supported_flags,
2168 &compulsory_flags);
2169
2170 if (supported)
2171 *supported = supported_flags;
2172
2173 if (compulsory)
2174 *compulsory = compulsory_flags;
2175
2176 BRASERO_BURN_LOG_FLAGS (supported_flags, "FLAGS: supported");
2177 BRASERO_BURN_LOG_FLAGS (compulsory_flags, "FLAGS: compulsory");
2178 return BRASERO_BURN_OK;
2179 }
2180