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 <math.h>
36 #include <stdio.h>
37 #include <string.h>
38 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 
43 #include <glib.h>
44 #include <glib-object.h>
45 #include <glib/gi18n-lib.h>
46 #include <glib/gstdio.h>
47 
48 #include "brasero-burn.h"
49 
50 #include "libbrasero-marshal.h"
51 #include "burn-basics.h"
52 #include "burn-debug.h"
53 #include "burn-dbus.h"
54 #include "burn-task-ctx.h"
55 #include "burn-task.h"
56 #include "brasero-caps-burn.h"
57 
58 #include "brasero-drive-priv.h"
59 
60 #include "brasero-volume.h"
61 #include "brasero-drive.h"
62 
63 #include "brasero-tags.h"
64 #include "brasero-track.h"
65 #include "brasero-session.h"
66 #include "brasero-track-image.h"
67 #include "brasero-track-disc.h"
68 #include "brasero-session-helper.h"
69 
70 G_DEFINE_TYPE (BraseroBurn, brasero_burn, G_TYPE_OBJECT);
71 
72 typedef struct _BraseroBurnPrivate BraseroBurnPrivate;
73 struct _BraseroBurnPrivate {
74 	BraseroBurnCaps *caps;
75 	BraseroBurnSession *session;
76 
77 	GMainLoop *sleep_loop;
78 	guint timeout_id;
79 
80 	guint tasks_done;
81 	guint task_nb;
82 	BraseroTask *task;
83 
84 	BraseroDrive *src;
85 	BraseroDrive *dest;
86 
87 	gint appcookie;
88 
89 	guint64 session_start;
90 	guint64 session_end;
91 
92 	guint mounted_by_us:1;
93 };
94 
95 #define BRASERO_BURN_NOT_SUPPORTED_LOG(burn)					\
96 	{									\
97 		brasero_burn_log (burn,						\
98 				  "unsupported operation (in %s at %s)",	\
99 				  G_STRFUNC,					\
100 				  G_STRLOC);					\
101 		return BRASERO_BURN_NOT_SUPPORTED;				\
102 	}
103 
104 #define BRASERO_BURN_NOT_READY_LOG(burn)					\
105 	{									\
106 		brasero_burn_log (burn,						\
107 				  "not ready to operate (in %s at %s)",		\
108 				  G_STRFUNC,					\
109 				  G_STRLOC);					\
110 		return BRASERO_BURN_NOT_READY;					\
111 	}
112 
113 #define BRASERO_BURN_DEBUG(burn, message, ...)					\
114 	{									\
115 		gchar *format;							\
116 		BRASERO_BURN_LOG (message, ##__VA_ARGS__);			\
117 		format = g_strdup_printf ("%s (%s %s)",				\
118 					  message,				\
119 					  G_STRFUNC,				\
120 					  G_STRLOC);				\
121 		brasero_burn_log (burn,						\
122 				  format,					\
123 				  ##__VA_ARGS__);				\
124 		g_free (format);						\
125 	}
126 
127 typedef enum {
128 	ASK_DISABLE_JOLIET_SIGNAL,
129 	WARN_DATA_LOSS_SIGNAL,
130 	WARN_PREVIOUS_SESSION_LOSS_SIGNAL,
131 	WARN_AUDIO_TO_APPENDABLE_SIGNAL,
132 	WARN_REWRITABLE_SIGNAL,
133 	INSERT_MEDIA_REQUEST_SIGNAL,
134 	LOCATION_REQUEST_SIGNAL,
135 	PROGRESS_CHANGED_SIGNAL,
136 	ACTION_CHANGED_SIGNAL,
137 	DUMMY_SUCCESS_SIGNAL,
138 	EJECT_FAILURE_SIGNAL,
139 	BLANK_FAILURE_SIGNAL,
140 	INSTALL_MISSING_SIGNAL,
141 	LAST_SIGNAL
142 } BraseroBurnSignalType;
143 
144 static guint brasero_burn_signals [LAST_SIGNAL] = { 0 };
145 
146 #define BRASERO_BURN_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_BURN, BraseroBurnPrivate))
147 
148 #define MAX_EJECT_ATTEMPTS	5
149 #define MAX_MOUNT_ATTEMPTS	40
150 
151 #define MOUNT_TIMEOUT		500
152 
153 static GObjectClass *parent_class = NULL;
154 
155 static void
brasero_burn_powermanagement(BraseroBurn * self,gboolean wake)156 brasero_burn_powermanagement (BraseroBurn *self,
157 			      gboolean wake)
158 {
159 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (self);
160 
161 	if (wake)
162 	  	priv->appcookie = brasero_inhibit_suspend (_("Burning CD/DVD"));
163 	else
164 		brasero_uninhibit_suspend (priv->appcookie);
165 }
166 
167 /**
168  * brasero_burn_new:
169  *
170  *  Creates a new #BraseroBurn object.
171  *
172  * Return value: a #BraseroBurn object.
173  **/
174 
175 BraseroBurn *
brasero_burn_new()176 brasero_burn_new ()
177 {
178 	return g_object_new (BRASERO_TYPE_BURN, NULL);
179 }
180 
181 static void
brasero_burn_log(BraseroBurn * burn,const gchar * format,...)182 brasero_burn_log (BraseroBurn *burn,
183 		  const gchar *format,
184 		  ...)
185 {
186 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
187 	va_list arg_list;
188 
189 	va_start (arg_list, format);
190 	brasero_burn_session_logv (priv->session, format, arg_list);
191 	va_end (arg_list);
192 }
193 
194 static BraseroBurnResult
brasero_burn_emit_signal(BraseroBurn * burn,guint signal,BraseroBurnResult default_answer)195 brasero_burn_emit_signal (BraseroBurn *burn,
196                           guint signal,
197                           BraseroBurnResult default_answer)
198 {
199 	GValue instance_and_params;
200 	GValue return_value;
201 
202 	instance_and_params.g_type = 0;
203 	g_value_init (&instance_and_params, G_TYPE_FROM_INSTANCE (burn));
204 	g_value_set_instance (&instance_and_params, burn);
205 
206 	return_value.g_type = 0;
207 	g_value_init (&return_value, G_TYPE_INT);
208 	g_value_set_int (&return_value, default_answer);
209 
210 	g_signal_emitv (&instance_and_params,
211 			brasero_burn_signals [signal],
212 			0,
213 			&return_value);
214 
215 	g_value_unset (&instance_and_params);
216 
217 	return g_value_get_int (&return_value);
218 }
219 
220 static void
brasero_burn_action_changed_real(BraseroBurn * burn,BraseroBurnAction action)221 brasero_burn_action_changed_real (BraseroBurn *burn,
222 				  BraseroBurnAction action)
223 {
224 	g_signal_emit (burn,
225 		       brasero_burn_signals [ACTION_CHANGED_SIGNAL],
226 		       0,
227 		       action);
228 
229 	if (action == BRASERO_BURN_ACTION_FINISHED)
230 		g_signal_emit (burn,
231 		               brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
232 		               0,
233 		               1.0,
234 		               1.0,
235 		               -1L);
236 	else if (action == BRASERO_BURN_ACTION_EJECTING)
237 		g_signal_emit (burn,
238 			       brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
239 			       0,
240 			       -1.0,
241 			       -1.0,
242 			       -1L);
243 }
244 
245 static gboolean
brasero_burn_wakeup(BraseroBurn * burn)246 brasero_burn_wakeup (BraseroBurn *burn)
247 {
248 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
249 
250 	if (priv->sleep_loop)
251 		g_main_loop_quit (priv->sleep_loop);
252 
253 	priv->timeout_id = 0;
254 	return FALSE;
255 }
256 
257 static BraseroBurnResult
brasero_burn_sleep(BraseroBurn * burn,gint msec)258 brasero_burn_sleep (BraseroBurn *burn, gint msec)
259 {
260 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
261 	GMainLoop *loop;
262 
263 	priv->sleep_loop = g_main_loop_new (NULL, FALSE);
264 	priv->timeout_id = g_timeout_add (msec,
265 					  (GSourceFunc) brasero_burn_wakeup,
266 					  burn);
267 
268 	/* Keep a reference to the loop in case we are cancelled to destroy it */
269 	loop = priv->sleep_loop;
270 	g_main_loop_run (loop);
271 
272 	if (priv->timeout_id) {
273 		g_source_remove (priv->timeout_id);
274 		priv->timeout_id = 0;
275 	}
276 
277 	g_main_loop_unref (loop);
278 	if (priv->sleep_loop) {
279 		priv->sleep_loop = NULL;
280 		return BRASERO_BURN_OK;
281 	}
282 
283 	/* if sleep_loop = NULL => We've been cancelled */
284 	return BRASERO_BURN_CANCEL;
285 }
286 
287 static BraseroBurnResult
brasero_burn_reprobe(BraseroBurn * burn)288 brasero_burn_reprobe (BraseroBurn *burn)
289 {
290 	BraseroBurnPrivate *priv;
291 	BraseroBurnResult result = BRASERO_BURN_OK;
292 
293 	priv = BRASERO_BURN_PRIVATE (burn);
294 
295 	BRASERO_BURN_LOG ("Reprobing for medium");
296 
297 	/* reprobe the medium and wait for it to be probed */
298 	brasero_drive_reprobe (priv->dest);
299 	while (brasero_drive_probing (priv->dest)) {
300 		result = brasero_burn_sleep (burn, 250);
301 		if (result != BRASERO_BURN_OK)
302 			return result;
303 	}
304 
305 	return result;
306 }
307 
308 static BraseroBurnResult
brasero_burn_unmount(BraseroBurn * self,BraseroMedium * medium,GError ** error)309 brasero_burn_unmount (BraseroBurn *self,
310                       BraseroMedium *medium,
311                       GError **error)
312 {
313 	guint counter = 0;
314 
315 	if (!medium)
316 		return BRASERO_BURN_OK;
317 
318 	/* Retry several times, since sometimes the drives are really busy */
319 	while (brasero_volume_is_mounted (BRASERO_VOLUME (medium))) {
320 		GError *ret_error;
321 		BraseroBurnResult result;
322 
323 		counter ++;
324 		if (counter > MAX_EJECT_ATTEMPTS) {
325 			BRASERO_BURN_LOG ("Max attempts reached at unmounting");
326 			if (error && !(*error))
327 				g_set_error (error,
328 					     BRASERO_BURN_ERROR,
329 					     BRASERO_BURN_ERROR_DRIVE_BUSY,
330 					     "%s. %s",
331 					     _("The drive is busy"),
332 					     _("Make sure another application is not using it"));
333 			return BRASERO_BURN_ERR;
334 		}
335 
336 		BRASERO_BURN_LOG ("Retrying unmounting");
337 
338 		ret_error = NULL;
339 		brasero_volume_umount (BRASERO_VOLUME (medium), TRUE, NULL);
340 
341 		if (ret_error) {
342 			BRASERO_BURN_LOG ("Ejection error: %s", ret_error->message);
343 			g_error_free (ret_error);
344 		}
345 
346 		result = brasero_burn_sleep (self, 500);
347 		if (result != BRASERO_BURN_OK)
348 			return result;
349 	}
350 
351 	return BRASERO_BURN_OK;
352 }
353 
354 static BraseroBurnResult
brasero_burn_emit_eject_failure_signal(BraseroBurn * burn,BraseroDrive * drive)355 brasero_burn_emit_eject_failure_signal (BraseroBurn *burn,
356                                         BraseroDrive *drive)
357 {
358 	GValue instance_and_params [4];
359 	GValue return_value;
360 
361 	instance_and_params [0].g_type = 0;
362 	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (burn));
363 	g_value_set_instance (instance_and_params, burn);
364 
365 	instance_and_params [1].g_type = 0;
366 	g_value_init (instance_and_params + 1, G_TYPE_FROM_INSTANCE (drive));
367 	g_value_set_instance (instance_and_params + 1, drive);
368 
369 	return_value.g_type = 0;
370 	g_value_init (&return_value, G_TYPE_INT);
371 	g_value_set_int (&return_value, BRASERO_BURN_CANCEL);
372 
373 	g_signal_emitv (instance_and_params,
374 			brasero_burn_signals [EJECT_FAILURE_SIGNAL],
375 			0,
376 			&return_value);
377 
378 	g_value_unset (instance_and_params);
379 
380 	return g_value_get_int (&return_value);
381 }
382 
383 static BraseroBurnResult
brasero_burn_eject(BraseroBurn * self,BraseroDrive * drive,GError ** error)384 brasero_burn_eject (BraseroBurn *self,
385 		    BraseroDrive *drive,
386 		    GError **error)
387 {
388 	guint counter = 0;
389 	BraseroMedium *medium;
390 	BraseroBurnResult result;
391 
392 	BRASERO_BURN_LOG ("Ejecting drive/medium");
393 
394 	/* Unmount, ... */
395 	medium = brasero_drive_get_medium (drive);
396 	result = brasero_burn_unmount (self, medium, error);
397 	if (result != BRASERO_BURN_OK)
398 		return result;
399 
400 	/* Release lock, ... */
401 	if (brasero_drive_is_locked (drive, NULL)) {
402 		if (!brasero_drive_unlock (drive)) {
403 			gchar *name;
404 
405 			name = brasero_drive_get_display_name (drive);
406 			g_set_error (error,
407 				     BRASERO_BURN_ERROR,
408 				     BRASERO_BURN_ERROR_GENERAL,
409 				     _("\"%s\" cannot be unlocked"),
410 				     name);
411 			g_free (name);
412 			return BRASERO_BURN_ERR;
413 		}
414 	}
415 
416 	/* Retry several times, since sometimes the drives are really busy */
417 	while (brasero_drive_get_medium (drive) || brasero_drive_probing (drive)) {
418 		GError *ret_error;
419 
420 		/* Don't interrupt a probe */
421 		if (brasero_drive_probing (drive)) {
422 			result = brasero_burn_sleep (self, 500);
423 			if (result != BRASERO_BURN_OK)
424 				return result;
425 
426 			continue;
427 		}
428 
429 		counter ++;
430 		if (counter == 1)
431 			brasero_burn_action_changed_real (self, BRASERO_BURN_ACTION_EJECTING);
432 
433 		if (counter > MAX_EJECT_ATTEMPTS) {
434 			BRASERO_BURN_LOG ("Max attempts reached at ejecting");
435 
436 			result = brasero_burn_emit_eject_failure_signal (self, drive);
437 			if (result != BRASERO_BURN_OK)
438 				return result;
439 
440 			continue;
441 		}
442 
443 		BRASERO_BURN_LOG ("Retrying ejection");
444 		ret_error = NULL;
445 		brasero_drive_eject (drive, TRUE, &ret_error);
446 
447 		if (ret_error) {
448 			BRASERO_BURN_LOG ("Ejection error: %s", ret_error->message);
449 			g_error_free (ret_error);
450 		}
451 
452 		result = brasero_burn_sleep (self, 500);
453 		if (result != BRASERO_BURN_OK)
454 			return result;
455 	}
456 
457 	return BRASERO_BURN_OK;
458 }
459 
460 static BraseroBurnResult
brasero_burn_ask_for_media(BraseroBurn * burn,BraseroDrive * drive,BraseroBurnError error_type,BraseroMedia required_media,GError ** error)461 brasero_burn_ask_for_media (BraseroBurn *burn,
462 			    BraseroDrive *drive,
463 			    BraseroBurnError error_type,
464 			    BraseroMedia required_media,
465 			    GError **error)
466 {
467 	GValue instance_and_params [4];
468 	GValue return_value;
469 
470 	instance_and_params [0].g_type = 0;
471 	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (burn));
472 	g_value_set_instance (instance_and_params, burn);
473 
474 	instance_and_params [1].g_type = 0;
475 	g_value_init (instance_and_params + 1, G_TYPE_FROM_INSTANCE (drive));
476 	g_value_set_instance (instance_and_params + 1, drive);
477 
478 	instance_and_params [2].g_type = 0;
479 	g_value_init (instance_and_params + 2, G_TYPE_INT);
480 	g_value_set_int (instance_and_params + 2, error_type);
481 
482 	instance_and_params [3].g_type = 0;
483 	g_value_init (instance_and_params + 3, G_TYPE_INT);
484 	g_value_set_int (instance_and_params + 3, required_media);
485 
486 	return_value.g_type = 0;
487 	g_value_init (&return_value, G_TYPE_INT);
488 	g_value_set_int (&return_value, BRASERO_BURN_CANCEL);
489 
490 	g_signal_emitv (instance_and_params,
491 			brasero_burn_signals [INSERT_MEDIA_REQUEST_SIGNAL],
492 			0,
493 			&return_value);
494 
495 	g_value_unset (instance_and_params);
496 	g_value_unset (instance_and_params + 1);
497 
498 	return g_value_get_int (&return_value);
499 }
500 
501 static BraseroBurnResult
brasero_burn_ask_for_src_media(BraseroBurn * burn,BraseroBurnError error_type,BraseroMedia required_media,GError ** error)502 brasero_burn_ask_for_src_media (BraseroBurn *burn,
503 				BraseroBurnError error_type,
504 				BraseroMedia required_media,
505 				GError **error)
506 {
507 	BraseroMedium *medium;
508 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
509 
510 	medium = brasero_drive_get_medium (priv->src);
511 	if (brasero_medium_get_status (medium) != BRASERO_MEDIUM_NONE
512 	||  brasero_drive_probing (priv->src)) {
513 		BraseroBurnResult result;
514 		result = brasero_burn_eject (burn, priv->src, error);
515 		if (result != BRASERO_BURN_OK)
516 			return result;
517 	}
518 
519 	return brasero_burn_ask_for_media (burn,
520 					   priv->src,
521 					   error_type,
522 					   required_media,
523 					   error);
524 }
525 
526 static BraseroBurnResult
brasero_burn_ask_for_dest_media(BraseroBurn * burn,BraseroBurnError error_type,BraseroMedia required_media,GError ** error)527 brasero_burn_ask_for_dest_media (BraseroBurn *burn,
528 				 BraseroBurnError error_type,
529 				 BraseroMedia required_media,
530 				 GError **error)
531 {
532 	BraseroDrive *drive;
533 	BraseroMedium *medium;
534 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
535 
536 	/* Since in some cases (like when we reload
537 	 * a medium after a copy), the destination
538 	 * medium may not be locked yet we use
539 	 * separate variable drive. */
540 	if (!priv->dest) {
541 		drive = brasero_burn_session_get_burner (priv->session);
542 		if (!drive) {
543 			g_set_error (error,
544 				     BRASERO_BURN_ERROR,
545 				     BRASERO_BURN_ERROR_OUTPUT_NONE,
546 				     "%s", _("No burner specified"));
547 			return BRASERO_BURN_ERR;
548 		}
549 	}
550 	else
551 		drive = priv->dest;
552 
553 	medium = brasero_drive_get_medium (drive);
554 	if (brasero_medium_get_status (medium) != BRASERO_MEDIUM_NONE
555 	||  brasero_drive_probing (drive)) {
556 		BraseroBurnResult result;
557 
558 		result = brasero_burn_eject (burn, drive, error);
559 		if (result != BRASERO_BURN_OK)
560 			return result;
561 	}
562 
563 	return brasero_burn_ask_for_media (burn,
564 					   drive,
565 					   error_type,
566 					   required_media,
567 					   error);
568 }
569 
570 static BraseroBurnResult
brasero_burn_lock_src_media(BraseroBurn * burn,GError ** error)571 brasero_burn_lock_src_media (BraseroBurn *burn,
572 			     GError **error)
573 {
574 	gchar *failure = NULL;
575 	BraseroMedia media;
576 	BraseroMedium *medium;
577 	BraseroBurnResult result;
578 	BraseroBurnError error_type;
579 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
580 
581 	priv->src = brasero_burn_session_get_src_drive (priv->session);
582 	if (!priv->src) {
583 		g_set_error (error,
584 			     BRASERO_BURN_ERROR,
585 			     BRASERO_BURN_ERROR_GENERAL,
586 			     "%s", _("No source drive specified"));
587 		return BRASERO_BURN_ERR;
588 	}
589 
590 
591 again:
592 
593 	while (brasero_drive_probing (priv->src)) {
594 		result = brasero_burn_sleep (burn, 500);
595 		if (result != BRASERO_BURN_OK)
596 			return result;
597 	}
598 
599 	medium = brasero_drive_get_medium (priv->src);
600 	if (brasero_volume_is_mounted (BRASERO_VOLUME (medium))) {
601 		if (!brasero_volume_umount (BRASERO_VOLUME (medium), TRUE, NULL))
602 			g_warning ("Couldn't unmount volume in drive: %s",
603 				   brasero_drive_get_device (priv->src));
604 	}
605 
606 	/* NOTE: we used to unmount the media before now we shouldn't need that
607 	 * get any information from the drive */
608 	media = brasero_medium_get_status (medium);
609 	if (media == BRASERO_MEDIUM_NONE)
610 		error_type = BRASERO_BURN_ERROR_MEDIUM_NONE;
611 	else if (media == BRASERO_MEDIUM_BUSY)
612 		error_type = BRASERO_BURN_ERROR_DRIVE_BUSY;
613 	else if (media == BRASERO_MEDIUM_UNSUPPORTED)
614 		error_type = BRASERO_BURN_ERROR_MEDIUM_INVALID;
615 	else if (media & BRASERO_MEDIUM_BLANK)
616 		error_type = BRASERO_BURN_ERROR_MEDIUM_NO_DATA;
617 	else
618 		error_type = BRASERO_BURN_ERROR_NONE;
619 
620 	if (error_type != BRASERO_BURN_ERROR_NONE) {
621 		result = brasero_burn_ask_for_src_media (burn,
622 							 BRASERO_BURN_ERROR_MEDIUM_NO_DATA,
623 							 error_type,
624 							 error);
625 		if (result != BRASERO_BURN_OK)
626 			return result;
627 
628 		goto again;
629 	}
630 
631 	if (!brasero_drive_is_locked (priv->src, NULL)
632 	&&  !brasero_drive_lock (priv->src, _("Ongoing copying process"), &failure)) {
633 		g_set_error (error,
634 			     BRASERO_BURN_ERROR,
635 			     BRASERO_BURN_ERROR_GENERAL,
636 			     _("The drive cannot be locked (%s)"),
637 			     failure);
638 		return BRASERO_BURN_ERR;
639 	}
640 
641 	return BRASERO_BURN_OK;
642 }
643 
644 static BraseroBurnResult
brasero_burn_reload_src_media(BraseroBurn * burn,BraseroBurnError error_code,GError ** error)645 brasero_burn_reload_src_media (BraseroBurn *burn,
646 			       BraseroBurnError error_code,
647 			       GError **error)
648 {
649 	BraseroBurnResult result;
650 
651 	result = brasero_burn_ask_for_src_media (burn,
652 						 error_code,
653 						 BRASERO_MEDIUM_HAS_DATA,
654 						 error);
655 	if (result != BRASERO_BURN_OK)
656 		return result;
657 
658 	result = brasero_burn_lock_src_media (burn, error);
659 	return result;
660 }
661 
662 static BraseroBurnResult
brasero_burn_lock_rewritable_media(BraseroBurn * burn,GError ** error)663 brasero_burn_lock_rewritable_media (BraseroBurn *burn,
664 				    GError **error)
665 {
666 	gchar *failure;
667 	BraseroMedia media;
668 	BraseroMedium *medium;
669 	BraseroBurnResult result;
670 	BraseroBurnError error_type;
671 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
672 
673 	priv->dest = brasero_burn_session_get_burner (priv->session);
674 	if (!priv->dest) {
675 		g_set_error (error,
676 			     BRASERO_BURN_ERROR,
677 			     BRASERO_BURN_ERROR_OUTPUT_NONE,
678 			     "%s", _("No burner specified"));
679 		return BRASERO_BURN_NOT_SUPPORTED;
680 	}
681 
682  again:
683 
684 	while (brasero_drive_probing (priv->dest)) {
685 		result = brasero_burn_sleep (burn, 500);
686 		if (result != BRASERO_BURN_OK)
687 			return result;
688 	}
689 
690 	medium = brasero_drive_get_medium (priv->dest);
691 	if (!brasero_medium_can_be_rewritten (medium)) {
692 		g_set_error (error,
693 			     BRASERO_BURN_ERROR,
694 			     BRASERO_BURN_ERROR_MEDIUM_NOT_REWRITABLE,
695 			     "%s", _("The drive has no rewriting capabilities"));
696 		return BRASERO_BURN_NOT_SUPPORTED;
697 	}
698 
699 	if (brasero_volume_is_mounted (BRASERO_VOLUME (medium))) {
700 		if (!brasero_volume_umount (BRASERO_VOLUME (medium), TRUE, NULL))
701 			g_warning ("Couldn't unmount volume in drive: %s",
702 				   brasero_drive_get_device (priv->dest));
703 	}
704 
705 	media = brasero_medium_get_status (medium);
706 	if (media == BRASERO_MEDIUM_NONE)
707 		error_type = BRASERO_BURN_ERROR_MEDIUM_NONE;
708 	else if (media == BRASERO_MEDIUM_BUSY)
709 		error_type = BRASERO_BURN_ERROR_DRIVE_BUSY;
710 	else if (media == BRASERO_MEDIUM_UNSUPPORTED)
711 		error_type = BRASERO_BURN_ERROR_MEDIUM_INVALID;
712 	else if (!(media & BRASERO_MEDIUM_REWRITABLE))
713 		error_type = BRASERO_BURN_ERROR_MEDIUM_NOT_REWRITABLE;
714 	else
715 		error_type = BRASERO_BURN_ERROR_NONE;
716 
717 	if (error_type != BRASERO_BURN_ERROR_NONE) {
718 		result = brasero_burn_ask_for_dest_media (burn,
719 							  error_type,
720 							  BRASERO_MEDIUM_REWRITABLE|
721 							  BRASERO_MEDIUM_HAS_DATA,
722 							  error);
723 
724 		if (result != BRASERO_BURN_OK)
725 			return result;
726 
727 		goto again;
728 	}
729 
730 	if (!brasero_drive_is_locked (priv->dest, NULL)
731 	&&  !brasero_drive_lock (priv->dest, _("Ongoing blanking process"), &failure)) {
732 		g_set_error (error,
733 			     BRASERO_BURN_ERROR,
734 			     BRASERO_BURN_ERROR_GENERAL,
735 			     _("The drive cannot be locked (%s)"),
736 			     failure);
737 		return BRASERO_BURN_ERR;
738 	}
739 
740 	return BRASERO_BURN_OK;
741 }
742 
743 static BraseroBurnResult
brasero_burn_lock_dest_media(BraseroBurn * burn,BraseroBurnError * ret_error,GError ** error)744 brasero_burn_lock_dest_media (BraseroBurn *burn,
745 			      BraseroBurnError *ret_error,
746 			      GError **error)
747 {
748 	gchar *failure;
749 	BraseroMedia media;
750 	BraseroBurnError berror;
751 	BraseroMedium *medium;
752 	BraseroBurnResult result;
753 	BraseroTrackType *input = NULL;
754 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
755 
756 	priv->dest = brasero_burn_session_get_burner (priv->session);
757 	if (!priv->dest) {
758 		g_set_error (error,
759 			     BRASERO_BURN_ERROR,
760 			     BRASERO_BURN_ERROR_OUTPUT_NONE,
761 			     "%s", _("No burner specified"));
762 		return BRASERO_BURN_ERR;
763 	}
764 
765 	/* Check the capabilities of the drive */
766 	if (!brasero_drive_can_write (priv->dest)) {
767 		g_set_error (error,
768 			     BRASERO_BURN_ERROR,
769 			     BRASERO_BURN_ERROR_GENERAL,
770 			     "%s", _("The drive cannot burn"));
771 		BRASERO_BURN_NOT_SUPPORTED_LOG (burn);
772 	}
773 
774 	/* NOTE: don't lock the drive here yet as
775 	 * otherwise we'd be probing forever. */
776 	while (brasero_drive_probing (priv->dest)) {
777 		result = brasero_burn_sleep (burn, 500);
778 		if (result != BRASERO_BURN_OK)
779 			return result;
780 	}
781 
782 	medium = brasero_drive_get_medium (priv->dest);
783 	if (!medium) {
784 		result = BRASERO_BURN_NEED_RELOAD;
785 		berror = BRASERO_BURN_ERROR_MEDIUM_NONE;
786 		goto end;
787 	}
788 
789 	/* unmount the medium */
790 	result = brasero_burn_unmount (burn, medium, error);
791 	if (result != BRASERO_BURN_OK)
792 		return result;
793 
794 	result = BRASERO_BURN_OK;
795 	berror = BRASERO_BURN_ERROR_NONE;
796 
797 	media = brasero_medium_get_status (medium);
798 	BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_DISC,
799 					 media,
800 					 BRASERO_PLUGIN_IO_NONE,
801 					 "Media inserted is");
802 
803 	if (media == BRASERO_MEDIUM_NONE) {
804 		result = BRASERO_BURN_NEED_RELOAD;
805 		berror = BRASERO_BURN_ERROR_MEDIUM_NONE;
806 		goto end;
807 	}
808 
809 	if (media == BRASERO_MEDIUM_UNSUPPORTED) {
810 		result = BRASERO_BURN_NEED_RELOAD;
811 		berror = BRASERO_BURN_ERROR_MEDIUM_INVALID;
812 		goto end;
813 	}
814 
815 	if (media == BRASERO_MEDIUM_BUSY) {
816 		result = BRASERO_BURN_NEED_RELOAD;
817 		berror = BRASERO_BURN_ERROR_DRIVE_BUSY;
818 		goto end;
819 	}
820 
821 	/* Make sure that media is supported and
822 	 * can be written to */
823 
824 	/* NOTE: Since we did not check the flags
825 	 * and since they might change, check if the
826 	 * session is supported without the flags.
827 	 * We use quite a strict checking though as
828 	 * from now on we require plugins to be
829 	 * ready. */
830 	result = brasero_burn_session_can_burn (priv->session, FALSE);
831 	if (result != BRASERO_BURN_OK) {
832 		BRASERO_BURN_LOG ("Inserted media is not supported");
833 		result = BRASERO_BURN_NEED_RELOAD;
834 		berror = BRASERO_BURN_ERROR_MEDIUM_INVALID;
835 		goto end;
836 	}
837 
838 	input = brasero_track_type_new ();
839 	brasero_burn_session_get_input_type (priv->session, input);
840 
841 	if (brasero_track_type_get_has_image (input)) {
842 		goffset medium_sec = 0;
843 		goffset session_sec = 0;
844 
845 		/* This test is only valid when it's an image
846 		 * as input which comes handy when copying
847 		 * from the same drive as we're sure we do
848 		 * have an image. */
849 		brasero_medium_get_capacity (medium,
850 		                             NULL,
851 		                             &medium_sec);
852 		brasero_burn_session_get_size (priv->session,
853 		                               &session_sec,
854 		                               NULL);
855 
856 		if (session_sec > medium_sec) {
857 			BRASERO_BURN_LOG ("Not enough space for image %"G_GOFFSET_FORMAT"/%"G_GOFFSET_FORMAT, session_sec, medium_sec);
858 			berror = BRASERO_BURN_ERROR_MEDIUM_SPACE;
859 			result = BRASERO_BURN_NEED_RELOAD;
860 			goto end;
861 		}
862 	}
863 
864 	/* Only lock the drive after all checks succeeded */
865 	if (!brasero_drive_is_locked (priv->dest, NULL)
866 	&&  !brasero_drive_lock (priv->dest, _("Ongoing burning process"), &failure)) {
867 		brasero_track_type_free (input);
868 
869 		g_set_error (error,
870 			     BRASERO_BURN_ERROR,
871 			     BRASERO_BURN_ERROR_GENERAL,
872 			     _("The drive cannot be locked (%s)"),
873 			     failure);
874 		return BRASERO_BURN_ERR;
875 	}
876 
877 end:
878 
879 	if (result != BRASERO_BURN_OK
880 	&& brasero_drive_is_locked (priv->dest, NULL))
881 		brasero_drive_unlock (priv->dest);
882 
883 	if (result == BRASERO_BURN_NEED_RELOAD && ret_error)
884 		*ret_error = berror;
885 
886 	brasero_track_type_free (input);
887 
888 	return result;
889 }
890 
891 static BraseroBurnResult
brasero_burn_reload_dest_media(BraseroBurn * burn,BraseroBurnError error_code,GError ** error)892 brasero_burn_reload_dest_media (BraseroBurn *burn,
893 				BraseroBurnError error_code,
894 				GError **error)
895 {
896 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
897 	BraseroMedia required_media;
898 	BraseroBurnResult result;
899 
900 again:
901 
902 	/* eject and ask the user to reload a disc */
903 	required_media = brasero_burn_session_get_required_media_type (priv->session);
904 	required_media &= (BRASERO_MEDIUM_WRITABLE|
905 			   BRASERO_MEDIUM_CD|
906 			   BRASERO_MEDIUM_DVD);
907 
908 	if (required_media == BRASERO_MEDIUM_NONE)
909 		required_media = BRASERO_MEDIUM_WRITABLE;
910 
911 	result = brasero_burn_ask_for_dest_media (burn,
912 						  error_code,
913 						  required_media,
914 						  error);
915 	if (result != BRASERO_BURN_OK)
916 		return result;
917 
918 	result = brasero_burn_lock_dest_media (burn,
919 					       &error_code,
920 					       error);
921 	if (result == BRASERO_BURN_NEED_RELOAD)
922 		goto again;
923 
924 	return result;
925 }
926 
927 static BraseroBurnResult
brasero_burn_lock_checksum_media(BraseroBurn * burn,GError ** error)928 brasero_burn_lock_checksum_media (BraseroBurn *burn,
929 				  GError **error)
930 {
931 	gchar *failure;
932 	BraseroMedia media;
933 	BraseroMedium *medium;
934 	BraseroBurnResult result;
935 	BraseroBurnError error_type;
936 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
937 
938 	priv->dest = brasero_burn_session_get_src_drive (priv->session);
939 
940 again:
941 
942 	while (brasero_drive_probing (priv->dest)) {
943 		result = brasero_burn_sleep (burn, 500);
944 		if (result != BRASERO_BURN_OK)
945 			return result;
946 	}
947 
948 	medium = brasero_drive_get_medium (priv->dest);
949 	media = brasero_medium_get_status (medium);
950 
951 	error_type = BRASERO_BURN_ERROR_NONE;
952 	BRASERO_BURN_LOG_DISC_TYPE (media, "Waiting for media to checksum");
953 
954 	if (media == BRASERO_MEDIUM_NONE) {
955 		/* NOTE: that's done on purpose since here if the drive is empty
956 		 * that's because we ejected it */
957 		result = brasero_burn_ask_for_dest_media (burn,
958 							  BRASERO_BURN_WARNING_CHECKSUM,
959 							  BRASERO_MEDIUM_NONE,
960 							  error);
961 		if (result != BRASERO_BURN_OK)
962 			return result;
963 	}
964 	else if (media == BRASERO_MEDIUM_BUSY)
965 		error_type = BRASERO_BURN_ERROR_DRIVE_BUSY;
966 	else if (media == BRASERO_MEDIUM_UNSUPPORTED)
967 		error_type = BRASERO_BURN_ERROR_MEDIUM_INVALID;
968 	else if (media & BRASERO_MEDIUM_BLANK)
969 		error_type = BRASERO_BURN_ERROR_MEDIUM_NO_DATA;
970 
971 	if (error_type != BRASERO_BURN_ERROR_NONE) {
972 		result = brasero_burn_ask_for_dest_media (burn,
973 							  BRASERO_BURN_WARNING_CHECKSUM,
974 							  BRASERO_MEDIUM_NONE,
975 							  error);
976 		if (result != BRASERO_BURN_OK)
977 			return result;
978 
979 		goto again;
980 	}
981 
982 	if (!brasero_drive_is_locked (priv->dest, NULL)
983 	&&  !brasero_drive_lock (priv->dest, _("Ongoing checksumming operation"), &failure)) {
984 		g_set_error (error,
985 			     BRASERO_BURN_ERROR,
986 			     BRASERO_BURN_ERROR_GENERAL,
987 			     _("The drive cannot be locked (%s)"),
988 			     failure);
989 		return BRASERO_BURN_ERR;
990 	}
991 
992 	/* if drive is mounted then unmount before checking anything */
993 /*	if (brasero_volume_is_mounted (BRASERO_VOLUME (medium))
994 	&& !brasero_volume_umount (BRASERO_VOLUME (medium), TRUE, NULL))
995 		g_warning ("Couldn't unmount volume in drive: %s",
996 			   brasero_drive_get_device (priv->dest));
997 */
998 
999 	return BRASERO_BURN_OK;
1000 }
1001 
1002 static BraseroBurnResult
brasero_burn_unlock_src_media(BraseroBurn * burn,GError ** error)1003 brasero_burn_unlock_src_media (BraseroBurn *burn,
1004 			       GError **error)
1005 {
1006 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1007 	BraseroMedium *medium;
1008 
1009 	if (!priv->src)
1010 		return BRASERO_BURN_OK;
1011 
1012 	/* If we mounted it ourselves, unmount it */
1013 	medium = brasero_drive_get_medium (priv->src);
1014 	if (priv->mounted_by_us) {
1015 		brasero_burn_unmount (burn, medium, error);
1016 		priv->mounted_by_us = FALSE;
1017 	}
1018 
1019 	if (brasero_drive_is_locked (priv->src, NULL))
1020 		brasero_drive_unlock (priv->src);
1021 
1022 	/* Never eject the source if we don't need to. Let the user do that. For
1023 	 * one thing it avoids breaking other applications that are using it
1024 	 * like for example totem. */
1025 	/* if (BRASERO_BURN_SESSION_EJECT (priv->session))
1026 		brasero_drive_eject (BRASERO_VOLUME (medium), FALSE, error); */
1027 
1028 	priv->src = NULL;
1029 	return BRASERO_BURN_OK;
1030 }
1031 
1032 static BraseroBurnResult
brasero_burn_unlock_dest_media(BraseroBurn * burn,GError ** error)1033 brasero_burn_unlock_dest_media (BraseroBurn *burn,
1034 				GError **error)
1035 {
1036 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1037 
1038 	if (!priv->dest)
1039 		return BRASERO_BURN_OK;
1040 
1041 	if (brasero_drive_is_locked (priv->dest, NULL))
1042 		brasero_drive_unlock (priv->dest);
1043 
1044 	if (!BRASERO_BURN_SESSION_EJECT (priv->session))
1045 		brasero_drive_reprobe (priv->dest);
1046 	else
1047 		brasero_burn_eject (burn, priv->dest, error);
1048 
1049 	priv->dest = NULL;
1050 	return BRASERO_BURN_OK;
1051 }
1052 
1053 static BraseroBurnResult
brasero_burn_unlock_medias(BraseroBurn * burn,GError ** error)1054 brasero_burn_unlock_medias (BraseroBurn *burn,
1055 			    GError **error)
1056 {
1057 	brasero_burn_unlock_dest_media (burn, error);
1058 	brasero_burn_unlock_src_media (burn, error);
1059 
1060 	return BRASERO_BURN_OK;
1061 }
1062 
1063 static void
brasero_burn_progress_changed(BraseroTaskCtx * task,BraseroBurn * burn)1064 brasero_burn_progress_changed (BraseroTaskCtx *task,
1065 			       BraseroBurn *burn)
1066 {
1067 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1068 	gdouble overall_progress = -1.0;
1069 	gdouble task_progress = -1.0;
1070 	glong time_remaining = -1;
1071 
1072 	/* get the task current progress */
1073 	if (brasero_task_ctx_get_progress (task, &task_progress) == BRASERO_BURN_OK) {
1074 		brasero_task_ctx_get_remaining_time (task, &time_remaining);
1075 		overall_progress = (task_progress + (gdouble) priv->tasks_done) /
1076 				   (gdouble) priv->task_nb;
1077 	}
1078 	else
1079 		overall_progress =  (gdouble) priv->tasks_done /
1080 				    (gdouble) priv->task_nb;
1081 
1082 	g_signal_emit (burn,
1083 		       brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
1084 		       0,
1085 		       overall_progress,
1086 		       task_progress,
1087 		       time_remaining);
1088 }
1089 
1090 static void
brasero_burn_action_changed(BraseroTask * task,BraseroBurnAction action,BraseroBurn * burn)1091 brasero_burn_action_changed (BraseroTask *task,
1092 			     BraseroBurnAction action,
1093 			     BraseroBurn *burn)
1094 {
1095 	brasero_burn_action_changed_real (burn, action);
1096 }
1097 
1098 /**
1099  * brasero_burn_get_action_string:
1100  * @burn: a #BraseroBurn
1101  * @action: a #BraseroBurnAction
1102  * @string: a #gchar **
1103  *
1104  * This function returns the current action (in @string)  of
1105  * an ongoing operation performed by @burn.
1106  * @action is used to set a default string in case there was
1107  * no string set by the backend to describe the current
1108  * operation.
1109  *
1110  **/
1111 
1112 void
brasero_burn_get_action_string(BraseroBurn * burn,BraseroBurnAction action,gchar ** string)1113 brasero_burn_get_action_string (BraseroBurn *burn,
1114 				BraseroBurnAction action,
1115 				gchar **string)
1116 {
1117 	BraseroBurnPrivate *priv;
1118 
1119 	g_return_if_fail (BRASERO_BURN (burn));
1120 	g_return_if_fail (string != NULL);
1121 
1122 	priv = BRASERO_BURN_PRIVATE (burn);
1123 	if (action == BRASERO_BURN_ACTION_FINISHED || !priv->task)
1124 		(*string) = g_strdup (brasero_burn_action_to_string (action));
1125 	else
1126 		brasero_task_ctx_get_current_action_string (BRASERO_TASK_CTX (priv->task),
1127 							    action,
1128 							    string);
1129 }
1130 
1131 /**
1132  * brasero_burn_status:
1133  * @burn: a #BraseroBurn
1134  * @media: a #BraseroMedia or NULL
1135  * @isosize: a #goffset or NULL
1136  * @written: a #goffset or NULL
1137  * @rate: a #guint64 or NULL
1138  *
1139  * Returns various information about the current operation
1140  * in @media (the current media type being burnt),
1141  * @isosize (the size of the data being burnt), @written (the
1142  * number of bytes having been written so far) and @rate
1143  * (the speed at which data are written).
1144  *
1145  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if there is
1146  * an ongoing operation; BRASERO_BURN_NOT_READY otherwise.
1147  **/
1148 
1149 BraseroBurnResult
brasero_burn_status(BraseroBurn * burn,BraseroMedia * media,goffset * isosize,goffset * written,guint64 * rate)1150 brasero_burn_status (BraseroBurn *burn,
1151 		     BraseroMedia *media,
1152 		     goffset *isosize,
1153 		     goffset *written,
1154 		     guint64 *rate)
1155 {
1156 	BraseroBurnPrivate *priv;
1157 	BraseroBurnResult result;
1158 
1159 	g_return_val_if_fail (BRASERO_BURN (burn), BRASERO_BURN_ERR);
1160 
1161 	priv = BRASERO_BURN_PRIVATE (burn);
1162 
1163 	if (!priv->task)
1164 		return BRASERO_BURN_NOT_READY;
1165 
1166 	if (isosize) {
1167 		goffset size_local = 0;
1168 
1169 		result = brasero_task_ctx_get_session_output_size (BRASERO_TASK_CTX (priv->task),
1170 								   NULL,
1171 								   &size_local);
1172 		if (result != BRASERO_BURN_OK)
1173 			*isosize = -1;
1174 		else
1175 			*isosize = size_local;
1176 	}
1177 
1178 	if (!brasero_task_is_running (priv->task))
1179 		return BRASERO_BURN_NOT_READY;
1180 
1181 	if (rate)
1182 		brasero_task_ctx_get_rate (BRASERO_TASK_CTX (priv->task), rate);
1183 
1184 	if (written) {
1185 		gint64 written_local = 0;
1186 
1187 		result = brasero_task_ctx_get_written (BRASERO_TASK_CTX (priv->task), &written_local);
1188 
1189 		if (result != BRASERO_BURN_OK)
1190 			*written = -1;
1191 		else
1192 			*written = written_local;
1193 	}
1194 
1195 	if (!media)
1196 		return BRASERO_BURN_OK;
1197 
1198 	/* return the disc we burn to if:
1199 	 * - that's the last task to perform
1200 	 * - brasero_burn_session_is_dest_file returns FALSE
1201 	 */
1202 	if (priv->tasks_done < priv->task_nb - 1) {
1203 		BraseroTrackType *input = NULL;
1204 
1205 		input = brasero_track_type_new ();
1206 		brasero_burn_session_get_input_type (priv->session, input);
1207 		if (brasero_track_type_get_has_medium (input))
1208 			*media = brasero_track_type_get_medium_type (input);
1209 		else
1210 			*media = BRASERO_MEDIUM_NONE;
1211 
1212 		brasero_track_type_free (input);
1213 	}
1214 	else if (brasero_burn_session_is_dest_file (priv->session))
1215 		*media = BRASERO_MEDIUM_FILE;
1216 	else
1217 		*media = brasero_burn_session_get_dest_media (priv->session);
1218 
1219 	return BRASERO_BURN_OK;
1220 }
1221 
1222 static BraseroBurnResult
brasero_burn_ask_for_joliet(BraseroBurn * burn)1223 brasero_burn_ask_for_joliet (BraseroBurn *burn)
1224 {
1225 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1226 	BraseroBurnResult result;
1227 	GSList *tracks;
1228 	GSList *iter;
1229 
1230 	result = brasero_burn_emit_signal (burn, ASK_DISABLE_JOLIET_SIGNAL, BRASERO_BURN_CANCEL);
1231 	if (result != BRASERO_BURN_OK)
1232 		return result;
1233 
1234 	tracks = brasero_burn_session_get_tracks (priv->session);
1235 	for (iter = tracks; iter; iter = iter->next) {
1236 		BraseroTrack *track;
1237 
1238 		track = iter->data;
1239 		brasero_track_data_rm_fs (BRASERO_TRACK_DATA (track), BRASERO_IMAGE_FS_JOLIET);
1240 	}
1241 
1242 	return BRASERO_BURN_OK;
1243 }
1244 
1245 static BraseroBurnResult
brasero_burn_ask_for_location(BraseroBurn * burn,GError * received_error,gboolean is_temporary,GError ** error)1246 brasero_burn_ask_for_location (BraseroBurn *burn,
1247 			       GError *received_error,
1248 			       gboolean is_temporary,
1249 			       GError **error)
1250 {
1251 	GValue instance_and_params [3];
1252 	GValue return_value;
1253 
1254 	instance_and_params [0].g_type = 0;
1255 	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (burn));
1256 	g_value_set_instance (instance_and_params, burn);
1257 
1258 	instance_and_params [1].g_type = 0;
1259 	g_value_init (instance_and_params + 1, G_TYPE_POINTER);
1260 	g_value_set_pointer (instance_and_params + 1, received_error);
1261 
1262 	instance_and_params [2].g_type = 0;
1263 	g_value_init (instance_and_params + 2, G_TYPE_BOOLEAN);
1264 	g_value_set_boolean (instance_and_params + 2, is_temporary);
1265 
1266 	return_value.g_type = 0;
1267 	g_value_init (&return_value, G_TYPE_INT);
1268 	g_value_set_int (&return_value, BRASERO_BURN_CANCEL);
1269 
1270 	g_signal_emitv (instance_and_params,
1271 			brasero_burn_signals [LOCATION_REQUEST_SIGNAL],
1272 			0,
1273 			&return_value);
1274 
1275 	g_value_unset (instance_and_params);
1276 	g_value_unset (instance_and_params + 1);
1277 
1278 	return g_value_get_int (&return_value);
1279 }
1280 
1281 static BraseroBurnResult
brasero_burn_run_eraser(BraseroBurn * burn,GError ** error)1282 brasero_burn_run_eraser (BraseroBurn *burn, GError **error)
1283 {
1284 	BraseroDrive *drive;
1285 	BraseroMedium *medium;
1286 	BraseroBurnPrivate *priv;
1287 	BraseroBurnResult result;
1288 
1289 	priv = BRASERO_BURN_PRIVATE (burn);
1290 
1291 	drive = brasero_burn_session_get_burner (priv->session);
1292 	medium = brasero_drive_get_medium (drive);
1293 
1294 	result = brasero_burn_unmount (burn, medium, error);
1295 	if (result != BRASERO_BURN_OK)
1296 		return result;
1297 
1298 	result = brasero_task_run (priv->task, error);
1299 	if (result != BRASERO_BURN_OK)
1300 		return result;
1301 
1302 	/* Reprobe. It can happen (like with dvd+rw-format) that
1303 	 * for the whole OS, the disc doesn't exist during the
1304 	 * formatting. Wait for the disc to reappear */
1305 	/*  Likewise, this is necessary when we do a
1306 	 * simulation before blanking since it blanked the disc
1307 	 * and then to create all tasks necessary for the real
1308 	 * burning operation, we'll need the real medium status
1309 	 * not to include a blanking job again. */
1310 	return brasero_burn_reprobe (burn);
1311 }
1312 
1313 static BraseroBurnResult
brasero_burn_run_imager(BraseroBurn * burn,gboolean fake,GError ** error)1314 brasero_burn_run_imager (BraseroBurn *burn,
1315 			 gboolean fake,
1316 			 GError **error)
1317 {
1318 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1319 	BraseroBurnError error_code;
1320 	BraseroBurnResult result;
1321 	GError *ret_error = NULL;
1322 	BraseroMedium *medium;
1323 	BraseroDrive *src;
1324 
1325 	src = brasero_burn_session_get_src_drive (priv->session);
1326 
1327 start:
1328 
1329 	medium = brasero_drive_get_medium (src);
1330 	if (medium) {
1331 		/* This is just in case */
1332 		result = brasero_burn_unmount (burn, medium, error);
1333 		if (result != BRASERO_BURN_OK)
1334 			return result;
1335 	}
1336 
1337 	/* If it succeeds then the new track(s) will be at the top of
1338 	 * session tracks stack and therefore usable by the recorder.
1339 	 * NOTE: it's up to the job to push the current tracks. */
1340 	if (fake)
1341 		result = brasero_task_check (priv->task, &ret_error);
1342 	else
1343 		result = brasero_task_run (priv->task, &ret_error);
1344 
1345 	if (result == BRASERO_BURN_OK) {
1346 		if (!fake) {
1347 			g_signal_emit (burn,
1348 				       brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
1349 				       0,
1350 				       1.0,
1351 				       1.0,
1352 				       -1L);
1353 		}
1354 		return BRASERO_BURN_OK;
1355 	}
1356 
1357 	if (result != BRASERO_BURN_ERR) {
1358 		if (error && ret_error)
1359 			g_propagate_error (error, ret_error);
1360 
1361 		return result;
1362 	}
1363 
1364 	if (!ret_error)
1365 		return result;
1366 
1367 	if (brasero_burn_session_is_dest_file (priv->session)) {
1368 		gchar *image = NULL;
1369 		gchar *toc = NULL;
1370 
1371 		/* If it was an image that was output, remove it. If that was
1372 		 * a temporary image, it will be removed by BraseroBurnSession
1373 		 * object. But if it was a final image, it would be left and
1374 		 * would clutter the disk, wasting space. */
1375 		brasero_burn_session_get_output (priv->session,
1376 						 &image,
1377 						 &toc);
1378 		if (image)
1379 			g_remove (image);
1380 		if (toc)
1381 			g_remove (toc);
1382 	}
1383 
1384 	/* See if we can recover from the error */
1385 	error_code = ret_error->code;
1386 	if (error_code == BRASERO_BURN_ERROR_IMAGE_JOLIET) {
1387 		/* clean the error anyway since at worst the user will cancel */
1388 		g_error_free (ret_error);
1389 		ret_error = NULL;
1390 
1391 		/* some files are not conforming to Joliet standard see
1392 		 * if the user wants to carry on with a non joliet disc */
1393 		result = brasero_burn_ask_for_joliet (burn);
1394 		if (result != BRASERO_BURN_OK)
1395 			return result;
1396 
1397 		goto start;
1398 	}
1399 	else if (error_code == BRASERO_BURN_ERROR_MEDIUM_NO_DATA) {
1400 		/* clean the error anyway since at worst the user will cancel */
1401 		g_error_free (ret_error);
1402 		ret_error = NULL;
1403 
1404 		/* The media hasn't data on it: ask for a new one. */
1405 		result = brasero_burn_reload_src_media (burn,
1406 							error_code,
1407 							error);
1408 		if (result != BRASERO_BURN_OK)
1409 			return result;
1410 
1411 		goto start;
1412 	}
1413 	else if (error_code == BRASERO_BURN_ERROR_DISK_SPACE
1414 	     ||  error_code == BRASERO_BURN_ERROR_PERMISSION
1415 	     ||  error_code == BRASERO_BURN_ERROR_TMP_DIRECTORY) {
1416 		gboolean is_temp;
1417 
1418 		/* That's an imager (outputs an image to the disc) so that means
1419 		 * that here the problem comes from the hard drive being too
1420 		 * small or we don't have the right permission. */
1421 
1422 		/* NOTE: Image file creation is always the last to take place
1423 		 * when it's not temporary. Another job should not take place
1424 		 * afterwards */
1425 		if (!brasero_burn_session_is_dest_file (priv->session))
1426 			is_temp = TRUE;
1427 		else
1428 			is_temp = FALSE;
1429 
1430 		result = brasero_burn_ask_for_location (burn,
1431 							ret_error,
1432 							is_temp,
1433 							error);
1434 
1435 		/* clean the error anyway since at worst the user will cancel */
1436 		g_error_free (ret_error);
1437 		ret_error = NULL;
1438 
1439 		if (result != BRASERO_BURN_OK)
1440 			return result;
1441 
1442 		goto start;
1443 	}
1444 
1445 	/* If we reached this point that means the error was not recoverable.
1446 	 * Propagate the error. */
1447 	if (error && ret_error)
1448 		g_propagate_error (error, ret_error);
1449 
1450 	return BRASERO_BURN_ERR;
1451 }
1452 
1453 static BraseroBurnResult
brasero_burn_can_use_drive_exclusively(BraseroBurn * burn,BraseroDrive * drive)1454 brasero_burn_can_use_drive_exclusively (BraseroBurn *burn,
1455 					BraseroDrive *drive)
1456 {
1457 	BraseroBurnResult result;
1458 
1459 	if (!drive)
1460 		return BRASERO_BURN_OK;
1461 
1462 	while (!brasero_drive_can_use_exclusively (drive)) {
1463 		BRASERO_BURN_LOG ("Device busy, retrying in 250 ms");
1464 		result = brasero_burn_sleep (burn, 250);
1465 		if (result != BRASERO_BURN_OK)
1466 			return result;
1467 	}
1468 
1469 	return BRASERO_BURN_OK;
1470 }
1471 
1472 static BraseroBurnResult
brasero_burn_run_recorder(BraseroBurn * burn,GError ** error)1473 brasero_burn_run_recorder (BraseroBurn *burn, GError **error)
1474 {
1475 	gint error_code;
1476 	BraseroDrive *src;
1477 	BraseroDrive *burner;
1478 	GError *ret_error = NULL;
1479 	BraseroBurnResult result;
1480 	BraseroMedium *src_medium;
1481 	BraseroMedium *burnt_medium;
1482 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1483 
1484 	src = brasero_burn_session_get_src_drive (priv->session);
1485 	src_medium = brasero_drive_get_medium (src);
1486 
1487 	burner = brasero_burn_session_get_burner (priv->session);
1488 	burnt_medium = brasero_drive_get_medium (burner);
1489 
1490 start:
1491 
1492 	/* this is just in case */
1493 	if (BRASERO_BURN_SESSION_NO_TMP_FILE (priv->session)) {
1494 		result = brasero_burn_unmount (burn, src_medium, error);
1495 		if (result != BRASERO_BURN_OK)
1496 			return result;
1497 	}
1498 
1499 	result = brasero_burn_unmount (burn, burnt_medium, error);
1500 	if (result != BRASERO_BURN_OK)
1501 		return result;
1502 
1503 	/* before we start let's see if that drive can be used exclusively.
1504 	 * Of course, it's not really safe since a process could take a lock
1505 	 * just after us but at least it'll give some time to HAL and friends
1506 	 * to finish what they're doing.
1507 	 * This was done because more than often backends wouldn't be able to
1508 	 * get a lock on a medium after a simulation. */
1509 	result = brasero_burn_can_use_drive_exclusively (burn, burner);
1510 	if (result != BRASERO_BURN_OK)
1511 		return result;
1512 
1513 	/* actual running of task */
1514 	result = brasero_task_run (priv->task, &ret_error);
1515 
1516 	/* let's see the results */
1517 	if (result == BRASERO_BURN_OK) {
1518 		g_signal_emit (burn,
1519 			       brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
1520 			       0,
1521 			       1.0,
1522 			       1.0,
1523 			       -1L);
1524 		return BRASERO_BURN_OK;
1525 	}
1526 
1527 	if (result != BRASERO_BURN_ERR
1528 	|| !ret_error
1529 	||  ret_error->domain != BRASERO_BURN_ERROR) {
1530 		if (ret_error)
1531 			g_propagate_error (error, ret_error);
1532 
1533 		return result;
1534 	}
1535 
1536 	/* see if error is recoverable */
1537 	error_code = ret_error->code;
1538 	if (error_code == BRASERO_BURN_ERROR_IMAGE_JOLIET) {
1539 		/* NOTE: this error can only come from the source when
1540 		 * burning on the fly => no need to recreate an imager */
1541 
1542 		/* some files are not conforming to Joliet standard see
1543 		 * if the user wants to carry on with a non joliet disc */
1544 		result = brasero_burn_ask_for_joliet (burn);
1545 		if (result != BRASERO_BURN_OK) {
1546 			if (ret_error)
1547 				g_propagate_error (error, ret_error);
1548 
1549 			return result;
1550 		}
1551 
1552 		g_error_free (ret_error);
1553 		ret_error = NULL;
1554 		goto start;
1555 	}
1556 	else if (error_code == BRASERO_BURN_ERROR_MEDIUM_NEED_RELOADING) {
1557 		/* NOTE: this error can only come from the source when
1558 		 * burning on the fly => no need to recreate an imager */
1559 
1560 		/* The source media (when copying on the fly) is empty
1561 		 * so ask the user to reload another media with data */
1562 		g_error_free (ret_error);
1563 		ret_error = NULL;
1564 
1565 		result = brasero_burn_reload_src_media (burn,
1566 							error_code,
1567 							error);
1568 		if (result != BRASERO_BURN_OK)
1569 			return result;
1570 
1571 		goto start;
1572 	}
1573 	else if (error_code == BRASERO_BURN_ERROR_SLOW_DMA) {
1574 		guint64 rate;
1575 
1576 		/* The whole system has just made a great effort. Sometimes it
1577 		 * helps to let it rest for a sec or two => that's what we do
1578 		 * before retrying. (That's why usually cdrecord waits a little
1579 		 * bit but sometimes it doesn't). Another solution would be to
1580 		 * lower the speed a little (we could do both) */
1581 		g_error_free (ret_error);
1582 		ret_error = NULL;
1583 
1584 		result = brasero_burn_sleep (burn, 2000);
1585 		if (result != BRASERO_BURN_OK)
1586 			return result;
1587 
1588 		/* set speed at 8x max and even less if speed  */
1589 		rate = brasero_burn_session_get_rate (priv->session);
1590 		if (rate <= BRASERO_SPEED_TO_RATE_CD (8)) {
1591 			rate = rate * 3 / 4;
1592 			if (rate < CD_RATE)
1593 				rate = CD_RATE;
1594 		}
1595 		else
1596 			rate = BRASERO_SPEED_TO_RATE_CD (8);
1597 
1598 		brasero_burn_session_set_rate (priv->session, rate);
1599 		goto start;
1600 	}
1601 	else if (error_code == BRASERO_BURN_ERROR_MEDIUM_SPACE) {
1602 		/* NOTE: this error can only come from the dest drive */
1603 
1604 		/* clean error and indicates this is a recoverable error */
1605 		g_error_free (ret_error);
1606 		ret_error = NULL;
1607 
1608 		/* the space left on the media is insufficient (that's strange
1609 		 * since we checked):
1610 		 * the disc is either not rewritable or is too small anyway then
1611 		 * we ask for a new media.
1612 		 * It raises the problem of session merging. Indeed at this
1613 		 * point an image can have been generated that was specifically
1614 		 * generated for the inserted media. So if we have MERGE/APPEND
1615 		 * that should fail.
1616 		 */
1617 		if (brasero_burn_session_get_flags (priv->session) &
1618 		   (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE)) {
1619 			g_set_error (error,
1620 				     BRASERO_BURN_ERROR,
1621 				     BRASERO_BURN_ERROR_MEDIUM_SPACE,
1622 				     "%s. %s",
1623 				     _("Merging data is impossible with this disc"),
1624 				     _("Not enough space available on the disc"));
1625 			return BRASERO_BURN_ERR;
1626 		}
1627 
1628 		/* ask for the destination media reload */
1629 		result = brasero_burn_reload_dest_media (burn,
1630 							 error_code,
1631 							 error);
1632 		if (result != BRASERO_BURN_OK)
1633 			return result;
1634 
1635 		goto start;
1636 	}
1637 	else if (error_code >= BRASERO_BURN_ERROR_MEDIUM_NONE
1638 	     &&  error_code <=  BRASERO_BURN_ERROR_MEDIUM_NEED_RELOADING) {
1639 		/* NOTE: these errors can only come from the dest drive */
1640 
1641 		/* clean error and indicates this is a recoverable error */
1642 		g_error_free (ret_error);
1643 		ret_error = NULL;
1644 
1645 		/* ask for the destination media reload */
1646 		result = brasero_burn_reload_dest_media (burn,
1647 							 error_code,
1648 							 error);
1649 
1650 		if (result != BRASERO_BURN_OK)
1651 			return result;
1652 
1653 		goto start;
1654 	}
1655 
1656 	if (ret_error)
1657 		g_propagate_error (error, ret_error);
1658 
1659 	return BRASERO_BURN_ERR;
1660 }
1661 
1662 static BraseroBurnResult
brasero_burn_install_missing(BraseroPluginErrorType error,const gchar * details,gpointer user_data)1663 brasero_burn_install_missing (BraseroPluginErrorType error,
1664 			      const gchar *details,
1665 			      gpointer user_data)
1666 {
1667 	GValue instance_and_params [3];
1668 	GValue return_value;
1669 
1670 	instance_and_params [0].g_type = 0;
1671 	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (user_data));
1672 	g_value_set_instance (instance_and_params, user_data);
1673 
1674 	instance_and_params [1].g_type = 0;
1675 	g_value_init (instance_and_params + 1, G_TYPE_INT);
1676 	g_value_set_int (instance_and_params + 1, error);
1677 
1678 	instance_and_params [2].g_type = 0;
1679 	g_value_init (instance_and_params + 2, G_TYPE_STRING);
1680 	g_value_set_string (instance_and_params + 2, details);
1681 
1682 	return_value.g_type = 0;
1683 	g_value_init (&return_value, G_TYPE_INT);
1684 	g_value_set_int (&return_value, BRASERO_BURN_ERROR);
1685 
1686 	g_signal_emitv (instance_and_params,
1687 			brasero_burn_signals [INSTALL_MISSING_SIGNAL],
1688 			0,
1689 			&return_value);
1690 
1691 	g_value_unset (instance_and_params);
1692 
1693 	return g_value_get_int (&return_value);
1694 }
1695 
1696 static BraseroBurnResult
brasero_burn_list_missing(BraseroPluginErrorType type,const gchar * detail,gpointer user_data)1697 brasero_burn_list_missing (BraseroPluginErrorType type,
1698 			   const gchar *detail,
1699 			   gpointer user_data)
1700 {
1701 	GString *string = user_data;
1702 
1703 	if (type == BRASERO_PLUGIN_ERROR_MISSING_APP ||
1704 	    type == BRASERO_PLUGIN_ERROR_SYMBOLIC_LINK_APP ||
1705 	    type == BRASERO_PLUGIN_ERROR_WRONG_APP_VERSION) {
1706 		g_string_append_c (string, '\n');
1707 		/* Translators: %s is the name of a missing application */
1708 		g_string_append_printf (string, _("%s (application)"), detail);
1709 	}
1710 	else if (type == BRASERO_PLUGIN_ERROR_MISSING_LIBRARY ||
1711 	         type == BRASERO_PLUGIN_ERROR_LIBRARY_VERSION) {
1712 		g_string_append_c (string, '\n');
1713 		/* Translators: %s is the name of a missing library */
1714 		g_string_append_printf (string, _("%s (library)"), detail);
1715 	}
1716 	else if (type == BRASERO_PLUGIN_ERROR_MISSING_GSTREAMER_PLUGIN) {
1717 		g_string_append_c (string, '\n');
1718 		/* Translators: %s is the name of a missing GStreamer plugin */
1719 		g_string_append_printf (string, _("%s (GStreamer plugin)"), detail);
1720 	}
1721 
1722 	return BRASERO_BURN_OK;
1723 }
1724 
1725 static BraseroBurnResult
brasero_burn_check_session_consistency(BraseroBurn * burn,BraseroTrackType * output,GError ** error)1726 brasero_burn_check_session_consistency (BraseroBurn *burn,
1727                                         BraseroTrackType *output,
1728 					GError **error)
1729 {
1730 	BraseroBurnFlag flag;
1731 	BraseroBurnFlag flags;
1732 	BraseroBurnFlag retval;
1733 	BraseroBurnResult result;
1734 	BraseroTrackType *input = NULL;
1735 	BraseroBurnFlag supported = BRASERO_BURN_FLAG_NONE;
1736 	BraseroBurnFlag compulsory = BRASERO_BURN_FLAG_NONE;
1737 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1738 
1739 	BRASERO_BURN_DEBUG (burn, "Checking session consistency");
1740 
1741 	/* make sure there is a track in the session. */
1742 	input = brasero_track_type_new ();
1743 	brasero_burn_session_get_input_type (priv->session, input);
1744 
1745 	if (brasero_track_type_is_empty (input)) {
1746 		brasero_track_type_free (input);
1747 
1748 		BRASERO_BURN_DEBUG (burn, "No track set");
1749 		g_set_error (error,
1750 			     BRASERO_BURN_ERROR,
1751 			     BRASERO_BURN_ERROR_GENERAL,
1752 			     "%s", _("There is no track to burn"));
1753 		return BRASERO_BURN_ERR;
1754 	}
1755 
1756 	/* No need to check if a burner was set as this
1757 	 * is done when locking. */
1758 
1759 	/* save then wipe out flags from session to check them one by one */
1760 	flags = brasero_burn_session_get_flags (priv->session);
1761 	brasero_burn_session_set_flags (BRASERO_BURN_SESSION (priv->session), BRASERO_BURN_FLAG_NONE);
1762 
1763 	if (!output || brasero_track_type_get_has_medium (output))
1764 		result = brasero_burn_session_get_burn_flags (priv->session,
1765 							      &supported,
1766 							      &compulsory);
1767 	else
1768 		result = brasero_caps_session_get_image_flags (input,
1769 		                                              output,
1770 		                                              &supported,
1771 		                                              &compulsory);
1772 
1773 	if (result != BRASERO_BURN_OK) {
1774 		brasero_track_type_free (input);
1775 		return result;
1776 	}
1777 
1778 	for (flag = 1; flag < BRASERO_BURN_FLAG_LAST; flag <<= 1) {
1779 		/* see if this flag was originally set */
1780 		if (!(flags & flag))
1781 			continue;
1782 
1783 		/* Check each flag before re-adding it. Emit warnings to user
1784 		 * to know if he wants to carry on for some flags when they are
1785 		 * not supported; namely DUMMY. Other flags trigger an error.
1786 		 * No need for BURNPROOF since that usually means it is just the
1787 		 * media type that doesn't need it. */
1788 		if (supported & flag) {
1789 			brasero_burn_session_add_flag (priv->session, flag);
1790 
1791 			if (!output || brasero_track_type_get_has_medium (output))
1792 				result = brasero_burn_session_get_burn_flags (priv->session,
1793 									      &supported,
1794 									      &compulsory);
1795 			else
1796 				result = brasero_caps_session_get_image_flags (input,
1797 									      output,
1798 									      &supported,
1799 									      &compulsory);
1800 		}
1801 		else {
1802 			BRASERO_BURN_LOG_FLAGS (flag, "Flag set but not supported:");
1803 
1804 			if (flag & BRASERO_BURN_FLAG_DUMMY) {
1805 				/* This is simply a warning that it's not possible */
1806 
1807 			}
1808 			else if (flag & BRASERO_BURN_FLAG_MERGE) {
1809 				brasero_track_type_free (input);
1810 
1811 				/* we pay attention to one flag in particular
1812 				 * (MERGE) if it was set then it must be
1813 				 * supported. Otherwise error out. */
1814 				g_set_error (error,
1815 					     BRASERO_BURN_ERROR,
1816 					     BRASERO_BURN_ERROR_GENERAL,
1817 					     "%s", _("Merging data is impossible with this disc"));
1818 				return BRASERO_BURN_ERR;
1819 			}
1820 			/* No need to tell the user burnproof is not supported
1821 			 * as these drives handle errors differently which makes
1822 			 * burnproof useless for them. */
1823 		}
1824 	}
1825 	brasero_track_type_free (input);
1826 
1827 	retval = brasero_burn_session_get_flags (priv->session);
1828 	if (retval != flags)
1829 		BRASERO_BURN_LOG_FLAGS (retval, "Some flags were not supported. Corrected to");
1830 
1831 	if (retval != (retval | compulsory)) {
1832 		retval |= compulsory;
1833 		BRASERO_BURN_LOG_FLAGS (retval, "Some compulsory flags were forgotten. Corrected to");
1834 	}
1835 
1836 	brasero_burn_session_set_flags (priv->session, retval);
1837 	BRASERO_BURN_LOG_FLAGS (retval, "Flags after checking =");
1838 
1839 	/* Check missing applications/GStreamer plugins.
1840 	 * This is the best place. */
1841 	brasero_burn_session_set_strict_support (BRASERO_BURN_SESSION (priv->session), TRUE);
1842 	result = brasero_burn_session_can_burn (priv->session, FALSE);
1843 	brasero_burn_session_set_strict_support (BRASERO_BURN_SESSION (priv->session), FALSE);
1844 
1845 	if (result == BRASERO_BURN_OK)
1846 		return result;
1847 
1848 	result = brasero_burn_session_can_burn (priv->session, FALSE);
1849 	if (result != BRASERO_BURN_OK)
1850 		return result;
1851 
1852 	result = brasero_session_foreach_plugin_error (priv->session,
1853 	                                               brasero_burn_install_missing,
1854 	                                               burn);
1855 	if (result != BRASERO_BURN_OK) {
1856 		if (result != BRASERO_BURN_CANCEL) {
1857 			GString *string;
1858 
1859 			string = g_string_new (_("Please install the following required applications and libraries manually and try again:"));
1860 			brasero_session_foreach_plugin_error (priv->session,
1861 			                                      brasero_burn_list_missing,
1862 	        			                      string);
1863 			g_set_error (error,
1864 				     BRASERO_BURN_ERROR,
1865 				     BRASERO_BURN_ERROR_MISSING_APP_AND_PLUGIN,
1866 				     "%s", string->str);
1867 
1868 			g_string_free (string, TRUE);
1869 		}
1870 
1871 		return BRASERO_BURN_ERR;
1872 	}
1873 
1874 	return BRASERO_BURN_OK;
1875 }
1876 
1877 static BraseroBurnResult
brasero_burn_check_data_loss(BraseroBurn * burn,BraseroTrackType * temp_output,GError ** error)1878 brasero_burn_check_data_loss (BraseroBurn *burn,
1879                               BraseroTrackType *temp_output,
1880                               GError **error)
1881 {
1882 	BraseroMedia media;
1883 	BraseroBurnFlag flags;
1884 	BraseroTrackType *input;
1885 	BraseroBurnResult result;
1886 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
1887 
1888 	if (!temp_output) {
1889 		BraseroTrackType *output;
1890 
1891 		output = brasero_track_type_new ();
1892 		brasero_burn_session_get_output_type (priv->session, output);
1893 		if (!brasero_track_type_get_has_medium (output)) {
1894 			brasero_track_type_free (output);
1895 			return BRASERO_BURN_OK;
1896 		}
1897 
1898 		media = brasero_track_type_get_medium_type (output);
1899 		brasero_track_type_free (output);
1900 	}
1901 	else {
1902 		if (!brasero_track_type_get_has_medium (temp_output))
1903 			return BRASERO_BURN_OK;
1904 
1905 		media = brasero_track_type_get_medium_type (temp_output);
1906 	}
1907 
1908 	input = brasero_track_type_new ();
1909 	brasero_burn_session_get_input_type (priv->session, input);
1910 	flags = brasero_burn_session_get_flags (priv->session);
1911 
1912 	if (media & (BRASERO_MEDIUM_HAS_DATA|BRASERO_MEDIUM_HAS_AUDIO)) {
1913 		if (flags & BRASERO_BURN_FLAG_BLANK_BEFORE_WRITE) {
1914 			/* There is an error if APPEND was set since this disc is not
1915 			 * supported without a prior blanking. */
1916 
1917 			/* we warn the user is going to lose data even if in the case of
1918 			 * DVD+/-RW we don't really blank the disc we rather overwrite */
1919 			result = brasero_burn_emit_signal (burn,
1920 							   WARN_DATA_LOSS_SIGNAL,
1921 							   BRASERO_BURN_CANCEL);
1922 			if (result == BRASERO_BURN_NEED_RELOAD)
1923 				goto reload;
1924 
1925 			if (result != BRASERO_BURN_OK) {
1926 				brasero_track_type_free (input);
1927 				return result;
1928 			}
1929 		}
1930 		else {
1931 			/* A few special warnings for the discs with data/audio on them
1932 			 * that don't need prior blanking or can't be blanked */
1933 			if ((media & BRASERO_MEDIUM_CD)
1934 			&&  brasero_track_type_get_has_stream (input)
1935 			&& !BRASERO_STREAM_FORMAT_HAS_VIDEO (brasero_track_type_get_stream_format (input))) {
1936 				/* We'd rather blank and rewrite a disc rather than
1937 				 * append audio to appendable disc. That's because audio
1938 				 * tracks have little chance to be readable by common CD
1939 				 * player as last tracks */
1940 				result = brasero_burn_emit_signal (burn,
1941 								   WARN_AUDIO_TO_APPENDABLE_SIGNAL,
1942 								   BRASERO_BURN_CANCEL);
1943 				if (result == BRASERO_BURN_NEED_RELOAD)
1944 					goto reload;
1945 
1946 				if (result != BRASERO_BURN_OK) {
1947 					brasero_track_type_free (input);
1948 					return result;
1949 				}
1950 			}
1951 
1952 			/* NOTE: if input is AUDIO we don't care since the OS
1953 			 * will load the last session of DATA anyway */
1954 			if ((media & BRASERO_MEDIUM_HAS_DATA)
1955 			&&   brasero_track_type_get_has_data (input)
1956 			&& !(flags & BRASERO_BURN_FLAG_MERGE)) {
1957 				/* warn the users that their previous data
1958 				 * session (s) will not be mounted by default by
1959 				 * the OS and that it'll be invisible */
1960 				result = brasero_burn_emit_signal (burn,
1961 								   WARN_PREVIOUS_SESSION_LOSS_SIGNAL,
1962 								   BRASERO_BURN_CANCEL);
1963 
1964 				if (result == BRASERO_BURN_RETRY) {
1965 					/* Wipe out the current flags,
1966 					 * Add a new one
1967 					 * Recheck the result */
1968 					brasero_burn_session_pop_settings (priv->session);
1969 					brasero_burn_session_push_settings (priv->session);
1970 					brasero_burn_session_add_flag (priv->session, BRASERO_BURN_FLAG_MERGE);
1971 					result = brasero_burn_check_session_consistency (burn, NULL, error);
1972 					if (result != BRASERO_BURN_OK)
1973 						return result;
1974 				}
1975 
1976 				if (result == BRASERO_BURN_NEED_RELOAD)
1977 					goto reload;
1978 
1979 				if (result != BRASERO_BURN_OK) {
1980 					brasero_track_type_free (input);
1981 					return result;
1982 				}
1983 			}
1984 		}
1985 	}
1986 
1987 	if (media & BRASERO_MEDIUM_REWRITABLE) {
1988 		/* emits a warning for the user if it's a rewritable
1989 		 * disc and he wants to write only audio tracks on it */
1990 
1991 		/* NOTE: no need to error out here since the only thing
1992 		 * we are interested in is if it is AUDIO or not or if
1993 		 * the disc we are copying has audio tracks only or not */
1994 		if (brasero_track_type_get_has_stream (input)
1995 		&& !BRASERO_STREAM_FORMAT_HAS_VIDEO (brasero_track_type_get_stream_format (input))) {
1996 			result = brasero_burn_emit_signal (burn,
1997 			                                   WARN_REWRITABLE_SIGNAL,
1998 			                                   BRASERO_BURN_CANCEL);
1999 
2000 			if (result == BRASERO_BURN_NEED_RELOAD)
2001 				goto reload;
2002 
2003 			if (result != BRASERO_BURN_OK) {
2004 				brasero_track_type_free (input);
2005 				return result;
2006 			}
2007 		}
2008 
2009 		if (brasero_track_type_get_has_medium (input)
2010 		&& (brasero_track_type_get_medium_type (input) & BRASERO_MEDIUM_HAS_AUDIO)) {
2011 			result = brasero_burn_emit_signal (burn,
2012 			                                   WARN_REWRITABLE_SIGNAL,
2013 			                                   BRASERO_BURN_CANCEL);
2014 
2015 			if (result == BRASERO_BURN_NEED_RELOAD)
2016 				goto reload;
2017 
2018 			if (result != BRASERO_BURN_OK) {
2019 				brasero_track_type_free (input);
2020 				return result;
2021 			}
2022 		}
2023 	}
2024 
2025 	brasero_track_type_free (input);
2026 
2027 	return BRASERO_BURN_OK;
2028 
2029 reload:
2030 
2031 	brasero_track_type_free (input);
2032 
2033 	result = brasero_burn_reload_dest_media (burn, BRASERO_BURN_ERROR_NONE, error);
2034 	if (result != BRASERO_BURN_OK)
2035 		return result;
2036 
2037 	return BRASERO_BURN_RETRY;
2038 }
2039 
2040 /* FIXME: at the moment we don't allow for mixed CD type */
2041 static BraseroBurnResult
brasero_burn_run_tasks(BraseroBurn * burn,gboolean erase_allowed,BraseroTrackType * temp_output,gboolean * dummy_session,GError ** error)2042 brasero_burn_run_tasks (BraseroBurn *burn,
2043 			gboolean erase_allowed,
2044                         BraseroTrackType *temp_output,
2045                         gboolean *dummy_session,
2046 			GError **error)
2047 {
2048 	BraseroBurnResult result;
2049 	GSList *tasks, *next, *iter;
2050 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (burn);
2051 
2052 	/* push the session settings to keep the original session untainted */
2053 	brasero_burn_session_push_settings (priv->session);
2054 
2055 	/* check flags consistency */
2056 	result = brasero_burn_check_session_consistency (burn, temp_output, error);
2057 	if (result != BRASERO_BURN_OK) {
2058 		brasero_burn_session_pop_settings (priv->session);
2059 		return result;
2060 	}
2061 
2062 	/* performed some additional tests that can only be performed at this
2063 	 * point. They are mere warnings. */
2064 	result = brasero_burn_check_data_loss (burn, temp_output, error);
2065 	if (result != BRASERO_BURN_OK) {
2066 		brasero_burn_session_pop_settings (priv->session);
2067 		return result;
2068 	}
2069 
2070 	tasks = brasero_burn_caps_new_task (priv->caps,
2071 					    priv->session,
2072 	                                    temp_output,
2073 					    error);
2074 	if (!tasks) {
2075 		brasero_burn_session_pop_settings (priv->session);
2076 		return BRASERO_BURN_NOT_SUPPORTED;
2077 	}
2078 
2079 	priv->tasks_done = 0;
2080 	priv->task_nb = g_slist_length (tasks);
2081 	BRASERO_BURN_LOG ("%i tasks to perform", priv->task_nb);
2082 
2083 	/* run all imaging tasks first */
2084 	for (iter = tasks; iter; iter = next) {
2085 		goffset len = 0;
2086 		BraseroDrive *drive;
2087 		BraseroMedium *medium;
2088 		BraseroTaskAction action;
2089 
2090 		next = iter->next;
2091 		priv->task = iter->data;
2092 		tasks = g_slist_remove (tasks, priv->task);
2093 
2094 		g_signal_connect (priv->task,
2095 				  "progress-changed",
2096 				  G_CALLBACK (brasero_burn_progress_changed),
2097 				  burn);
2098 		g_signal_connect (priv->task,
2099 				  "action-changed",
2100 				  G_CALLBACK (brasero_burn_action_changed),
2101 				  burn);
2102 
2103 		/* see what type of task it is. It could be a blank/erase one. */
2104 		/* FIXME!
2105 		 * If so then that's time to test the size of the image against
2106 		 * the size of the disc since erasing/formatting is always left
2107 		 * for the end, just before burning. We would not like to
2108 		 * blank a disc and tell the user right after that the size of
2109 		 * the disc is not enough. */
2110 		action = brasero_task_ctx_get_action (BRASERO_TASK_CTX (priv->task));
2111 		if (action == BRASERO_TASK_ACTION_ERASE) {
2112 			BraseroTrackType *type;
2113 
2114 			/* FIXME: how could it be possible for a drive to test
2115 			 * with a CLOSED CDRW for example. Maybe we should
2116 			 * format/blank anyway. */
2117 
2118 			/* This is to avoid blanking a medium without knowing
2119 			 * if the data will fit on it. At this point we do know
2120 			 * what the size of the data is going to be. */
2121 			type = brasero_track_type_new ();
2122 			brasero_burn_session_get_input_type (priv->session, type);
2123 			if (brasero_track_type_get_has_image (type)
2124 			||  brasero_track_type_get_has_medium (type)) {
2125 				BraseroMedium *medium;
2126 				goffset session_sec = 0;
2127 				goffset medium_sec = 0;
2128 
2129 				medium = brasero_drive_get_medium (priv->dest);
2130 				brasero_medium_get_capacity (medium,
2131 							     NULL,
2132 							     &medium_sec);
2133 
2134 				brasero_burn_session_get_size (priv->session,
2135 							       &session_sec,
2136 							       NULL);
2137 
2138 				if (session_sec > medium_sec) {
2139 					BRASERO_BURN_LOG ("Not enough space on medium %"G_GOFFSET_FORMAT"/%"G_GOFFSET_FORMAT, session_sec, medium_sec);
2140 					result = brasero_burn_reload_dest_media (burn,
2141 					                                         BRASERO_BURN_ERROR_MEDIUM_SPACE,
2142 					                                         error);
2143 					if (result == BRASERO_BURN_OK)
2144 						result = BRASERO_BURN_RETRY;
2145 
2146 					break;
2147 				}
2148 			}
2149 			brasero_track_type_free (type);
2150 
2151 			/* This is to avoid a potential problem when running a
2152 			 * dummy session first. When running dummy session the
2153 			 * media gets erased if need be. Since it is not
2154 			 * reloaded afterwards, for brasero it has still got
2155 			 * data on it when we get to the real recording. */
2156 			if (erase_allowed) {
2157 				result = brasero_burn_run_eraser (burn, error);
2158 				if (result == BRASERO_BURN_CANCEL)
2159 					return result;
2160 
2161 				/* If the erasing process did not work then do
2162 				 * not fail and cancel the entire session but
2163 				 * ask the user if he wants to insert another
2164 				 * disc instead. */
2165 				if (result != BRASERO_BURN_OK) {
2166 					BraseroBurnResult local_result;
2167 
2168 					local_result = brasero_burn_emit_signal (burn,
2169 					                                         BLANK_FAILURE_SIGNAL,
2170 					                                         BRASERO_BURN_ERR);
2171 					if (local_result == BRASERO_BURN_OK) {
2172 						local_result = brasero_burn_reload_dest_media (burn,
2173 						                                               BRASERO_BURN_ERROR_NONE,
2174 						                                               NULL);
2175 						if (local_result == BRASERO_BURN_OK)
2176 							result = BRASERO_BURN_RETRY;
2177 					}
2178 
2179 					break;
2180 				}
2181 
2182 				/* Since we blanked/formatted we need to recheck the burn
2183 				 * flags with the new medium type as some flags could have
2184 				 * been given the benefit of the double (MULTI with a CLOSED
2185 				 * CD for example). Recheck the original flags as they were
2186 				 * passed. */
2187 				/* FIXME: for some important flags we should warn the user
2188 				 * that it won't be possible */
2189 				brasero_burn_session_pop_settings (priv->session);
2190 				brasero_burn_session_push_settings (priv->session);
2191 				result = brasero_burn_check_session_consistency (burn, temp_output,error);
2192 				if (result != BRASERO_BURN_OK)
2193 					break;
2194 			}
2195 			else
2196 				result = BRASERO_BURN_OK;
2197 
2198 			g_object_unref (priv->task);
2199 			priv->task = NULL;
2200 			priv->tasks_done ++;
2201 
2202 			continue;
2203 		}
2204 
2205 		/* Init the task and set the task output size. The task should
2206 		 * then check that the disc has enough space. If the output is
2207 		 * to the hard drive it will be done afterwards when not in fake
2208 		 * mode. */
2209 		result = brasero_burn_run_imager (burn, TRUE, error);
2210 		if (result != BRASERO_BURN_OK)
2211 			break;
2212 
2213 		/* try to get the output size */
2214 		brasero_task_ctx_get_session_output_size (BRASERO_TASK_CTX (priv->task),
2215 							  &len,
2216 							  NULL);
2217 
2218 		drive = brasero_burn_session_get_burner (priv->session);
2219 		medium = brasero_drive_get_medium (drive);
2220 
2221 		if (brasero_burn_session_get_flags (priv->session) & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
2222 			priv->session_start = brasero_medium_get_next_writable_address (medium);
2223 		else
2224 			priv->session_start = 0;
2225 
2226 		priv->session_end = priv->session_start + len;
2227 
2228 		BRASERO_BURN_LOG ("Burning from %lld to %lld",
2229 				  priv->session_start,
2230 				  priv->session_end);
2231 
2232 		/* see if we reached a recording task: it's the last task */
2233 		if (!next) {
2234 			if (!brasero_burn_session_is_dest_file (priv->session)) {
2235 				*dummy_session = (brasero_burn_session_get_flags (priv->session) & BRASERO_BURN_FLAG_DUMMY);
2236 				result = brasero_burn_run_recorder (burn, error);
2237 			}
2238 			else
2239 				result = brasero_burn_run_imager (burn, FALSE, error);
2240 
2241 			if (result == BRASERO_BURN_OK)
2242 				priv->tasks_done ++;
2243 
2244 			break;
2245 		}
2246 
2247 		/* run the imager */
2248 		result = brasero_burn_run_imager (burn, FALSE, error);
2249 		if (result != BRASERO_BURN_OK)
2250 			break;
2251 
2252 		g_object_unref (priv->task);
2253 		priv->task = NULL;
2254 		priv->tasks_done ++;
2255 	}
2256 
2257 	/* restore the session settings. Keep the used flags
2258 	 * nevertheless to make sure we actually use the flags that were
2259 	 * set after checking for session consistency. */
2260 	brasero_burn_session_pop_settings (priv->session);
2261 
2262 	if (priv->task) {
2263 		g_object_unref (priv->task);
2264 		priv->task = NULL;
2265 	}
2266 
2267 	g_slist_foreach (tasks, (GFunc) g_object_unref, NULL);
2268 	g_slist_free (tasks);
2269 
2270 	return result;
2271 }
2272 
2273 static BraseroBurnResult
brasero_burn_check_real(BraseroBurn * self,BraseroTrack * track,GError ** error)2274 brasero_burn_check_real (BraseroBurn *self,
2275 			 BraseroTrack *track,
2276 			 GError **error)
2277 {
2278 	BraseroBurnResult result;
2279 	BraseroBurnPrivate *priv;
2280 
2281 	priv = BRASERO_BURN_PRIVATE (self);
2282 
2283 	BRASERO_BURN_LOG ("Starting to check track integrity");
2284 
2285 	/* get the task and run it skip it otherwise */
2286 	priv->task = brasero_burn_caps_new_checksuming_task (priv->caps,
2287 							     priv->session,
2288 							     NULL);
2289 	if (priv->task) {
2290 		priv->task_nb = 1;
2291 		priv->tasks_done = 0;
2292 		g_signal_connect (priv->task,
2293 				  "progress-changed",
2294 				  G_CALLBACK (brasero_burn_progress_changed),
2295 				  self);
2296 		g_signal_connect (priv->task,
2297 				  "action-changed",
2298 				  G_CALLBACK (brasero_burn_action_changed),
2299 				  self);
2300 
2301 
2302 		/* make sure one last time it is not mounted IF and only IF the
2303 		 * checksum type is NOT FILE_MD5 */
2304 		/* it seems to work without unmounting ... */
2305 		/* if (medium
2306 		 * &&  brasero_volume_is_mounted (BRASERO_VOLUME (medium))
2307 		 * && !brasero_volume_umount (BRASERO_VOLUME (medium), TRUE, NULL)) {
2308 		 *	g_set_error (error,
2309 		 *		     BRASERO_BURN_ERROR,
2310 		 *		     BRASERO_BURN_ERROR_DRIVE_BUSY,
2311 		 *		     "%s. %s",
2312 		 *		     _("The drive is busy"),
2313 		 *		     _("Make sure another application is not using it"));
2314 		 *	return BRASERO_BURN_ERR;
2315 		 * }
2316 		 */
2317 
2318 		result = brasero_task_run (priv->task, error);
2319 		g_signal_emit (self,
2320 			       brasero_burn_signals [PROGRESS_CHANGED_SIGNAL],
2321 			       0,
2322 			       1.0,
2323 			       1.0,
2324 			       -1L);
2325 
2326 		g_object_unref (priv->task);
2327 		priv->task = NULL;
2328 	}
2329 	else {
2330 		BRASERO_BURN_LOG ("The track cannot be checked");
2331 		return BRASERO_BURN_OK;
2332 	}
2333 
2334 	return result;
2335 }
2336 
2337 static void
brasero_burn_unset_checksums(BraseroBurn * self)2338 brasero_burn_unset_checksums (BraseroBurn *self)
2339 {
2340 	GSList *tracks;
2341 	BraseroTrackType *type;
2342 	BraseroBurnPrivate *priv;
2343 
2344 	priv = BRASERO_BURN_PRIVATE (self);
2345 
2346 	tracks = brasero_burn_session_get_tracks (priv->session);
2347 	type = brasero_track_type_new ();
2348 	for (; tracks; tracks = tracks->next) {
2349 		BraseroTrack *track;
2350 
2351 		track = tracks->data;
2352 		brasero_track_get_track_type (track, type);
2353 		if (!brasero_track_type_get_has_image (type)
2354 		&& !brasero_track_type_get_has_medium (type))
2355 			brasero_track_set_checksum (track,
2356 						    BRASERO_CHECKSUM_NONE,
2357 						    NULL);
2358 	}
2359 
2360 	brasero_track_type_free (type);
2361 }
2362 
2363 static BraseroBurnResult
brasero_burn_record_session(BraseroBurn * burn,gboolean erase_allowed,BraseroTrackType * temp_output,GError ** error)2364 brasero_burn_record_session (BraseroBurn *burn,
2365 			     gboolean erase_allowed,
2366                              BraseroTrackType *temp_output,
2367 			     GError **error)
2368 {
2369 	gboolean dummy_session = FALSE;
2370 	const gchar *checksum = NULL;
2371 	BraseroTrack *track = NULL;
2372 	BraseroChecksumType type;
2373 	BraseroBurnPrivate *priv;
2374 	BraseroBurnResult result;
2375 	GError *ret_error = NULL;
2376 	GSList *tracks;
2377 
2378 	priv = BRASERO_BURN_PRIVATE (burn);
2379 
2380 	/* unset checksum since no image has the exact
2381 	 * same even if it is created from the same files */
2382 	brasero_burn_unset_checksums (burn);
2383 
2384 	do {
2385 		if (ret_error) {
2386 			g_error_free (ret_error);
2387 			ret_error = NULL;
2388 		}
2389 
2390 		result = brasero_burn_run_tasks (burn,
2391 						 erase_allowed,
2392 		                                 temp_output,
2393 		                                 &dummy_session,
2394 						 &ret_error);
2395 	} while (result == BRASERO_BURN_RETRY);
2396 
2397 	if (result != BRASERO_BURN_OK) {
2398 		/* handle errors */
2399 		if (ret_error) {
2400 			g_propagate_error (error, ret_error);
2401 			ret_error = NULL;
2402 		}
2403 
2404 		return result;
2405 	}
2406 
2407 	if (brasero_burn_session_is_dest_file (priv->session))
2408 		return BRASERO_BURN_OK;
2409 
2410 	if (dummy_session) {
2411 		/* if we are in dummy mode and successfully completed then:
2412 		 * - no need to checksum the media afterward (done later)
2413 		 * - no eject to have automatic real burning */
2414 
2415 		BRASERO_BURN_DEBUG (burn, "Dummy session successfully finished");
2416 
2417 		/* recording was successful, so tell it */
2418 		brasero_burn_action_changed_real (burn, BRASERO_BURN_ACTION_FINISHED);
2419 
2420 		/* need to try again but this time for real */
2421 		result = brasero_burn_emit_signal (burn,
2422 						   DUMMY_SUCCESS_SIGNAL,
2423 						   BRASERO_BURN_OK);
2424 		if (result != BRASERO_BURN_OK)
2425 			return result;
2426 
2427 		/* unset checksum since no image has the exact same even if it
2428 		 * is created from the same files */
2429 		brasero_burn_unset_checksums (burn);
2430 
2431 		/* remove dummy flag and restart real burning calling ourselves
2432 		 * NOTE: don't bother to push the session. We know the changes
2433 		 * that were made. */
2434 		brasero_burn_session_remove_flag (priv->session, BRASERO_BURN_FLAG_DUMMY);
2435 		result = brasero_burn_record_session (burn, FALSE, temp_output, error);
2436 		brasero_burn_session_add_flag (priv->session, BRASERO_BURN_FLAG_DUMMY);
2437 
2438 		return result;
2439 	}
2440 
2441 	/* see if we have a checksum generated for the session if so use
2442 	 * it to check if the recording went well remaining on the top of
2443 	 * the session should be the last track burnt/imaged */
2444 	tracks = brasero_burn_session_get_tracks (priv->session);
2445 	if (g_slist_length (tracks) != 1)
2446 		return BRASERO_BURN_OK;
2447 
2448 	track = tracks->data;
2449 	type = brasero_track_get_checksum_type (track);
2450 	if (type == BRASERO_CHECKSUM_MD5
2451 	||  type == BRASERO_CHECKSUM_SHA1
2452 	||  type == BRASERO_CHECKSUM_SHA256)
2453 		checksum = brasero_track_get_checksum (track);
2454 	else if (type == BRASERO_CHECKSUM_MD5_FILE)
2455 		checksum = BRASERO_MD5_FILE;
2456 	else if (type == BRASERO_CHECKSUM_SHA1_FILE)
2457 		checksum = BRASERO_SHA1_FILE;
2458 	else if (type == BRASERO_CHECKSUM_SHA256_FILE)
2459 		checksum = BRASERO_SHA256_FILE;
2460 	else
2461 		return BRASERO_BURN_OK;
2462 
2463 	/* recording was successful, so tell it */
2464 	brasero_burn_action_changed_real (burn, BRASERO_BURN_ACTION_FINISHED);
2465 
2466 	/* the idea is to push a new track on the stack with
2467 	 * the current disc burnt and the checksum generated
2468 	 * during the session recording */
2469 	brasero_burn_session_push_tracks (priv->session);
2470 
2471 	track = BRASERO_TRACK (brasero_track_disc_new ());
2472 	brasero_track_set_checksum (BRASERO_TRACK (track),
2473 	                            type,
2474 	                            checksum);
2475 
2476 	brasero_track_disc_set_drive (BRASERO_TRACK_DISC (track), brasero_burn_session_get_burner (priv->session));
2477 	brasero_burn_session_add_track (priv->session, track, NULL);
2478 
2479 	/* It's good practice to unref the track afterwards as we don't need it
2480 	 * anymore. BraseroBurnSession refs it. */
2481 	g_object_unref (track);
2482 
2483 	BRASERO_BURN_DEBUG (burn, "Preparing to checksum (type %i %s)", type, checksum);
2484 
2485 	/* reprobe the medium and wait for it to be probed */
2486 	result = brasero_burn_reprobe (burn);
2487 	if (result != BRASERO_BURN_OK) {
2488 		brasero_burn_session_pop_tracks (priv->session);
2489 		return result;
2490 	}
2491 
2492 	/* Why do we do this?
2493 	 * Because for a lot of medium types the size
2494 	 * of the track return is not the real size of the
2495 	 * data that was written; examples
2496 	 * - CD that was written in SAO mode
2497 	 * - a DVD-R which usually aligns its track size
2498 	 *   to a 16 block boundary
2499 	 */
2500 	if (type == BRASERO_CHECKSUM_MD5
2501 	||  type == BRASERO_CHECKSUM_SHA1
2502 	||  type == BRASERO_CHECKSUM_SHA256) {
2503 		GValue *value;
2504 
2505 		/* get the last written track address */
2506 		value = g_new0 (GValue, 1);
2507 		g_value_init (value, G_TYPE_UINT64);
2508 
2509 		BRASERO_BURN_LOG ("Start of last written track address == %lli", priv->session_start);
2510 		g_value_set_uint64 (value, priv->session_start);
2511 		brasero_track_tag_add (track,
2512 				       BRASERO_TRACK_MEDIUM_ADDRESS_START_TAG,
2513 				       value);
2514 
2515 		value = g_new0 (GValue, 1);
2516 		g_value_init (value, G_TYPE_UINT64);
2517 
2518 		BRASERO_BURN_LOG ("End of last written track address == %lli", priv->session_end);
2519 		g_value_set_uint64 (value, priv->session_end);
2520 		brasero_track_tag_add (track,
2521 				       BRASERO_TRACK_MEDIUM_ADDRESS_END_TAG,
2522 				       value);
2523 	}
2524 
2525 	result = brasero_burn_check_real (burn, track, error);
2526 	brasero_burn_session_pop_tracks (priv->session);
2527 
2528 	if (result == BRASERO_BURN_CANCEL) {
2529 		/* change the result value so we won't stop here if there are
2530 		 * other copies to be made */
2531 		result = BRASERO_BURN_OK;
2532 	}
2533 
2534 	return result;
2535 }
2536 
2537 /**
2538  * brasero_burn_check:
2539  * @burn: a #BraseroBurn
2540  * @session: a #BraseroBurnSession
2541  * @error: a #GError
2542  *
2543  * Checks the integrity of a medium according to the parameters
2544  * set in @session. The medium must be inserted in the #BraseroDrive
2545  * set as the source of a #BraseroTrackDisc track inserted in @session.
2546  *
2547  * Return value: a #BraseroBurnResult. The result of the operation.
2548  * BRASERO_BURN_OK if it was successful.
2549  **/
2550 
2551 BraseroBurnResult
brasero_burn_check(BraseroBurn * self,BraseroBurnSession * session,GError ** error)2552 brasero_burn_check (BraseroBurn *self,
2553 		    BraseroBurnSession *session,
2554 		    GError **error)
2555 {
2556 	GSList *tracks;
2557 	BraseroTrack *track;
2558 	BraseroBurnResult result;
2559 	BraseroBurnPrivate *priv;
2560 
2561 	g_return_val_if_fail (BRASERO_IS_BURN (self), BRASERO_BURN_ERR);
2562 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
2563 
2564 	priv = BRASERO_BURN_PRIVATE (self);
2565 
2566 	g_object_ref (session);
2567 	priv->session = session;
2568 
2569 	/* NOTE: no need to check for parameters here;
2570 	 * that'll be done when asking for a task */
2571 	tracks = brasero_burn_session_get_tracks (priv->session);
2572 	if (g_slist_length (tracks) != 1) {
2573 		g_set_error (error,
2574 			     BRASERO_BURN_ERROR,
2575 			     BRASERO_BURN_ERROR_GENERAL,
2576 			     "%s", _("Only one track at a time can be checked"));
2577 		return BRASERO_BURN_ERR;
2578 	}
2579 
2580 	track = tracks->data;
2581 
2582 	/* if the input is a DISC, ask/check there is one and lock it (as dest) */
2583 	if (BRASERO_IS_TRACK_IMAGE (track)) {
2584 		/* make sure there is a disc. If not, ask one and lock it */
2585 		result = brasero_burn_lock_checksum_media (self, error);
2586 		if (result != BRASERO_BURN_OK)
2587 			return result;
2588 	}
2589 
2590 	brasero_burn_powermanagement (self, TRUE);
2591 
2592 	result = brasero_burn_check_real (self, track, error);
2593 
2594 	brasero_burn_powermanagement (self, FALSE);
2595 
2596 	if (result == BRASERO_BURN_OK)
2597 		result = brasero_burn_unlock_medias (self, error);
2598 	else
2599 		brasero_burn_unlock_medias (self, NULL);
2600 
2601 	/* no need to check the result of the comparison, it's set in session */
2602 
2603 	if (result == BRASERO_BURN_OK)
2604 		brasero_burn_action_changed_real (self,
2605 		                                  BRASERO_BURN_ACTION_FINISHED);
2606 
2607 	/* NOTE: unref session only AFTER drives are unlocked */
2608 	priv->session = NULL;
2609 	g_object_unref (session);
2610 
2611 	return result;
2612 }
2613 
2614 static BraseroBurnResult
brasero_burn_same_src_dest_image(BraseroBurn * self,GError ** error)2615 brasero_burn_same_src_dest_image (BraseroBurn *self,
2616 				  GError **error)
2617 {
2618 	BraseroBurnResult result;
2619 	BraseroBurnPrivate *priv;
2620 	BraseroTrackType *output = NULL;
2621 
2622 	/* we can't create a proper list of tasks here since we don't know the
2623 	 * dest media type yet. So we try to find an intermediate image type and
2624 	 * add it to the session as output */
2625 	priv = BRASERO_BURN_PRIVATE (self);
2626 
2627 	/* get the first possible format */
2628 	output = brasero_track_type_new ();
2629 	result = brasero_burn_session_get_tmp_image_type_same_src_dest (priv->session, output);
2630 	if (result != BRASERO_BURN_OK) {
2631 		brasero_track_type_free (output);
2632 		g_set_error (error,
2633 			     BRASERO_BURN_ERROR,
2634 			     BRASERO_BURN_ERROR_GENERAL,
2635 			     "%s", _("No format for the temporary image could be found"));
2636 		return result;
2637 	}
2638 
2639 	/* lock drive */
2640 	result = brasero_burn_lock_src_media (self, error);
2641 	if (result != BRASERO_BURN_OK)
2642 		goto end;
2643 
2644 	/* run */
2645 	result = brasero_burn_record_session (self, TRUE, output, error);
2646 
2647 	/* Check the results right now. If there was
2648 	 * an error the source medium will be dealt
2649 	 * with in brasero_burn_record () anyway
2650 	 * with brasero_burn_unlock_medias () */
2651 	if (result != BRASERO_BURN_OK)
2652 		goto end;
2653 
2654 	/* reset everything back to normal */
2655 	result = brasero_burn_eject (self, priv->src, error);
2656 	if (result != BRASERO_BURN_OK)
2657 		goto end;
2658 
2659 	brasero_burn_unlock_src_media (self, NULL);
2660 
2661 	/* There should be (a) track(s) at the top of
2662 	 * the session stack so no need to create a
2663 	 * new one */
2664 
2665 	brasero_burn_action_changed_real (self, BRASERO_BURN_ACTION_FINISHED);
2666 
2667 end:
2668 
2669 	if (output)
2670 		brasero_track_type_free (output);
2671 
2672 	return result;
2673 }
2674 
2675 static BraseroBurnResult
brasero_burn_same_src_dest_reload_medium(BraseroBurn * burn,GError ** error)2676 brasero_burn_same_src_dest_reload_medium (BraseroBurn *burn,
2677 					  GError **error)
2678 {
2679 	BraseroBurnError berror;
2680 	BraseroBurnPrivate *priv;
2681 	BraseroBurnResult result;
2682 	BraseroMedia required_media;
2683 
2684 	priv = BRASERO_BURN_PRIVATE (burn);
2685 
2686 	BRASERO_BURN_LOG ("Reloading medium after copy");
2687 
2688 	/* Now there is the problem of flags... This really is a special
2689 	 * case. we need to try to adjust the flags to the media type
2690 	 * just after a new one is detected. For example there could be
2691 	 * BURNPROOF/DUMMY whereas they are not supported for DVD+RW. So
2692 	 * we need to be lenient. */
2693 
2694 	/* Eject and ask the user to reload a disc */
2695 	required_media = brasero_burn_session_get_required_media_type (priv->session);
2696 	required_media &= (BRASERO_MEDIUM_WRITABLE|
2697 			   BRASERO_MEDIUM_CD|
2698 			   BRASERO_MEDIUM_DVD|
2699 			   BRASERO_MEDIUM_BD);
2700 
2701 	/* There is sometimes no way to determine which type of media is
2702 	 * required since some flags (that will be adjusted afterwards)
2703 	 * prevent to reach some media type like BURNPROOF and DVD+RW. */
2704 	if (required_media == BRASERO_MEDIUM_NONE)
2705 		required_media = BRASERO_MEDIUM_WRITABLE;
2706 
2707 	berror = BRASERO_BURN_WARNING_INSERT_AFTER_COPY;
2708 
2709 again:
2710 
2711 	result = brasero_burn_ask_for_dest_media (burn,
2712 						  berror,
2713 						  required_media,
2714 						  error);
2715 	if (result != BRASERO_BURN_OK)
2716 		return result;
2717 
2718 	/* Note: we don't need to update the flags anymore
2719 	 * as they are updated in brasero_burn_run_tasks ()
2720 	 * anyway. */
2721 
2722 	if (result != BRASERO_BURN_OK) {
2723 		/* Tell the user his/her disc is not supported and reload */
2724 		berror = BRASERO_BURN_ERROR_MEDIUM_INVALID;
2725 		goto again;
2726 	}
2727 
2728 	result = brasero_burn_lock_dest_media (burn, &berror, error);
2729 	if (result == BRASERO_BURN_CANCEL)
2730 		return result;
2731 
2732 	if (result != BRASERO_BURN_OK) {
2733 		/* Tell the user his/her disc is not supported and reload */
2734 		goto again;
2735 	}
2736 
2737 	return BRASERO_BURN_OK;
2738 }
2739 
2740 /**
2741  * brasero_burn_record:
2742  * @burn: a #BraseroBurn
2743  * @session: a #BraseroBurnSession
2744  * @error: a #GError
2745  *
2746  * Burns or creates a disc image according to the parameters
2747  * set in @session.
2748  *
2749  * Return value: a #BraseroBurnResult. The result of the operation.
2750  * BRASERO_BURN_OK if it was successful.
2751  **/
2752 
2753 BraseroBurnResult
brasero_burn_record(BraseroBurn * burn,BraseroBurnSession * session,GError ** error)2754 brasero_burn_record (BraseroBurn *burn,
2755 		     BraseroBurnSession *session,
2756 		     GError **error)
2757 {
2758 	BraseroTrackType *type = NULL;
2759 	BraseroBurnResult result;
2760 	BraseroBurnPrivate *priv;
2761 
2762 	g_return_val_if_fail (BRASERO_IS_BURN (burn), BRASERO_BURN_ERR);
2763 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
2764 
2765 	priv = BRASERO_BURN_PRIVATE (burn);
2766 
2767 	/* make sure we're ready */
2768 	if (brasero_burn_session_get_status (session, NULL) != BRASERO_BURN_OK)
2769 		return BRASERO_BURN_ERR;
2770 
2771 	g_object_ref (session);
2772 	priv->session = session;
2773 
2774 	brasero_burn_powermanagement (burn, TRUE);
2775 
2776 	/* say to the whole world we started */
2777 	brasero_burn_action_changed_real (burn, BRASERO_BURN_ACTION_PREPARING);
2778 
2779 	if (brasero_burn_session_same_src_dest_drive (session)) {
2780 		/* This is a special case */
2781 		result = brasero_burn_same_src_dest_image (burn, error);
2782 		if (result != BRASERO_BURN_OK)
2783 			goto end;
2784 
2785 		result = brasero_burn_same_src_dest_reload_medium (burn, error);
2786 		if (result != BRASERO_BURN_OK)
2787 			goto end;
2788 	}
2789 	else if (!brasero_burn_session_is_dest_file (session)) {
2790 		BraseroBurnError berror = BRASERO_BURN_ERROR_NONE;
2791 
2792 		/* do some drive locking quite early to make sure we have a
2793 		 * media in the drive so that we'll have all the necessary
2794 		 * information */
2795 		result = brasero_burn_lock_dest_media (burn, &berror, error);
2796 		while (result == BRASERO_BURN_NEED_RELOAD) {
2797 			BraseroMedia required_media;
2798 
2799 			required_media = brasero_burn_session_get_required_media_type (priv->session);
2800 			if (required_media == BRASERO_MEDIUM_NONE)
2801 				required_media = BRASERO_MEDIUM_WRITABLE;
2802 
2803 			result = brasero_burn_ask_for_dest_media (burn,
2804 								  berror,
2805 								  required_media,
2806 								  error);
2807 			if (result != BRASERO_BURN_OK)
2808 				goto end;
2809 
2810 			result = brasero_burn_lock_dest_media (burn, &berror, error);
2811 		}
2812 
2813 		if (result != BRASERO_BURN_OK)
2814 			goto end;
2815 	}
2816 
2817 	type = brasero_track_type_new ();
2818 	brasero_burn_session_get_input_type (session, type);
2819 	if (brasero_track_type_get_has_medium (type)) {
2820 		result = brasero_burn_lock_src_media (burn, error);
2821 		if (result != BRASERO_BURN_OK)
2822 			goto end;
2823 	}
2824 
2825 	/* burn the session except if dummy session */
2826 	result = brasero_burn_record_session (burn, TRUE, NULL, error);
2827 
2828 end:
2829 
2830 	brasero_track_type_free (type);
2831 
2832 	if (result == BRASERO_BURN_OK)
2833 		result = brasero_burn_unlock_medias (burn, error);
2834 	else
2835 		brasero_burn_unlock_medias (burn, NULL);
2836 
2837 	if (error && (*error) == NULL
2838 	&& (result == BRASERO_BURN_NOT_READY
2839 	||  result == BRASERO_BURN_NOT_SUPPORTED
2840 	||  result == BRASERO_BURN_RUNNING
2841 	||  result == BRASERO_BURN_NOT_RUNNING)) {
2842 		BRASERO_BURN_LOG ("Internal error with result %i", result);
2843 		g_set_error (error,
2844 			     BRASERO_BURN_ERROR,
2845 			     BRASERO_BURN_ERROR_GENERAL,
2846 			     "%s", _("An internal error occurred"));
2847 	}
2848 
2849 	if (result == BRASERO_BURN_CANCEL) {
2850 		BRASERO_BURN_DEBUG (burn, "Session cancelled by user");
2851 	}
2852 	else if (result != BRASERO_BURN_OK) {
2853 		if (error && (*error)) {
2854 			BRASERO_BURN_DEBUG (burn,
2855 					    "Session error : %s",
2856 					    (*error)->message);
2857 		}
2858 		else
2859 			BRASERO_BURN_DEBUG (burn, "Session error : unknown");
2860 	}
2861 	else {
2862 		BRASERO_BURN_DEBUG (burn, "Session successfully finished");
2863 		brasero_burn_action_changed_real (burn,
2864 		                                  BRASERO_BURN_ACTION_FINISHED);
2865 	}
2866 
2867 	brasero_burn_powermanagement (burn, FALSE);
2868 
2869 	/* release session */
2870 	g_object_unref (priv->session);
2871 	priv->session = NULL;
2872 
2873 	return result;
2874 }
2875 
2876 static BraseroBurnResult
brasero_burn_blank_real(BraseroBurn * burn,GError ** error)2877 brasero_burn_blank_real (BraseroBurn *burn, GError **error)
2878 {
2879 	BraseroBurnResult result;
2880 	BraseroBurnPrivate *priv;
2881 
2882 	priv = BRASERO_BURN_PRIVATE (burn);
2883 
2884 	priv->task = brasero_burn_caps_new_blanking_task (priv->caps,
2885 							  priv->session,
2886 							  error);
2887 	if (!priv->task)
2888 		return BRASERO_BURN_NOT_SUPPORTED;
2889 
2890 	g_signal_connect (priv->task,
2891 			  "progress-changed",
2892 			  G_CALLBACK (brasero_burn_progress_changed),
2893 			  burn);
2894 	g_signal_connect (priv->task,
2895 			  "action-changed",
2896 			  G_CALLBACK (brasero_burn_action_changed),
2897 			  burn);
2898 
2899 	result = brasero_burn_run_eraser (burn, error);
2900 	g_object_unref (priv->task);
2901 	priv->task = NULL;
2902 
2903 	return result;
2904 }
2905 
2906 /**
2907  * brasero_burn_blank:
2908  * @burn: a #BraseroBurn
2909  * @session: a #BraseroBurnSession
2910  * @error: a #GError
2911  *
2912  * Blanks a medium according to the parameters
2913  * set in @session. The medium must be inserted in the #BraseroDrive
2914  * set with brasero_burn_session_set_burner ().
2915  *
2916  * Return value: a #BraseroBurnResult. The result of the operation.
2917  * BRASERO_BURN_OK if it was successful.
2918  **/
2919 
2920 BraseroBurnResult
brasero_burn_blank(BraseroBurn * burn,BraseroBurnSession * session,GError ** error)2921 brasero_burn_blank (BraseroBurn *burn,
2922 		    BraseroBurnSession *session,
2923 		    GError **error)
2924 {
2925 	BraseroBurnPrivate *priv;
2926 	BraseroBurnResult result;
2927 	GError *ret_error = NULL;
2928 
2929 	g_return_val_if_fail (burn != NULL, BRASERO_BURN_ERR);
2930 	g_return_val_if_fail (session != NULL, BRASERO_BURN_ERR);
2931 
2932 	priv = BRASERO_BURN_PRIVATE (burn);
2933 
2934 	g_object_ref (session);
2935 	priv->session = session;
2936 
2937 	brasero_burn_powermanagement (burn, TRUE);
2938 
2939 	/* we wait for the insertion of a media and lock it */
2940 	result = brasero_burn_lock_rewritable_media (burn, error);
2941 	if (result != BRASERO_BURN_OK)
2942 		goto end;
2943 
2944 	result = brasero_burn_blank_real (burn, &ret_error);
2945 	while (result == BRASERO_BURN_ERR &&
2946 	       ret_error &&
2947 	       ret_error->code == BRASERO_BURN_ERROR_MEDIUM_NOT_REWRITABLE) {
2948 		g_error_free (ret_error);
2949 		ret_error = NULL;
2950 
2951 		result = brasero_burn_ask_for_dest_media (burn,
2952 							  BRASERO_BURN_ERROR_MEDIUM_NOT_REWRITABLE,
2953 							  BRASERO_MEDIUM_REWRITABLE|
2954 							  BRASERO_MEDIUM_HAS_DATA,
2955 							  error);
2956 		if (result != BRASERO_BURN_OK)
2957 			break;
2958 
2959 		result = brasero_burn_lock_rewritable_media (burn, error);
2960 		if (result != BRASERO_BURN_OK)
2961 			break;
2962 
2963 		result = brasero_burn_blank_real (burn, &ret_error);
2964 	}
2965 
2966 end:
2967 	if (ret_error)
2968 		g_propagate_error (error, ret_error);
2969 
2970 	if (result == BRASERO_BURN_OK && !ret_error)
2971 		result = brasero_burn_unlock_medias (burn, error);
2972 	else
2973 		brasero_burn_unlock_medias (burn, NULL);
2974 
2975 	if (result == BRASERO_BURN_OK)
2976 		brasero_burn_action_changed_real (burn, BRASERO_BURN_ACTION_FINISHED);
2977 
2978 	brasero_burn_powermanagement (burn, FALSE);
2979 
2980 	/* release session */
2981 	g_object_unref (priv->session);
2982 	priv->session = NULL;
2983 
2984 	return result;
2985 }
2986 
2987 /**
2988  * brasero_burn_cancel:
2989  * @burn: a #BraseroBurn
2990  * @protect: a #gboolean
2991  *
2992  * Cancels any ongoing operation. If @protect is TRUE then
2993  * cancellation will not take place for a "critical" task, a task whose interruption
2994  * could damage the medium or the drive.
2995  *
2996  * Return value: a #BraseroBurnResult. The result of the operation.
2997  * BRASERO_BURN_OK if it was successful.
2998  **/
2999 
3000 BraseroBurnResult
brasero_burn_cancel(BraseroBurn * burn,gboolean protect)3001 brasero_burn_cancel (BraseroBurn *burn, gboolean protect)
3002 {
3003 	BraseroBurnResult result = BRASERO_BURN_OK;
3004 	BraseroBurnPrivate *priv;
3005 
3006 	g_return_val_if_fail (BRASERO_BURN (burn), BRASERO_BURN_ERR);
3007 
3008 	priv = BRASERO_BURN_PRIVATE (burn);
3009 
3010 	if (priv->timeout_id) {
3011 		g_source_remove (priv->timeout_id);
3012 		priv->timeout_id = 0;
3013 	}
3014 
3015 	if (priv->sleep_loop) {
3016 		g_main_loop_quit (priv->sleep_loop);
3017 		priv->sleep_loop = NULL;
3018 	}
3019 
3020 	if (priv->dest)
3021 		brasero_drive_cancel_current_operation (priv->dest);
3022 
3023 	if (priv->src)
3024 		brasero_drive_cancel_current_operation (priv->src);
3025 
3026 	if (priv->task && brasero_task_is_running (priv->task))
3027 		result = brasero_task_cancel (priv->task, protect);
3028 
3029 	return result;
3030 }
3031 
3032 static void
brasero_burn_finalize(GObject * object)3033 brasero_burn_finalize (GObject *object)
3034 {
3035 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (object);
3036 
3037 	if (priv->timeout_id) {
3038 		g_source_remove (priv->timeout_id);
3039 		priv->timeout_id = 0;
3040 	}
3041 
3042 	if (priv->sleep_loop) {
3043 		g_main_loop_quit (priv->sleep_loop);
3044 		priv->sleep_loop = NULL;
3045 	}
3046 
3047 	if (priv->task) {
3048 		g_object_unref (priv->task);
3049 		priv->task = NULL;
3050 	}
3051 
3052 	if (priv->session) {
3053 		g_object_unref (priv->session);
3054 		priv->session = NULL;
3055 	}
3056 
3057 	if (priv->caps)
3058 		g_object_unref (priv->caps);
3059 
3060 	G_OBJECT_CLASS (parent_class)->finalize (object);
3061 }
3062 
3063 static void
brasero_burn_class_init(BraseroBurnClass * klass)3064 brasero_burn_class_init (BraseroBurnClass *klass)
3065 {
3066 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
3067 
3068 	g_type_class_add_private (klass, sizeof (BraseroBurnPrivate));
3069 
3070 	parent_class = g_type_class_peek_parent (klass);
3071 	object_class->finalize = brasero_burn_finalize;
3072 
3073 	brasero_burn_signals [ASK_DISABLE_JOLIET_SIGNAL] =
3074 		g_signal_new ("disable_joliet",
3075 			      G_TYPE_FROM_CLASS (klass),
3076 			      G_SIGNAL_RUN_LAST,
3077 			      G_STRUCT_OFFSET (BraseroBurnClass,
3078 					       ask_disable_joliet),
3079 			      NULL, NULL,
3080 			      brasero_marshal_INT__VOID,
3081 			      G_TYPE_INT, 0);
3082         brasero_burn_signals [WARN_DATA_LOSS_SIGNAL] =
3083 		g_signal_new ("warn_data_loss",
3084 			      G_TYPE_FROM_CLASS (klass),
3085 			      G_SIGNAL_RUN_LAST,
3086 			      G_STRUCT_OFFSET (BraseroBurnClass,
3087 					       warn_data_loss),
3088 			      NULL, NULL,
3089 			      brasero_marshal_INT__VOID,
3090 			      G_TYPE_INT, 0);
3091         brasero_burn_signals [WARN_PREVIOUS_SESSION_LOSS_SIGNAL] =
3092 		g_signal_new ("warn_previous_session_loss",
3093 			      G_TYPE_FROM_CLASS (klass),
3094 			      G_SIGNAL_RUN_LAST,
3095 			      G_STRUCT_OFFSET (BraseroBurnClass,
3096 					       warn_previous_session_loss),
3097 			      NULL, NULL,
3098 			      brasero_marshal_INT__VOID,
3099 			      G_TYPE_INT, 0);
3100         brasero_burn_signals [WARN_AUDIO_TO_APPENDABLE_SIGNAL] =
3101 		g_signal_new ("warn_audio_to_appendable",
3102 			      G_TYPE_FROM_CLASS (klass),
3103 			      G_SIGNAL_RUN_LAST,
3104 			      G_STRUCT_OFFSET (BraseroBurnClass,
3105 					       warn_audio_to_appendable),
3106 			      NULL, NULL,
3107 			      brasero_marshal_INT__VOID,
3108 			      G_TYPE_INT, 0);
3109 	brasero_burn_signals [WARN_REWRITABLE_SIGNAL] =
3110 		g_signal_new ("warn_rewritable",
3111 			      G_TYPE_FROM_CLASS (klass),
3112 			      G_SIGNAL_RUN_LAST,
3113 			      G_STRUCT_OFFSET (BraseroBurnClass,
3114 					       warn_rewritable),
3115 			      NULL, NULL,
3116 			      brasero_marshal_INT__VOID,
3117 			      G_TYPE_INT, 0);
3118 	brasero_burn_signals [INSERT_MEDIA_REQUEST_SIGNAL] =
3119 		g_signal_new ("insert_media",
3120 			      G_TYPE_FROM_CLASS (klass),
3121 			      G_SIGNAL_RUN_LAST,
3122 			      G_STRUCT_OFFSET (BraseroBurnClass,
3123 					       insert_media_request),
3124 			      NULL, NULL,
3125 			      brasero_marshal_INT__OBJECT_INT_INT,
3126 			      G_TYPE_INT,
3127 			      3,
3128 			      BRASERO_TYPE_DRIVE,
3129 			      G_TYPE_INT,
3130 			      G_TYPE_INT);
3131 	brasero_burn_signals [LOCATION_REQUEST_SIGNAL] =
3132 		g_signal_new ("location-request",
3133 			      G_TYPE_FROM_CLASS (klass),
3134 			      G_SIGNAL_RUN_LAST,
3135 			      G_STRUCT_OFFSET (BraseroBurnClass,
3136 					       location_request),
3137 			      NULL, NULL,
3138 			      brasero_marshal_INT__POINTER_BOOLEAN,
3139 			      G_TYPE_INT,
3140 			      2,
3141 			      G_TYPE_POINTER,
3142 			      G_TYPE_INT);
3143 	brasero_burn_signals [PROGRESS_CHANGED_SIGNAL] =
3144 		g_signal_new ("progress_changed",
3145 			      G_TYPE_FROM_CLASS (klass),
3146 			      G_SIGNAL_RUN_LAST,
3147 			      G_STRUCT_OFFSET (BraseroBurnClass,
3148 					       progress_changed),
3149 			      NULL, NULL,
3150 			      brasero_marshal_VOID__DOUBLE_DOUBLE_LONG,
3151 			      G_TYPE_NONE,
3152 			      3,
3153 			      G_TYPE_DOUBLE,
3154 			      G_TYPE_DOUBLE,
3155 			      G_TYPE_LONG);
3156         brasero_burn_signals [ACTION_CHANGED_SIGNAL] =
3157 		g_signal_new ("action_changed",
3158 			      G_TYPE_FROM_CLASS (klass),
3159 			      G_SIGNAL_RUN_LAST,
3160 			      G_STRUCT_OFFSET (BraseroBurnClass,
3161 					       action_changed),
3162 			      NULL, NULL,
3163 			      g_cclosure_marshal_VOID__INT,
3164 			      G_TYPE_NONE,
3165 			      1,
3166 			      G_TYPE_INT);
3167         brasero_burn_signals [DUMMY_SUCCESS_SIGNAL] =
3168 		g_signal_new ("dummy_success",
3169 			      G_TYPE_FROM_CLASS (klass),
3170 			      G_SIGNAL_RUN_LAST,
3171 			      G_STRUCT_OFFSET (BraseroBurnClass,
3172 					       dummy_success),
3173 			      NULL, NULL,
3174 			      brasero_marshal_INT__VOID,
3175 			      G_TYPE_INT, 0);
3176         brasero_burn_signals [EJECT_FAILURE_SIGNAL] =
3177 		g_signal_new ("eject_failure",
3178 			      G_TYPE_FROM_CLASS (klass),
3179 			      G_SIGNAL_RUN_LAST,
3180 			      G_STRUCT_OFFSET (BraseroBurnClass,
3181 					       eject_failure),
3182 			      NULL, NULL,
3183 			      brasero_marshal_INT__OBJECT,
3184 			      G_TYPE_INT, 1,
3185 		              BRASERO_TYPE_DRIVE);
3186         brasero_burn_signals [BLANK_FAILURE_SIGNAL] =
3187 		g_signal_new ("blank_failure",
3188 			      G_TYPE_FROM_CLASS (klass),
3189 			      G_SIGNAL_RUN_LAST,
3190 			      G_STRUCT_OFFSET (BraseroBurnClass,
3191 					       blank_failure),
3192 			      NULL, NULL,
3193 			      brasero_marshal_INT__VOID,
3194 			      G_TYPE_INT, 0,
3195 		              G_TYPE_NONE);
3196 	brasero_burn_signals [INSTALL_MISSING_SIGNAL] =
3197 		g_signal_new ("install_missing",
3198 			      G_TYPE_FROM_CLASS (klass),
3199 			      G_SIGNAL_RUN_LAST,
3200 			      G_STRUCT_OFFSET (BraseroBurnClass,
3201 					       install_missing),
3202 			      NULL, NULL,
3203 			      brasero_marshal_INT__INT_STRING,
3204 			      G_TYPE_INT, 2,
3205 		              G_TYPE_INT,
3206 			      G_TYPE_STRING);
3207 }
3208 
3209 static void
brasero_burn_init(BraseroBurn * obj)3210 brasero_burn_init (BraseroBurn *obj)
3211 {
3212 	BraseroBurnPrivate *priv = BRASERO_BURN_PRIVATE (obj);
3213 
3214 	priv->caps = brasero_burn_caps_get_default ();
3215 }
3216