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 <errno.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 
41 #include <glib.h>
42 #include <glib-object.h>
43 #include <glib/gstdio.h>
44 #include <glib/gi18n-lib.h>
45 
46 #include "brasero-session.h"
47 #include "brasero-session-helper.h"
48 
49 #include "burn-basics.h"
50 #include "burn-debug.h"
51 #include "libbrasero-marshal.h"
52 #include "burn-image-format.h"
53 #include "brasero-track-type-private.h"
54 
55 #include "brasero-medium.h"
56 #include "brasero-drive.h"
57 #include "brasero-drive-priv.h"
58 #include "brasero-medium-monitor.h"
59 
60 #include "brasero-tags.h"
61 #include "brasero-track.h"
62 #include "brasero-track-disc.h"
63 
64 G_DEFINE_TYPE (BraseroBurnSession, brasero_burn_session, G_TYPE_OBJECT);
65 #define BRASERO_BURN_SESSION_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_BURN_SESSION, BraseroBurnSessionPrivate))
66 
67 /**
68  * SECTION:brasero-session
69  * @short_description: Store parameters when burning and blanking
70  * @see_also: #BraseroBurn, #BraseroSessionCfg
71  * @include: brasero-session.h
72  *
73  * This object stores all parameters for all operations performed by #BraseroBurn such as
74  * burning, blanking and checksuming. To have this object configured automatically see
75  * #BraseroSessionCfg.
76  **/
77 
78 struct _BraseroSessionSetting {
79 	BraseroDrive *burner;
80 
81 	/**
82 	 * Used when outputting an image instead of burning
83 	 */
84 	BraseroImageFormat format;
85 	gchar *image;
86 	gchar *toc;
87 
88 	/**
89 	 * Used when burning
90 	 */
91 	gchar *label;
92 	guint64 rate;
93 
94 	BraseroBurnFlag flags;
95 };
96 typedef struct _BraseroSessionSetting BraseroSessionSetting;
97 
98 struct _BraseroBurnSessionPrivate {
99 	int session;
100 	gchar *session_path;
101 
102 	gchar *tmpdir;
103 	GSList *tmpfiles;
104 
105 	BraseroSessionSetting settings [1];
106 	GSList *pile_settings;
107 
108 	GHashTable *tags;
109 
110 	guint dest_added_sig;
111 	guint dest_removed_sig;
112 
113 	GSList *tracks;
114 	GSList *pile_tracks;
115 
116 	guint strict_checks:1;
117 };
118 typedef struct _BraseroBurnSessionPrivate BraseroBurnSessionPrivate;
119 
120 #define BRASERO_BURN_SESSION_WRITE_TO_DISC(priv)	(priv->settings->burner &&			\
121 							!brasero_drive_is_fake (priv->settings->burner))
122 #define BRASERO_BURN_SESSION_WRITE_TO_FILE(priv)	(priv->settings->burner &&			\
123 							 brasero_drive_is_fake (priv->settings->burner))
124 #define BRASERO_STR_EQUAL(a, b)	((!(a) && !(b)) || ((a) && (b) && !strcmp ((a), (b))))
125 
126 typedef enum {
127 	TAG_CHANGED_SIGNAL,
128 	TRACK_ADDED_SIGNAL,
129 	TRACK_REMOVED_SIGNAL,
130 	TRACK_CHANGED_SIGNAL,
131 	OUTPUT_CHANGED_SIGNAL,
132 	LAST_SIGNAL
133 } BraseroBurnSessionSignalType;
134 
135 static guint brasero_burn_session_signals [LAST_SIGNAL] = { 0 };
136 
137 enum {
138 	PROP_0,
139 	PROP_TMPDIR,
140 	PROP_RATE,
141 	PROP_FLAGS
142 };
143 
144 static GObjectClass *parent_class = NULL;
145 
146 static void
brasero_session_settings_clean(BraseroSessionSetting * settings)147 brasero_session_settings_clean (BraseroSessionSetting *settings)
148 {
149 	if (settings->image)
150 		g_free (settings->image);
151 
152 	if (settings->toc)
153 		g_free (settings->toc);
154 
155 	if (settings->label)
156 		g_free (settings->label);
157 
158 	if (settings->burner)
159 		g_object_unref (settings->burner);
160 
161 	memset (settings, 0, sizeof (BraseroSessionSetting));
162 }
163 
164 static void
brasero_session_settings_copy(BraseroSessionSetting * dest,BraseroSessionSetting * original)165 brasero_session_settings_copy (BraseroSessionSetting *dest,
166 			       BraseroSessionSetting *original)
167 {
168 	brasero_session_settings_clean (dest);
169 
170 	memcpy (dest, original, sizeof (BraseroSessionSetting));
171 
172 	g_object_ref (dest->burner);
173 	dest->image = g_strdup (original->image);
174 	dest->toc = g_strdup (original->toc);
175 	dest->label = g_strdup (original->label);
176 }
177 
178 static void
brasero_session_settings_free(BraseroSessionSetting * settings)179 brasero_session_settings_free (BraseroSessionSetting *settings)
180 {
181 	brasero_session_settings_clean (settings);
182 	g_free (settings);
183 }
184 
185 static void
brasero_burn_session_track_changed(BraseroTrack * track,BraseroBurnSession * self)186 brasero_burn_session_track_changed (BraseroTrack *track,
187 				    BraseroBurnSession *self)
188 {
189 	g_signal_emit (self,
190 		       brasero_burn_session_signals [TRACK_CHANGED_SIGNAL],
191 		       0,
192 		       track);
193 }
194 
195 static void
brasero_burn_session_start_track_monitoring(BraseroBurnSession * self,BraseroTrack * track)196 brasero_burn_session_start_track_monitoring (BraseroBurnSession *self,
197 					     BraseroTrack *track)
198 {
199 	g_signal_connect (track,
200 			  "changed",
201 			  G_CALLBACK (brasero_burn_session_track_changed),
202 			  self);
203 }
204 
205 static void
brasero_burn_session_stop_tracks_monitoring(BraseroBurnSession * self)206 brasero_burn_session_stop_tracks_monitoring (BraseroBurnSession *self)
207 {
208 	BraseroBurnSessionPrivate *priv;
209 	GSList *iter;
210 
211 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
212 
213 	for (iter = priv->tracks; iter; iter = iter->next) {
214 		BraseroTrack *track;
215 
216 		track = iter->data;
217 		g_signal_handlers_disconnect_by_func (track,
218 						      brasero_burn_session_track_changed,
219 						      self);
220 	}
221 }
222 
223 static void
brasero_burn_session_free_tracks(BraseroBurnSession * self)224 brasero_burn_session_free_tracks (BraseroBurnSession *self)
225 {
226 	BraseroBurnSessionPrivate *priv;
227 	GSList *iter;
228 	GSList *next;
229 
230 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
231 
232 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
233 
234 	brasero_burn_session_stop_tracks_monitoring (self);
235 
236 	for (iter = priv->tracks; iter; iter = next) {
237 		BraseroTrack *track;
238 
239 		track = iter->data;
240 		next = iter->next;
241 		priv->tracks = g_slist_remove (priv->tracks, track);
242 		g_signal_emit (self,
243 			       brasero_burn_session_signals [TRACK_REMOVED_SIGNAL],
244 			       0,
245 			       track,
246 			       0);
247 		g_object_unref (track);
248 	}
249 }
250 
251 /**
252  * brasero_burn_session_set_strict_support:
253  * @session: a #BraseroBurnSession.
254  * @flags: a #BraseroSessionCheckFlags
255  *
256  * For the following functions:
257  * brasero_burn_session_supported ()
258  * brasero_burn_session_input_supported ()
259  * brasero_burn_session_output_supported ()
260  * brasero_burn_session_can_blank ()
261  * this function sets whether these functions will
262  * ignore the plugins with errors (%TRUE).
263  */
264 
265 void
brasero_burn_session_set_strict_support(BraseroBurnSession * session,gboolean strict_checks)266 brasero_burn_session_set_strict_support (BraseroBurnSession *session,
267                                          gboolean strict_checks)
268 {
269 	BraseroBurnSessionPrivate *priv;
270 
271 	g_return_if_fail (BRASERO_IS_BURN_SESSION (session));
272 
273 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
274 	priv->strict_checks = strict_checks;
275 }
276 
277 /**
278  * brasero_burn_session_get_strict_support:
279  * @session: a #BraseroBurnSession.
280  *
281  * For the following functions:
282  * brasero_burn_session_can_burn ()
283  * brasero_burn_session_input_supported ()
284  * brasero_burn_session_output_supported ()
285  * brasero_burn_session_can_blank ()
286  * this function gets whether the checks will
287  * ignore the plugins with errors (return %TRUE).
288  *
289  * Returns:  #gboolean
290  */
291 
292 gboolean
brasero_burn_session_get_strict_support(BraseroBurnSession * session)293 brasero_burn_session_get_strict_support (BraseroBurnSession *session)
294 {
295 	BraseroBurnSessionPrivate *priv;
296 
297 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), FALSE);
298 
299 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
300 	return priv->strict_checks;
301 }
302 
303 /**
304  * brasero_burn_session_add_track:
305  * @session: a #BraseroBurnSession.
306  * @new_track: (allow-none): a #BraseroTrack or NULL.
307  * @sibling: (allow-none): a #BraseroTrack or NULL.
308  *
309  * Inserts a new track after @sibling or appended if @sibling is NULL. If @track is NULL then all tracks
310  * already in @session will be removed.
311  * NOTE: if there are already #BraseroTrack objects inserted in the session and if they are not
312  * of the same type as @new_track then they will be removed before the insertion of @new_track.
313  *
314  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if the track was successfully inserted or BRASERO_BURN_ERR otherwise.
315  **/
316 
317 BraseroBurnResult
brasero_burn_session_add_track(BraseroBurnSession * self,BraseroTrack * new_track,BraseroTrack * sibling)318 brasero_burn_session_add_track (BraseroBurnSession *self,
319 				BraseroTrack *new_track,
320 				BraseroTrack *sibling)
321 {
322 	BraseroBurnSessionPrivate *priv;
323 
324 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
325 
326 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
327 
328 	/* Prevent adding the same tracks several times */
329 	if (g_slist_find (priv->tracks, new_track)) {
330 		BRASERO_BURN_LOG ("Tried to add the same track multiple times");
331 		return BRASERO_BURN_OK;
332 	}
333 
334 	if (!new_track) {
335 		if (!priv->tracks)
336 			return BRASERO_BURN_OK;
337 
338 		brasero_burn_session_free_tracks (self);
339 		return BRASERO_BURN_OK;
340 	}
341 
342 	g_object_ref (new_track);
343 	if (!priv->tracks) {
344 		/* we only need to emit the signal here since if there are
345 		 * multiple tracks they must be exactly of the same type */
346 		priv->tracks = g_slist_prepend (NULL, new_track);
347 		brasero_burn_session_start_track_monitoring (self, new_track);
348 
349 		/* if (!brasero_track_type_equal (priv->input, &new_type)) */
350 		g_signal_emit (self,
351 			       brasero_burn_session_signals [TRACK_ADDED_SIGNAL],
352 			       0,
353 			       new_track);
354 
355 		return BRASERO_BURN_OK;
356 	}
357 
358 	/* if there is already a track, then we replace it on condition that it
359 	 * is not AUDIO (only one type allowed to have several tracks) */
360 	if (!BRASERO_IS_TRACK_STREAM (new_track)
361 	||  !BRASERO_IS_TRACK_STREAM (priv->tracks->data))
362 		brasero_burn_session_free_tracks (self);
363 
364 	brasero_burn_session_start_track_monitoring (self, new_track);
365 	if (sibling) {
366 		GSList *sibling_node;
367 
368 		sibling_node = g_slist_find (priv->tracks, sibling);
369 		priv->tracks = g_slist_insert_before (priv->tracks,
370 						      sibling_node,
371 						      new_track);
372 	}
373 	else
374 		priv->tracks = g_slist_append (priv->tracks, new_track);
375 
376 	g_signal_emit (self,
377 		       brasero_burn_session_signals [TRACK_ADDED_SIGNAL],
378 		       0,
379 		       new_track);
380 
381 	return BRASERO_BURN_OK;
382 }
383 
384 /**
385  * brasero_burn_session_move_track:
386  * @session: a #BraseroBurnSession.
387  * @track: a #BraseroTrack.
388  * @sibling: (allow-none): a #BraseroTrack or NULL.
389  *
390  * Moves @track after @sibling; if @sibling is NULL then it is appended.
391  *
392  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if the track was successfully moved or BRASERO_BURN_ERR otherwise.
393  **/
394 
395 BraseroBurnResult
brasero_burn_session_move_track(BraseroBurnSession * session,BraseroTrack * track,BraseroTrack * sibling)396 brasero_burn_session_move_track (BraseroBurnSession *session,
397 				 BraseroTrack *track,
398 				 BraseroTrack *sibling)
399 {
400 	BraseroBurnSessionPrivate *priv;
401 	guint former_position;
402 
403 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
404 
405 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
406 
407 	/* Find the track, remove it */
408 	former_position = g_slist_index (priv->tracks, track);
409 	priv->tracks = g_slist_remove (priv->tracks, track);
410 	g_signal_emit (session,
411 		       brasero_burn_session_signals [TRACK_REMOVED_SIGNAL],
412 		       0,
413 		       track,
414 		       former_position);
415 
416 	/* Re-add it */
417 	if (sibling) {
418 		GSList *sibling_node;
419 
420 		sibling_node = g_slist_find (priv->tracks, sibling);
421 		priv->tracks = g_slist_insert_before (priv->tracks,
422 						      sibling_node,
423 						      track);
424 	}
425 	else
426 		priv->tracks = g_slist_append (priv->tracks, track);
427 
428 	g_signal_emit (session,
429 		       brasero_burn_session_signals [TRACK_ADDED_SIGNAL],
430 		       0,
431 		       track);
432 
433 	return BRASERO_BURN_OK;
434 }
435 
436 /**
437  * brasero_burn_session_remove_track:
438  * @session: a #BraseroBurnSession
439  * @track: a #BraseroTrack
440  *
441  * Removes @track from @session.
442  *
443  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if the track was successfully removed or BRASERO_BURN_ERR otherwise.
444  **/
445 
446 BraseroBurnResult
brasero_burn_session_remove_track(BraseroBurnSession * session,BraseroTrack * track)447 brasero_burn_session_remove_track (BraseroBurnSession *session,
448 				   BraseroTrack *track)
449 {
450 	BraseroBurnSessionPrivate *priv;
451 	guint former_position;
452 
453 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_BURN_ERR);
454 
455 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
456 
457 	/* Find the track, remove it */
458 	former_position = g_slist_index (priv->tracks, track);
459 	priv->tracks = g_slist_remove (priv->tracks, track);
460 	g_signal_handlers_disconnect_by_func (track,
461 					      brasero_burn_session_track_changed,
462 					      session);
463 
464 	g_signal_emit (session,
465 		       brasero_burn_session_signals [TRACK_REMOVED_SIGNAL],
466 		       0,
467 		       track,
468 		       former_position);
469 
470 	g_object_unref (track);
471 	return BRASERO_BURN_OK;
472 }
473 
474 /**
475  * brasero_burn_session_get_tracks:
476  * @session: a #BraseroBurnSession
477  *
478  * Returns the list of #BraseroTrack added to @session.
479  *
480  * Return value: (element-type BraseroBurn.Track) (transfer none): a #GSList or #BraseroTrack object. Do not unref the objects in the list nor destroy the list.
481  *
482  **/
483 
484 GSList *
brasero_burn_session_get_tracks(BraseroBurnSession * self)485 brasero_burn_session_get_tracks (BraseroBurnSession *self)
486 {
487 	BraseroBurnSessionPrivate *priv;
488 
489 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
490 
491 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
492 
493 	return priv->tracks;
494 }
495 
496 /**
497  * brasero_burn_session_get_status:
498  * @session: a #BraseroBurnSession
499  * @status: a #BraseroTrackStatus
500  *
501  * Sets @status to reflect whether @session is ready to be used.
502  *
503  * Return value: a #BraseroBurnResult.
504  * BRASERO_BURN_OK if it was successful
505  * BRASERO_BURN_NOT_READY if @track needs more time for processing
506  * BRASERO_BURN_ERR if something is wrong or if it is empty
507  **/
508 
509 BraseroBurnResult
brasero_burn_session_get_status(BraseroBurnSession * session,BraseroStatus * status)510 brasero_burn_session_get_status (BraseroBurnSession *session,
511 				 BraseroStatus *status)
512 {
513 	BraseroBurnSessionPrivate *priv;
514 	BraseroStatus *track_status;
515 	gdouble num_tracks = 0.0;
516 	guint not_ready = 0;
517 	gdouble done = -1.0;
518 	GSList *iter;
519 
520 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_TRACK_TYPE_NONE);
521 
522 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
523 	if (!priv->tracks)
524 		return BRASERO_BURN_ERR;
525 
526 	track_status = brasero_status_new ();
527 
528 	if (priv->settings->burner && brasero_drive_probing (priv->settings->burner)) {
529 		BRASERO_BURN_LOG ("Drive not ready yet");
530 		brasero_status_set_not_ready (status, -1, NULL);
531 		return BRASERO_BURN_NOT_READY;
532 	}
533 
534 	for (iter = priv->tracks; iter; iter = iter->next) {
535 		BraseroTrack *track;
536 		BraseroBurnResult result;
537 
538 		track = iter->data;
539 		result = brasero_track_get_status (track, track_status);
540 		num_tracks ++;
541 
542 		if (result == BRASERO_BURN_NOT_READY || result == BRASERO_BURN_RUNNING)
543 			not_ready ++;
544 		else if (result != BRASERO_BURN_OK) {
545 			g_object_unref (track_status);
546 			return brasero_track_get_status (track, status);
547 		}
548 
549 		if (brasero_status_get_progress (track_status) != -1.0)
550 			done += brasero_status_get_progress (track_status);
551 	}
552 	g_object_unref (track_status);
553 
554 	if (not_ready > 0) {
555 		if (status) {
556 			if (done != -1.0)
557 				brasero_status_set_not_ready (status,
558 							      (gdouble) ((gdouble) (done) / (gdouble) (num_tracks)),
559 							      NULL);
560 			else
561 				brasero_status_set_not_ready (status, -1.0, NULL);
562 		}
563 		return BRASERO_BURN_NOT_READY;
564 	}
565 
566 	if (status)
567 		brasero_status_set_completed (status);
568 
569 	return BRASERO_BURN_OK;
570 }
571 
572 /**
573  * brasero_burn_session_get_size:
574  * @session: a #BraseroBurnSession
575  * @blocks: a #goffset or NULL
576  * @bytes: a #goffset or NULL
577  *
578  * Returns the size of the data contained by @session in bytes or in sectors
579  *
580  * Return value: a #BraseroBurnResult.
581  * BRASERO_BURN_OK if it was successful
582  * BRASERO_BURN_NOT_READY if @track needs more time for processing the size
583  * BRASERO_BURN_ERR if something is wrong or if it is empty
584  **/
585 
586 BraseroBurnResult
brasero_burn_session_get_size(BraseroBurnSession * session,goffset * blocks,goffset * bytes)587 brasero_burn_session_get_size (BraseroBurnSession *session,
588 			       goffset *blocks,
589 			       goffset *bytes)
590 {
591 	BraseroBurnSessionPrivate *priv;
592 	gsize session_blocks = 0;
593 	gsize session_bytes = 0;
594 	GSList *iter;
595 
596 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (session), BRASERO_TRACK_TYPE_NONE);
597 
598 	priv = BRASERO_BURN_SESSION_PRIVATE (session);
599 	if (!priv->tracks)
600 		return BRASERO_BURN_ERR;
601 
602 	for (iter = priv->tracks; iter; iter = iter->next) {
603 		BraseroBurnResult res;
604 		BraseroTrack *track;
605 		goffset track_blocks;
606 		goffset track_bytes;
607 
608 		track = iter->data;
609 		track_blocks = 0;
610 		track_bytes = 0;
611 
612 		res = brasero_track_get_size (track, &track_blocks, &track_bytes);
613 
614 		/* That way we get the size even if the track has not completed
615 		 * what's it's doing which allows to show progress */
616 		if (res != BRASERO_BURN_OK && res != BRASERO_BURN_NOT_READY)
617 			continue;
618 
619 		session_blocks += track_blocks;
620 		session_bytes += track_bytes;
621 	}
622 
623 	if (blocks)
624 		*blocks = session_blocks;
625 	if (bytes)
626 		*bytes = session_bytes;
627 
628 	return BRASERO_BURN_OK;
629 }
630 
631 /**
632  * brasero_burn_session_get_input_type:
633  * @session: a #BraseroBurnSession
634  * @type: a #BraseroTrackType or NULL
635  *
636  * Sets @type to reflect the type of data contained in @session
637  *
638  * Return value: a #BraseroBurnResult.
639  * BRASERO_BURN_OK if it was successful
640  **/
641 
642 BraseroBurnResult
brasero_burn_session_get_input_type(BraseroBurnSession * self,BraseroTrackType * type)643 brasero_burn_session_get_input_type (BraseroBurnSession *self,
644 				     BraseroTrackType *type)
645 {
646 	GSList *iter;
647 	BraseroStreamFormat format;
648 	BraseroBurnSessionPrivate *priv;
649 
650 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
651 
652 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
653 
654 	/* there can be many tracks (in case of audio) but they must be
655 	 * all of the same kind for the moment. Yet their subtypes may
656 	 * be different. */
657 	format = BRASERO_AUDIO_FORMAT_NONE;
658 	for (iter = priv->tracks; iter; iter = iter->next) {
659 		BraseroTrack *track;
660 
661 		track = iter->data;
662 		brasero_track_get_track_type (track, type);
663 		if (brasero_track_type_get_has_stream (type))
664 			format |= brasero_track_type_get_stream_format (type);
665 	}
666 
667 	if (brasero_track_type_get_has_stream (type))
668 		brasero_track_type_set_image_format (type, format);
669 
670 	return BRASERO_BURN_OK;
671 }
672 
673 static void
brasero_burn_session_dest_media_added(BraseroDrive * drive,BraseroMedium * medium,BraseroBurnSession * self)674 brasero_burn_session_dest_media_added (BraseroDrive *drive,
675 				       BraseroMedium *medium,
676 				       BraseroBurnSession *self)
677 {
678 	/* No medium before */
679 	g_signal_emit (self,
680 		       brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL],
681 		       0,
682 		       NULL);
683 }
684 
685 static void
brasero_burn_session_dest_media_removed(BraseroDrive * drive,BraseroMedium * medium,BraseroBurnSession * self)686 brasero_burn_session_dest_media_removed (BraseroDrive *drive,
687 					 BraseroMedium *medium,
688 					 BraseroBurnSession *self)
689 {
690 	g_signal_emit (self,
691 		       brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL],
692 		       0,
693 		       medium);
694 }
695 
696 /**
697  * brasero_burn_session_set_burner:
698  * @session: a #BraseroBurnSession
699  * @drive: a #BraseroDrive
700  *
701  * Sets the #BraseroDrive that should be used to burn the session contents.
702  *
703  **/
704 
705 void
brasero_burn_session_set_burner(BraseroBurnSession * self,BraseroDrive * drive)706 brasero_burn_session_set_burner (BraseroBurnSession *self,
707 				 BraseroDrive *drive)
708 {
709 	BraseroBurnSessionPrivate *priv;
710 	BraseroMedium *former;
711 
712 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
713 
714 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
715 
716 	if (drive == priv->settings->burner)
717 		return;
718 
719 	former = brasero_drive_get_medium (priv->settings->burner);
720 	if (former)
721 		g_object_ref (former);
722 
723 	/* If there was no drive before no need for a changing signal */
724 	if (priv->settings->burner) {
725 		if (priv->dest_added_sig) {
726 			g_signal_handler_disconnect (priv->settings->burner,
727 						     priv->dest_added_sig);
728 			priv->dest_added_sig = 0;
729 		}
730 
731 		if (priv->dest_removed_sig) {
732 			g_signal_handler_disconnect (priv->settings->burner,
733 						     priv->dest_removed_sig);
734 			priv->dest_removed_sig = 0;
735 		}
736 
737 		g_object_unref (priv->settings->burner);
738 	}
739 
740 	if (drive) {
741 		priv->dest_added_sig = g_signal_connect (drive,
742 							 "medium-added",
743 							 G_CALLBACK (brasero_burn_session_dest_media_added),
744 							 self);
745 		priv->dest_removed_sig = g_signal_connect (drive,
746 							   "medium-removed",
747 							   G_CALLBACK (brasero_burn_session_dest_media_removed),
748 							   self);
749 		g_object_ref (drive);
750 	}
751 
752 	priv->settings->burner = drive;
753 
754 	g_signal_emit (self,
755 		       brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL],
756 		       0,
757 		       former);
758 
759 	if (former)
760 		g_object_unref (former);
761 }
762 
763 /**
764  * brasero_burn_session_get_burner:
765  * @session: a #BraseroBurnSession
766  *
767  * Returns the #BraseroDrive that should be used to burn the session contents.
768  *
769  * Return value: (transfer none) (allow-none): a #BraseroDrive or NULL. Do not unref after use.
770  **/
771 
772 BraseroDrive *
brasero_burn_session_get_burner(BraseroBurnSession * self)773 brasero_burn_session_get_burner (BraseroBurnSession *self)
774 {
775 	BraseroBurnSessionPrivate *priv;
776 
777 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
778 
779 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
780 	return priv->settings->burner;
781 }
782 
783 /**
784  * brasero_burn_session_set_rate:
785  * @session: a #BraseroBurnSession
786  * @rate: a #guint64
787  *
788  * Sets the speed at which the medium should be burnt.
789  * NOTE: before using this function a #BraseroDrive should have been
790  * set with brasero_burn_session_set_burner ().
791  *
792  * Return value: a #BraseroBurnResult.
793  * BRASERO_BURN_OK if it was successful; BRASERO_BURN_ERR otherwise.
794  **/
795 
796 BraseroBurnResult
brasero_burn_session_set_rate(BraseroBurnSession * self,guint64 rate)797 brasero_burn_session_set_rate (BraseroBurnSession *self,
798                                guint64 rate)
799 {
800 	BraseroBurnSessionPrivate *priv;
801 
802 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
803 
804 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
805 
806 	if (!BRASERO_BURN_SESSION_WRITE_TO_DISC (priv))
807 		return BRASERO_BURN_ERR;
808 
809 	priv->settings->rate = rate;
810 	g_object_notify (G_OBJECT (self), "speed");
811 	return BRASERO_BURN_OK;
812 }
813 
814 /**
815  * brasero_burn_session_get_rate:
816  * @session: a #BraseroBurnSession
817  *
818  * Returns the speed at which the medium should be burnt.
819  * NOTE: before using this function a #BraseroDrive should have been
820  * set with brasero_burn_session_set_burner ().
821  *
822  * Return value: a #guint64 or 0.
823  **/
824 
825 guint64
brasero_burn_session_get_rate(BraseroBurnSession * self)826 brasero_burn_session_get_rate (BraseroBurnSession *self)
827 {
828 	BraseroBurnSessionPrivate *priv;
829 	BraseroMedium *medium;
830 	gint64 max_rate;
831 
832 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), 0);
833 
834 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
835 
836 	if (!BRASERO_BURN_SESSION_WRITE_TO_DISC (priv))
837 		return 0;
838 
839 	medium = brasero_drive_get_medium (priv->settings->burner);
840 	if (!medium)
841 		return 0;
842 
843 	max_rate = brasero_medium_get_max_write_speed (medium);
844 	if (priv->settings->rate <= 0)
845 		return max_rate;
846 	else
847 		return MIN (max_rate, priv->settings->rate);
848 }
849 
850 /**
851  * brasero_burn_session_get_output_type:
852  * @session: a #BraseroBurnSession
853  * @output: a #BraseroTrackType or NULL
854  *
855  * This function returns the type of output set for the session.
856  *
857  * Return value: a #BraseroBurnResult.
858  * BRASERO_BURN_OK if it was successful; BRASERO_BURN_NOT_READY if no setting has been set; BRASERO_BURN_ERR otherwise.
859  **/
860 BraseroBurnResult
brasero_burn_session_get_output_type(BraseroBurnSession * self,BraseroTrackType * output)861 brasero_burn_session_get_output_type (BraseroBurnSession *self,
862                                       BraseroTrackType *output)
863 {
864 	BraseroBurnSessionPrivate *priv;
865 
866 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
867 
868 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
869 	if (!priv->settings->burner)
870 		return BRASERO_BURN_NOT_READY;
871 
872 	if (brasero_drive_is_fake (priv->settings->burner)) {
873 		brasero_track_type_set_has_image (output);
874 		brasero_track_type_set_image_format (output, brasero_burn_session_get_output_format (self));
875 	}
876 	else {
877 		brasero_track_type_set_has_medium (output);
878 		brasero_track_type_set_medium_type (output, brasero_medium_get_status (brasero_drive_get_medium (priv->settings->burner)));
879 	}
880 
881 	return BRASERO_BURN_OK;
882 }
883 
884 /**
885  * brasero_burn_session_get_output:
886  * @session: a #BraseroBurnSession.
887  * @image: (allow-none) (out): a #gchar to store the image path or NULL.
888  * @toc: (allow-none) (out): a #gchar to store the toc path or NULL.
889  *
890  * When the contents of @session should be written to a
891  * file then this function returns the image path (and if
892  * necessary a toc path).
893  * @image and @toc should be freed if not used anymore.
894  *
895  * NOTE: before using this function a #BraseroDrive should have been
896  * set with brasero_burn_session_set_burner () and it should be the
897  * fake drive (see brasero_drive_is_fake ()).
898  *
899  * Return value: a #BraseroBurnResult.
900  * BRASERO_BURN_OK if it was successful; BRASERO_BURN_ERR otherwise.
901  **/
902 
903 BraseroBurnResult
brasero_burn_session_get_output(BraseroBurnSession * self,gchar ** image,gchar ** toc)904 brasero_burn_session_get_output (BraseroBurnSession *self,
905 				 gchar **image,
906 				 gchar **toc)
907 {
908 	BraseroBurnSessionClass *klass;
909 	BraseroBurnSessionPrivate *priv;
910 
911 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_IMAGE_FORMAT_NONE);
912 
913 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
914 	if (!BRASERO_BURN_SESSION_WRITE_TO_FILE (priv)) {
915 		BRASERO_BURN_LOG ("no file disc");
916 		return BRASERO_BURN_ERR;
917 	}
918 
919 	klass = BRASERO_BURN_SESSION_GET_CLASS (self);
920 	return klass->get_output_path (self, image, toc);
921 }
922 
923 
924 static BraseroBurnResult
brasero_burn_session_get_output_path_real(BraseroBurnSession * self,gchar ** image_ret,gchar ** toc_ret)925 brasero_burn_session_get_output_path_real (BraseroBurnSession *self,
926 					   gchar **image_ret,
927 					   gchar **toc_ret)
928 {
929 	gchar *toc = NULL;
930 	gchar *image = NULL;
931 	BraseroBurnSessionPrivate *priv;
932 
933 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
934 
935 	image = g_strdup (priv->settings->image);
936 	toc = g_strdup (priv->settings->toc);
937 	if (!image && !toc)
938 		return BRASERO_BURN_ERR;
939 
940 	if (image_ret) {
941 		/* output paths were set so test them and returns them if OK */
942 		if (!image && toc) {
943 			gchar *complement;
944 			BraseroImageFormat format;
945 
946 			/* get the cuesheet complement */
947 			format = brasero_burn_session_get_output_format (self);
948 			complement = brasero_image_format_get_complement (format, toc);
949 			if (!complement) {
950 				BRASERO_BURN_LOG ("no output specified");
951 				g_free (toc);
952 				return BRASERO_BURN_ERR;
953 			}
954 
955 			*image_ret = complement;
956 		}
957 		else if (image)
958 			*image_ret = image;
959 		else {
960 			BRASERO_BURN_LOG ("no output specified");
961 			return BRASERO_BURN_ERR;
962 		}
963 	}
964 	else
965 		g_free (image);
966 
967 	if (toc_ret)
968 		*toc_ret = toc;
969 	else
970 		g_free (toc);
971 
972 	return BRASERO_BURN_OK;
973 }
974 
975 /**
976  * brasero_burn_session_get_output_format:
977  * @session: a #BraseroBurnSession
978  *
979  * When the contents of @session should be written to a
980  * file then this function returns the format of the image to write.
981  *
982  * NOTE: before using this function a #BraseroDrive should have been
983  * set with brasero_burn_session_set_burner () and it should be the
984  * fake drive (see brasero_drive_is_fake ()).
985  *
986  * Return value: a #BraseroImageFormat. The format of the image to be written.
987  **/
988 
989 BraseroImageFormat
brasero_burn_session_get_output_format(BraseroBurnSession * self)990 brasero_burn_session_get_output_format (BraseroBurnSession *self)
991 {
992 	BraseroBurnSessionClass *klass;
993 	BraseroBurnSessionPrivate *priv;
994 
995 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_IMAGE_FORMAT_NONE);
996 
997 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
998 	if (!BRASERO_BURN_SESSION_WRITE_TO_FILE (priv))
999 		return BRASERO_IMAGE_FORMAT_NONE;
1000 
1001 	klass = BRASERO_BURN_SESSION_GET_CLASS (self);
1002 	return klass->get_output_format (self);
1003 }
1004 
1005 static BraseroImageFormat
brasero_burn_session_get_output_format_real(BraseroBurnSession * self)1006 brasero_burn_session_get_output_format_real (BraseroBurnSession *self)
1007 {
1008 	BraseroBurnSessionPrivate *priv;
1009 
1010 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1011 	return priv->settings->format;
1012 }
1013 
1014 /**
1015  * This function allows to tell where we should write the image. Depending on
1016  * the type of image it can be a toc (cue) or the path of the image (all others)
1017  */
1018 
1019 static void
brasero_burn_session_set_image_output_real(BraseroBurnSession * self,BraseroImageFormat format,const gchar * image,const gchar * toc)1020 brasero_burn_session_set_image_output_real (BraseroBurnSession *self,
1021 					    BraseroImageFormat format,
1022 					    const gchar *image,
1023 					    const gchar *toc)
1024 {
1025 	BraseroBurnSessionPrivate *priv;
1026 
1027 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1028 
1029 	if (priv->settings->image)
1030 		g_free (priv->settings->image);
1031 
1032 	if (image)
1033 		priv->settings->image = g_strdup (image);
1034 	else
1035 		priv->settings->image = NULL;
1036 
1037 	if (priv->settings->toc)
1038 		g_free (priv->settings->toc);
1039 
1040 	if (toc)
1041 		priv->settings->toc = g_strdup (toc);
1042 	else
1043 		priv->settings->toc = NULL;
1044 
1045 	priv->settings->format = format;
1046 }
1047 
1048 static void
brasero_burn_session_set_fake_drive(BraseroBurnSession * self)1049 brasero_burn_session_set_fake_drive (BraseroBurnSession *self)
1050 {
1051 	BraseroMediumMonitor *monitor;
1052 	BraseroDrive *drive;
1053 	GSList *list;
1054 
1055 	/* NOTE: changing/changed signals are handled in
1056 	 * set_burner (). */
1057 	monitor = brasero_medium_monitor_get_default ();
1058 	list = brasero_medium_monitor_get_media (monitor, BRASERO_MEDIA_TYPE_FILE);
1059 	drive = brasero_medium_get_drive (list->data);
1060 	brasero_burn_session_set_burner (self, drive);
1061 	g_object_unref (monitor);
1062 	g_slist_free (list);
1063 }
1064 
1065 static BraseroBurnResult
brasero_burn_session_set_output_image_real(BraseroBurnSession * self,BraseroImageFormat format,const gchar * image,const gchar * toc)1066 brasero_burn_session_set_output_image_real (BraseroBurnSession *self,
1067 					    BraseroImageFormat format,
1068 					    const gchar *image,
1069 					    const gchar *toc)
1070 {
1071 	BraseroBurnSessionPrivate *priv;
1072 
1073 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1074 
1075 	if (priv->settings->format == format
1076 	&&  BRASERO_STR_EQUAL (image, priv->settings->image)
1077 	&&  BRASERO_STR_EQUAL (toc, priv->settings->toc)) {
1078 		if (!BRASERO_BURN_SESSION_WRITE_TO_FILE (priv))
1079 			brasero_burn_session_set_fake_drive (self);
1080 
1081 		return BRASERO_BURN_OK;
1082 	}
1083 
1084 	brasero_burn_session_set_image_output_real (self, format, image, toc);
1085 	if (BRASERO_BURN_SESSION_WRITE_TO_FILE (priv))
1086 		g_signal_emit (self,
1087 			       brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL],
1088 			       0,
1089 			       brasero_drive_get_medium (priv->settings->burner));
1090 	else
1091 		brasero_burn_session_set_fake_drive (self);
1092 
1093 	return BRASERO_BURN_OK;
1094 }
1095 
1096 /**
1097  * brasero_burn_session_set_image_output_format:
1098  * @session: a #BraseroBurnSession
1099  * @format: a #BraseroImageFormat
1100  *
1101  * When the contents of @session should be written to a
1102  * file, this function sets format of the image that will be
1103  * created.
1104  *
1105  * NOTE: after a call to this function the #BraseroDrive for
1106  * @session will be the fake #BraseroDrive.
1107  *
1108  * Since 2.29.0
1109  *
1110  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if it was successfully set;
1111  * BRASERO_BURN_ERR otherwise.
1112  **/
1113 
1114 BraseroBurnResult
brasero_burn_session_set_image_output_format(BraseroBurnSession * self,BraseroImageFormat format)1115 brasero_burn_session_set_image_output_format (BraseroBurnSession *self,
1116 					    BraseroImageFormat format)
1117 {
1118 	BraseroBurnSessionClass *klass;
1119 	BraseroBurnSessionPrivate *priv;
1120 	BraseroBurnResult res;
1121 	gchar *image;
1122 	gchar *toc;
1123 
1124 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1125 
1126 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1127 	klass = BRASERO_BURN_SESSION_GET_CLASS (self);
1128 
1129 	image = g_strdup (priv->settings->image);
1130 	toc = g_strdup (priv->settings->toc);
1131 	res = klass->set_output_image (self, format, image, toc);
1132 	g_free (image);
1133 	g_free (toc);
1134 
1135 	return res;
1136 }
1137 
1138 /**
1139  * brasero_burn_session_set_image_output_full:
1140  * @session: a #BraseroBurnSession.
1141  * @format: a #BraseroImageFormat.
1142  * @image: (allow-none): a #gchar or NULL.
1143  * @toc: (allow-none): a #gchar or NULL.
1144  *
1145  * When the contents of @session should be written to a
1146  * file, this function sets the different parameters of this
1147  * image like its path (and the one of the associated toc if
1148  * necessary) and its format.
1149  *
1150  * NOTE: after a call to this function the #BraseroDrive for
1151  * @session will be the fake #BraseroDrive.
1152  *
1153  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if it was successfully set;
1154  * BRASERO_BURN_ERR otherwise.
1155  **/
1156 
1157 BraseroBurnResult
brasero_burn_session_set_image_output_full(BraseroBurnSession * self,BraseroImageFormat format,const gchar * image,const gchar * toc)1158 brasero_burn_session_set_image_output_full (BraseroBurnSession *self,
1159 					    BraseroImageFormat format,
1160 					    const gchar *image,
1161 					    const gchar *toc)
1162 {
1163 	BraseroBurnSessionClass *klass;
1164 
1165 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1166 
1167 	klass = BRASERO_BURN_SESSION_GET_CLASS (self);
1168 	return klass->set_output_image (self, format, image, toc);
1169 }
1170 
1171 /**
1172  * brasero_burn_session_set_tmpdir:
1173  * @session: a #BraseroBurnSession
1174  * @path: a #gchar or NULL
1175  *
1176  * Sets the path of the directory in which to write temporary directories and files.
1177  * If set to NULL then the result of g_get_tmp_dir () will be used.
1178  *
1179  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if it was successfully set;
1180  * BRASERO_BURN_ERR otherwise.
1181  **/
1182 
1183 BraseroBurnResult
brasero_burn_session_set_tmpdir(BraseroBurnSession * self,const gchar * path)1184 brasero_burn_session_set_tmpdir (BraseroBurnSession *self,
1185 				 const gchar *path)
1186 {
1187 	BraseroBurnSessionPrivate *priv;
1188 
1189 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1190 
1191 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1192 
1193 	if (!g_strcmp0 (priv->tmpdir, path))
1194 		return BRASERO_BURN_OK;
1195 
1196 	if (!path) {
1197 		g_free (priv->tmpdir);
1198 		priv->tmpdir = NULL;
1199 		g_object_notify (G_OBJECT (self), "tmpdir");
1200 		return BRASERO_BURN_OK;
1201 	}
1202 
1203 	if (!g_str_has_prefix (path, G_DIR_SEPARATOR_S))
1204 		return BRASERO_BURN_ERR;
1205 
1206 	g_free (priv->tmpdir);
1207 	priv->tmpdir = g_strdup (path);
1208 	g_object_notify (G_OBJECT (self), "tmpdir");
1209 
1210 	return BRASERO_BURN_OK;
1211 }
1212 
1213 /**
1214  * brasero_burn_session_get_tmpdir:
1215  * @session: a #BraseroBurnSession
1216  *
1217  * Returns the path of the directory in which to write temporary directories and files.
1218  *
1219  * Return value: a #gchar. The path to the temporary directory.
1220  **/
1221 
1222 const gchar *
brasero_burn_session_get_tmpdir(BraseroBurnSession * self)1223 brasero_burn_session_get_tmpdir (BraseroBurnSession *self)
1224 {
1225 	BraseroBurnSessionPrivate *priv;
1226 
1227 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
1228 
1229 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1230 	return priv->tmpdir? priv->tmpdir:g_get_tmp_dir ();
1231 }
1232 
1233 /**
1234  * brasero_burn_session_get_tmp_dir:
1235  * @session: a #BraseroBurnSession
1236  * @path: a #gchar or NULL
1237  * @error: a #GError
1238  *
1239  * Creates then returns (in @path) a temporary directory at the proper location.
1240  * On error, @error is set appropriately.
1241  * See brasero_burn_session_set_tmpdir ().
1242  * This function is used internally and is not public API.
1243  *
1244  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if it was successfully set;
1245  * BRASERO_BURN_ERR otherwise.
1246  **/
1247 
1248 BraseroBurnResult
brasero_burn_session_get_tmp_dir(BraseroBurnSession * self,gchar ** path,GError ** error)1249 brasero_burn_session_get_tmp_dir (BraseroBurnSession *self,
1250 				  gchar **path,
1251 				  GError **error)
1252 {
1253 	gchar *tmp;
1254 	const gchar *tmpdir;
1255 	BraseroBurnSessionPrivate *priv;
1256 
1257 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1258 
1259 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1260 
1261 	/* create a working directory in tmp */
1262 	tmpdir = priv->tmpdir ?
1263 		 priv->tmpdir :
1264 		 g_get_tmp_dir ();
1265 
1266 	tmp = g_build_path (G_DIR_SEPARATOR_S,
1267 			    tmpdir,
1268 			    BRASERO_BURN_TMP_FILE_NAME,
1269 			    NULL);
1270 
1271 	*path = g_mkdtemp (tmp);
1272 	if (*path == NULL) {
1273                 int errsv = errno;
1274 
1275 		BRASERO_BURN_LOG ("Impossible to create tmp directory");
1276 		g_free (tmp);
1277 		if (errsv != EACCES)
1278 			g_set_error (error,
1279 				     BRASERO_BURN_ERROR,
1280 				     BRASERO_BURN_ERROR_TMP_DIRECTORY,
1281 				     "%s",
1282 				     g_strerror (errsv));
1283 		else
1284 			g_set_error (error,
1285 				     BRASERO_BURN_ERROR,
1286 				     BRASERO_BURN_ERROR_TMP_DIRECTORY,
1287 				     _("You do not have the required permission to write at this location"));
1288 		return BRASERO_BURN_ERR;
1289 	}
1290 
1291 	/* this must be removed when session is completly unreffed */
1292 	priv->tmpfiles = g_slist_prepend (priv->tmpfiles, g_strdup (tmp));
1293 
1294 	return BRASERO_BURN_OK;
1295 }
1296 
1297 /**
1298  * brasero_burn_session_get_tmp_file:
1299  * @session: a #BraseroBurnSession
1300  * @suffix: a #gchar
1301  * @path: a #gchar or NULL
1302  * @error: a #GError
1303  *
1304  * Creates then returns (in @path) a temporary file at the proper location. Its name
1305  * will be appended with suffix.
1306  * On error, @error is set appropriately.
1307  * See brasero_burn_session_set_tmpdir ().
1308  * This function is used internally and is not public API.
1309  *
1310  * Return value: a #BraseroBurnResult. BRASERO_BURN_OK if it was successfully set;
1311  * BRASERO_BURN_ERR otherwise.
1312  **/
1313 
1314 BraseroBurnResult
brasero_burn_session_get_tmp_file(BraseroBurnSession * self,const gchar * suffix,gchar ** path,GError ** error)1315 brasero_burn_session_get_tmp_file (BraseroBurnSession *self,
1316 				   const gchar *suffix,
1317 				   gchar **path,
1318 				   GError **error)
1319 {
1320 	BraseroBurnSessionPrivate *priv;
1321 	const gchar *tmpdir;
1322 	gchar *name;
1323 	gchar *tmp;
1324 	int fd;
1325 
1326 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1327 
1328 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1329 
1330 	if (!path)
1331 		return BRASERO_BURN_OK;
1332 
1333 	/* takes care of the output file */
1334 	tmpdir = priv->tmpdir ?
1335 		 priv->tmpdir :
1336 		 g_get_tmp_dir ();
1337 
1338 	name = g_strconcat (BRASERO_BURN_TMP_FILE_NAME, suffix, NULL);
1339 	tmp = g_build_path (G_DIR_SEPARATOR_S,
1340 			    tmpdir,
1341 			    name,
1342 			    NULL);
1343 	g_free (name);
1344 
1345 	fd = g_mkstemp (tmp);
1346 	if (fd == -1) {
1347                 int errsv = errno;
1348 
1349 		BRASERO_BURN_LOG ("Impossible to create tmp file %s", tmp);
1350 
1351 		g_free (tmp);
1352 		if (errsv != EACCES)
1353 			g_set_error (error,
1354 				     BRASERO_BURN_ERROR,
1355 				     BRASERO_BURN_ERROR_TMP_DIRECTORY,
1356 				     "%s",
1357 				     g_strerror (errsv));
1358 		else
1359 			g_set_error (error,
1360 				     BRASERO_BURN_ERROR,
1361 				     BRASERO_BURN_ERROR_TMP_DIRECTORY,
1362 				     _("You do not have the required permission to write at this location"));
1363 
1364 		return BRASERO_BURN_ERR;
1365 	}
1366 
1367 	/* this must be removed when session is completly unreffed */
1368 	priv->tmpfiles = g_slist_prepend (priv->tmpfiles,
1369 					  g_strdup (tmp));
1370 
1371 	close (fd);
1372 	*path = tmp;
1373 	return BRASERO_BURN_OK;
1374 }
1375 
1376 static gchar *
brasero_burn_session_get_image_complement(BraseroBurnSession * self,BraseroImageFormat format,const gchar * path)1377 brasero_burn_session_get_image_complement (BraseroBurnSession *self,
1378 					   BraseroImageFormat format,
1379 					   const gchar *path)
1380 {
1381 	gchar *retval = NULL;
1382 
1383 	if (format == BRASERO_IMAGE_FORMAT_CLONE)
1384 		retval = g_strdup_printf ("%s.toc", path);
1385 	else if (format == BRASERO_IMAGE_FORMAT_CUE) {
1386 		if (g_str_has_suffix (path, ".bin"))
1387 			retval = g_strdup_printf ("%.*scue",
1388 						  (int) strlen (path) - 3,
1389 						  path);
1390 		else
1391 			retval = g_strdup_printf ("%s.cue", path);
1392 	}
1393 	else if (format == BRASERO_IMAGE_FORMAT_CDRDAO) {
1394 		if (g_str_has_suffix (path, ".bin"))
1395 			retval = g_strdup_printf ("%.*stoc",
1396 						  (int) strlen (path) - 3,
1397 						  path);
1398 		else
1399 			retval = g_strdup_printf ("%s.toc", path);
1400 	}
1401 	else
1402 		retval = NULL;
1403 
1404 	return retval;
1405 }
1406 
1407 /**
1408  * This function is used internally and is not public API
1409  */
1410 
1411 BraseroBurnResult
brasero_burn_session_get_tmp_image(BraseroBurnSession * self,BraseroImageFormat format,gchar ** image,gchar ** toc,GError ** error)1412 brasero_burn_session_get_tmp_image (BraseroBurnSession *self,
1413 				    BraseroImageFormat format,
1414 				    gchar **image,
1415 				    gchar **toc,
1416 				    GError **error)
1417 {
1418 	BraseroBurnSessionPrivate *priv;
1419 	BraseroBurnResult result;
1420 	gchar *complement = NULL;
1421 	gchar *path = NULL;
1422 
1423 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1424 
1425 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1426 
1427 	/* Image tmp file */
1428 	result = brasero_burn_session_get_tmp_file (self,
1429 						    (format == BRASERO_IMAGE_FORMAT_CLONE)? NULL:".bin",
1430 						    &path,
1431 						    error);
1432 	if (result != BRASERO_BURN_OK)
1433 		return result;
1434 
1435 	if (format != BRASERO_IMAGE_FORMAT_BIN) {
1436 		/* toc tmp file */
1437 		complement = brasero_burn_session_get_image_complement (self, format, path);
1438 		if (complement) {
1439 			/* That shouldn't happen ... */
1440 			if (g_file_test (complement, G_FILE_TEST_EXISTS)) {
1441 				g_free (complement);
1442 				return BRASERO_BURN_ERR;
1443 			}
1444 		}
1445 	}
1446 
1447 	if (complement)
1448 		priv->tmpfiles = g_slist_prepend (priv->tmpfiles,
1449 						  g_strdup (complement));
1450 
1451 	if (image)
1452 		*image = path;
1453 	else
1454 		g_free (path);
1455 
1456 	if (toc)
1457 		*toc = complement;
1458 	else
1459 		g_free (complement);
1460 
1461 	return BRASERO_BURN_OK;
1462 }
1463 
1464 /**
1465  * used to modify session flags.
1466  */
1467 
1468 /**
1469  * brasero_burn_session_set_flags:
1470  * @session: a #BraseroBurnSession
1471  * @flags: a #BraseroBurnFlag
1472  *
1473  * Replaces the current flags set in @session with @flags.
1474  *
1475  **/
1476 
1477 void
brasero_burn_session_set_flags(BraseroBurnSession * self,BraseroBurnFlag flags)1478 brasero_burn_session_set_flags (BraseroBurnSession *self,
1479 			        BraseroBurnFlag flags)
1480 {
1481 	BraseroBurnSessionPrivate *priv;
1482 
1483 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1484 
1485 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1486 	if (priv->settings->flags == flags)
1487 		return;
1488 
1489 	priv->settings->flags = flags;
1490 	g_object_notify (G_OBJECT (self), "flags");
1491 }
1492 
1493 /**
1494  * brasero_burn_session_add_flag:
1495  * @session: a #BraseroBurnSession
1496  * @flags: a #BraseroBurnFlag
1497  *
1498  * Merges the current flags set in @session with @flags.
1499  *
1500  **/
1501 
1502 void
brasero_burn_session_add_flag(BraseroBurnSession * self,BraseroBurnFlag flag)1503 brasero_burn_session_add_flag (BraseroBurnSession *self,
1504 			       BraseroBurnFlag flag)
1505 {
1506 	BraseroBurnSessionPrivate *priv;
1507 
1508 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1509 
1510 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1511 	if ((priv->settings->flags & flag) == flag)
1512 		return;
1513 
1514 	priv->settings->flags |= flag;
1515 	g_object_notify (G_OBJECT (self), "flags");
1516 }
1517 
1518 /**
1519  * brasero_burn_session_remove_flag:
1520  * @session: a #BraseroBurnSession
1521  * @flags: a #BraseroBurnFlag
1522  *
1523  * Removes @flags from the current flags set for @session.
1524  *
1525  **/
1526 
1527 void
brasero_burn_session_remove_flag(BraseroBurnSession * self,BraseroBurnFlag flag)1528 brasero_burn_session_remove_flag (BraseroBurnSession *self,
1529 				  BraseroBurnFlag flag)
1530 {
1531 	BraseroBurnSessionPrivate *priv;
1532 
1533 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1534 
1535 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1536 	if ((priv->settings->flags & flag) == 0)
1537 		return;
1538 
1539 	priv->settings->flags &= ~flag;
1540 	g_object_notify (G_OBJECT (self), "flags");
1541 }
1542 
1543 /**
1544  * brasero_burn_session_get_flags:
1545  * @session: a #BraseroBurnSession
1546  *
1547  * Returns the current flags set for @session.
1548  *
1549  * Return value: a #BraseroBurnFlag.
1550  **/
1551 
1552 BraseroBurnFlag
brasero_burn_session_get_flags(BraseroBurnSession * self)1553 brasero_burn_session_get_flags (BraseroBurnSession *self)
1554 {
1555 	BraseroBurnSessionPrivate *priv;
1556 
1557 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1558 
1559 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1560 	return priv->settings->flags;
1561 }
1562 
1563 /**
1564  * Used to set the label or the title of an album.
1565  */
1566 
1567 /**
1568  * brasero_burn_session_set_label:
1569  * @session: a #BraseroBurnSession
1570  * @label: (allow-none): a #gchar or %NULL
1571  *
1572  * Sets the label for @session.
1573  *
1574  **/
1575 
1576 void
brasero_burn_session_set_label(BraseroBurnSession * self,const gchar * label)1577 brasero_burn_session_set_label (BraseroBurnSession *self,
1578 				const gchar *label)
1579 {
1580 	BraseroBurnSessionPrivate *priv;
1581 
1582 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1583 
1584 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1585 	if (priv->settings->label)
1586 		g_free (priv->settings->label);
1587 
1588 	priv->settings->label = NULL;
1589 
1590 	if (label) {
1591 		if (strlen (label) > 32) {
1592 			const gchar *delim;
1593 			gchar *next_char;
1594 
1595 			/* find last possible character. We can't just do a tmp
1596 			 * + 32 since we don't know if we are at the start of a
1597 			 * character */
1598 			delim = label;
1599 			while ((next_char = g_utf8_find_next_char (delim, NULL))) {
1600 				if (next_char - label > 32)
1601 					break;
1602 
1603 				delim = next_char;
1604 			}
1605 
1606 			priv->settings->label = g_strndup (label, delim - label);
1607 		}
1608 		else
1609 			priv->settings->label = g_strdup (label);
1610 	}
1611 }
1612 
1613 /**
1614  * brasero_burn_session_get_label:
1615  * @session: a #BraseroBurnSession
1616  *
1617  * Returns the label (a string) set for @session.
1618  *
1619  * Return value: a #gchar or NULL. Do not free after use.
1620  **/
1621 
1622 const gchar *
brasero_burn_session_get_label(BraseroBurnSession * self)1623 brasero_burn_session_get_label (BraseroBurnSession *self)
1624 {
1625 	BraseroBurnSessionPrivate *priv;
1626 
1627 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
1628 
1629 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1630 	return priv->settings->label;
1631 }
1632 
1633 static void
brasero_burn_session_tag_value_free(gpointer user_data)1634 brasero_burn_session_tag_value_free (gpointer user_data)
1635 {
1636 	GValue *value = user_data;
1637 
1638 	g_value_reset (value);
1639 	g_free (value);
1640 }
1641 
1642 /**
1643  * brasero_burn_session_tag_remove:
1644  * @session: a #BraseroBurnSession
1645  * @tag: a #gchar *
1646  *
1647  * Removes a value associated with @session through
1648  * brasero_session_tag_add ().
1649  *
1650  * Return value: a #BraseroBurnResult.
1651  * BRASERO_BURN_OK if the retrieval was successful
1652  * BRASERO_BURN_ERR otherwise
1653  **/
1654 
1655 BraseroBurnResult
brasero_burn_session_tag_remove(BraseroBurnSession * self,const gchar * tag)1656 brasero_burn_session_tag_remove (BraseroBurnSession *self,
1657 				 const gchar *tag)
1658 {
1659 	BraseroBurnSessionPrivate *priv;
1660 
1661 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1662 	g_return_val_if_fail (tag != NULL, BRASERO_BURN_ERR);
1663 
1664 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1665 	if (!priv->tags)
1666 		return BRASERO_BURN_ERR;
1667 
1668 	g_hash_table_remove (priv->tags, tag);
1669 
1670 	g_signal_emit (self,
1671 	               brasero_burn_session_signals [TAG_CHANGED_SIGNAL],
1672 	               0,
1673 	               tag);
1674 	return BRASERO_BURN_OK;
1675 }
1676 
1677 /**
1678  * brasero_burn_session_tag_add:
1679  * @session: a #BraseroBurnSession
1680  * @tag: a #gchar *
1681  * @value: a #GValue *
1682  *
1683  * Associates a new @tag with @session. This can be used
1684  * to pass arbitrary information for plugins, like parameters
1685  * for video discs, ...
1686  * NOTE: the #BraseroBurnSession object takes ownership of @value.
1687  * See brasero-tags.h for a list of knowns tags.
1688  *
1689  * Return value: a #BraseroBurnResult.
1690  * BRASERO_BURN_OK if it was successful,
1691  * BRASERO_BURN_ERR otherwise.
1692  **/
1693 
1694 BraseroBurnResult
brasero_burn_session_tag_add(BraseroBurnSession * self,const gchar * tag,GValue * value)1695 brasero_burn_session_tag_add (BraseroBurnSession *self,
1696 			      const gchar *tag,
1697 			      GValue *value)
1698 {
1699 	BraseroBurnSessionPrivate *priv;
1700 
1701 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1702 	g_return_val_if_fail (tag != NULL, BRASERO_BURN_ERR);
1703 
1704 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1705 	if (!priv->tags)
1706 		priv->tags = g_hash_table_new_full (g_str_hash,
1707 						    g_str_equal,
1708 						    g_free,
1709 						    brasero_burn_session_tag_value_free);
1710 	g_hash_table_insert (priv->tags, g_strdup (tag), value);
1711 	g_signal_emit (self,
1712 	               brasero_burn_session_signals [TAG_CHANGED_SIGNAL],
1713 	               0,
1714 	               tag);
1715 
1716 	return BRASERO_BURN_OK;
1717 }
1718 
1719 /**
1720  * brasero_burn_session_tag_add_int:
1721  * @session: a #BraseroBurnSession
1722  * @tag: a #gchar *
1723  * @value: a #gint
1724  *
1725  * Associates a new @tag with @session. This can be used
1726  * to pass arbitrary information for plugins, like parameters
1727  * for video discs, ...
1728  * See brasero-tags.h for a list of knowns tags.
1729  *
1730  * Since 2.29.0
1731  *
1732  * Return value: a #BraseroBurnResult.
1733  * BRASERO_BURN_OK if it was successful,
1734  * BRASERO_BURN_ERR otherwise.
1735  **/
1736 
1737 BraseroBurnResult
brasero_burn_session_tag_add_int(BraseroBurnSession * self,const gchar * tag,gint value)1738 brasero_burn_session_tag_add_int (BraseroBurnSession *self,
1739                                   const gchar *tag,
1740                                   gint value)
1741 {
1742 	GValue *gvalue;
1743 
1744 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1745 	g_return_val_if_fail (tag != NULL, BRASERO_BURN_ERR);
1746 
1747 	gvalue = g_new0 (GValue, 1);
1748 	g_value_init (gvalue, G_TYPE_INT);
1749 	g_value_set_int (gvalue, value);
1750 
1751 	return brasero_burn_session_tag_add (self, tag, gvalue);
1752 }
1753 
1754 /**
1755  * brasero_burn_session_tag_lookup:
1756  * @session: a #BraseroBurnSession
1757  * @tag: a #gchar *
1758  * @value: a #GValue
1759  *
1760  * Retrieves a value associated with @session through
1761  * brasero_session_tag_add () and stores it in @value. Do
1762  * not destroy @value afterwards as it is not a copy.
1763  *
1764  * Return value: a #BraseroBurnResult.
1765  * BRASERO_BURN_OK if the retrieval was successful
1766  * BRASERO_BURN_ERR otherwise
1767  **/
1768 
1769 BraseroBurnResult
brasero_burn_session_tag_lookup(BraseroBurnSession * self,const gchar * tag,GValue ** value)1770 brasero_burn_session_tag_lookup (BraseroBurnSession *self,
1771 				 const gchar *tag,
1772 				 GValue **value)
1773 {
1774 	BraseroBurnSessionPrivate *priv;
1775 	gpointer data;
1776 
1777 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_BURN_ERR);
1778 	g_return_val_if_fail (tag != NULL, BRASERO_BURN_ERR);
1779 
1780 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1781 	if (!value)
1782 		return BRASERO_BURN_ERR;
1783 
1784 	if (!priv->tags)
1785 		return BRASERO_BURN_ERR;
1786 
1787 	data = g_hash_table_lookup (priv->tags, tag);
1788 	if (!data)
1789 		return BRASERO_BURN_ERR;
1790 
1791 	/* value can be NULL if the function was just called
1792 	 * to check whether a tag was set. */
1793 	if (value)
1794 		*value = data;
1795 	return BRASERO_BURN_OK;
1796 }
1797 
1798 /**
1799  * brasero_burn_session_tag_lookup_int:
1800  * @session: a #BraseroBurnSession
1801  * @tag: a #gchar
1802  *
1803  * Retrieves an int value associated with @session through
1804  * brasero_session_tag_add () and returns it.
1805  *
1806  * Since 2.29.0
1807  *
1808  * Return value: a #gint.
1809  **/
1810 
1811 gint
brasero_burn_session_tag_lookup_int(BraseroBurnSession * self,const gchar * tag)1812 brasero_burn_session_tag_lookup_int (BraseroBurnSession *self,
1813                                      const gchar *tag)
1814 {
1815 	GValue *value = NULL;
1816 
1817 	brasero_burn_session_tag_lookup (self, tag, &value);
1818 	if (!value || !G_VALUE_HOLDS_INT (value))
1819 		return 0;
1820 
1821 	return g_value_get_int (value);
1822 }
1823 
1824 /**
1825  * Used to save and restore settings/sources
1826  */
1827 
1828 void
brasero_burn_session_push_settings(BraseroBurnSession * self)1829 brasero_burn_session_push_settings (BraseroBurnSession *self)
1830 {
1831 	BraseroSessionSetting *settings;
1832 	BraseroBurnSessionPrivate *priv;
1833 
1834 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1835 
1836 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1837 
1838 	/* NOTE: don't clean the settings so no need to issue a signal */
1839 	settings = g_new0 (BraseroSessionSetting, 1);
1840 	brasero_session_settings_copy (settings, priv->settings);
1841 	priv->pile_settings = g_slist_prepend (priv->pile_settings, settings);
1842 }
1843 
1844 void
brasero_burn_session_pop_settings(BraseroBurnSession * self)1845 brasero_burn_session_pop_settings (BraseroBurnSession *self)
1846 {
1847 	BraseroSessionSetting *settings;
1848 	BraseroBurnSessionPrivate *priv;
1849 	BraseroMedium *former;
1850 
1851 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1852 
1853 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1854 
1855 	if (!priv->pile_settings)
1856 		return;
1857 
1858 	if (priv->dest_added_sig) {
1859 		g_signal_handler_disconnect (priv->settings->burner,
1860 					     priv->dest_added_sig);
1861 		priv->dest_added_sig = 0;
1862 	}
1863 
1864 	if (priv->dest_removed_sig) {
1865 		g_signal_handler_disconnect (priv->settings->burner,
1866 					     priv->dest_removed_sig);
1867 		priv->dest_removed_sig = 0;
1868 	}
1869 
1870 	former = brasero_drive_get_medium (priv->settings->burner);
1871 	if (former)
1872 		former = g_object_ref (former);
1873 
1874 	brasero_session_settings_clean (priv->settings);
1875 
1876 	settings = priv->pile_settings->data;
1877 	priv->pile_settings = g_slist_remove (priv->pile_settings, settings);
1878 	brasero_session_settings_copy (priv->settings, settings);
1879 
1880 	brasero_session_settings_free (settings);
1881 	if (priv->settings->burner) {
1882 		priv->dest_added_sig = g_signal_connect (priv->settings->burner,
1883 							 "medium-added",
1884 							 G_CALLBACK (brasero_burn_session_dest_media_added),
1885 							 self);
1886 		priv->dest_removed_sig = g_signal_connect (priv->settings->burner,
1887 							   "medium-removed",
1888 							   G_CALLBACK (brasero_burn_session_dest_media_removed),
1889 							   self);
1890 	}
1891 
1892 	g_signal_emit (self,
1893 		       brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL],
1894 		       0,
1895 		       former);
1896 
1897 	if (former)
1898 		g_object_unref (former);
1899 }
1900 
1901 void
brasero_burn_session_push_tracks(BraseroBurnSession * self)1902 brasero_burn_session_push_tracks (BraseroBurnSession *self)
1903 {
1904 	BraseroBurnSessionPrivate *priv;
1905 	GSList *iter;
1906 
1907 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
1908 
1909 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1910 
1911 	brasero_burn_session_stop_tracks_monitoring (self);
1912 
1913 	priv->pile_tracks = g_slist_prepend (priv->pile_tracks, priv->tracks);
1914 	iter = priv->tracks;
1915 	priv->tracks = NULL;
1916 
1917 	for (; iter; iter = iter->next) {
1918 		BraseroTrack *track;
1919 
1920 		track = iter->data;
1921 		g_signal_emit (self,
1922 			       brasero_burn_session_signals [TRACK_REMOVED_SIGNAL],
1923 			       0,
1924 			       track,
1925 			       0);
1926 	}
1927 }
1928 
1929 BraseroBurnResult
brasero_burn_session_pop_tracks(BraseroBurnSession * self)1930 brasero_burn_session_pop_tracks (BraseroBurnSession *self)
1931 {
1932 	GSList *sources;
1933 	BraseroBurnSessionPrivate *priv;
1934 
1935 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), FALSE);
1936 
1937 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1938 
1939 	/* Don't go further if there is no list of tracks on the pile */
1940 	if (!priv->pile_tracks)
1941 		return BRASERO_BURN_OK;
1942 
1943 	if (priv->tracks)
1944 		brasero_burn_session_free_tracks (self);
1945 
1946 	sources = priv->pile_tracks->data;
1947 	priv->pile_tracks = g_slist_remove (priv->pile_tracks, sources);
1948 	priv->tracks = sources;
1949 
1950 	for (; sources; sources = sources->next) {
1951 		BraseroTrack *track;
1952 
1953 		track = sources->data;
1954 		brasero_burn_session_start_track_monitoring (self, track);
1955 		g_signal_emit (self,
1956 			       brasero_burn_session_signals [TRACK_ADDED_SIGNAL],
1957 			       0,
1958 			       track);
1959 	}
1960 
1961 	return BRASERO_BURN_RETRY;
1962 }
1963 
1964 gboolean
brasero_burn_session_is_dest_file(BraseroBurnSession * self)1965 brasero_burn_session_is_dest_file (BraseroBurnSession *self)
1966 {
1967 	BraseroBurnSessionPrivate *priv;
1968 
1969 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), FALSE);
1970 
1971 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1972 	return BRASERO_BURN_SESSION_WRITE_TO_FILE (priv);
1973 }
1974 
1975 BraseroMedia
brasero_burn_session_get_dest_media(BraseroBurnSession * self)1976 brasero_burn_session_get_dest_media (BraseroBurnSession *self)
1977 {
1978 	BraseroBurnSessionPrivate *priv;
1979 	BraseroMedium *medium;
1980 
1981 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), BRASERO_MEDIUM_NONE);
1982 
1983 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
1984 
1985 	if (BRASERO_BURN_SESSION_WRITE_TO_FILE (priv))
1986 		return BRASERO_MEDIUM_FILE;
1987 
1988 	medium = brasero_drive_get_medium (priv->settings->burner);
1989 
1990 	return brasero_medium_get_status (medium);
1991 }
1992 
1993 /**
1994  * brasero_burn_session_get_available_medium_space:
1995  * @session: a #BraseroBurnSession
1996  *
1997  * Returns the maximum space available for the
1998  * medium currently inserted in the #BraseroDrive
1999  * set as burner with brasero_burn_session_set_burner ().
2000  * This takes into account flags.
2001  *
2002  * Return value: a #goffset.
2003  **/
2004 
2005 goffset
brasero_burn_session_get_available_medium_space(BraseroBurnSession * session)2006 brasero_burn_session_get_available_medium_space (BraseroBurnSession *session)
2007 {
2008 	BraseroDrive *burner;
2009 	BraseroBurnFlag flags;
2010 	BraseroMedium *medium;
2011 	goffset available_blocks = 0;
2012 
2013 	/* Retrieve the size available for burning */
2014 	burner = brasero_burn_session_get_burner (session);
2015 	if (!burner)
2016 		return 0;
2017 
2018 	medium = brasero_drive_get_medium (burner);
2019 	if (!medium)
2020 		return 0;
2021 
2022 	flags = brasero_burn_session_get_flags (session);
2023 	if (flags & (BRASERO_BURN_FLAG_MERGE|BRASERO_BURN_FLAG_APPEND))
2024 		brasero_medium_get_free_space (medium, NULL, &available_blocks);
2025 	else if (brasero_burn_session_can_blank (session) == BRASERO_BURN_OK)
2026 		brasero_medium_get_capacity (medium, NULL, &available_blocks);
2027 	else
2028 		brasero_medium_get_free_space (medium, NULL, &available_blocks);
2029 
2030 	BRASERO_BURN_LOG ("Available space on medium %" G_GINT64_FORMAT, available_blocks);
2031 	return available_blocks;
2032 }
2033 
2034 BraseroMedium *
brasero_burn_session_get_src_medium(BraseroBurnSession * self)2035 brasero_burn_session_get_src_medium (BraseroBurnSession *self)
2036 {
2037 	BraseroTrack *track;
2038 	BraseroDrive *drive;
2039 	BraseroBurnSessionPrivate *priv;
2040 
2041 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
2042 
2043 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2044 
2045 	/* to be able to burn to a DVD we must:
2046 	 * - have only one track
2047 	 * - not have any audio track */
2048 
2049 	if (!priv->tracks)
2050 		return NULL;
2051 
2052 	if (g_slist_length (priv->tracks) != 1)
2053 		return NULL;
2054 
2055 	track = priv->tracks->data;
2056 	if (!BRASERO_IS_TRACK_DISC (track))
2057 		return NULL;
2058 
2059 	drive = brasero_track_disc_get_drive (BRASERO_TRACK_DISC (track));
2060 	return brasero_drive_get_medium (drive);
2061 }
2062 
2063 BraseroDrive *
brasero_burn_session_get_src_drive(BraseroBurnSession * self)2064 brasero_burn_session_get_src_drive (BraseroBurnSession *self)
2065 {
2066 	BraseroTrack *track;
2067 	BraseroBurnSessionPrivate *priv;
2068 
2069 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
2070 
2071 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2072 
2073 	/* to be able to burn to a DVD we must:
2074 	 * - have only one track
2075 	 * - not have any audio track */
2076 
2077 	if (!priv->tracks)
2078 		return NULL;
2079 
2080 	if (g_slist_length (priv->tracks) != 1)
2081 		return NULL;
2082 
2083 	track = priv->tracks->data;
2084 	if (!BRASERO_IS_TRACK_DISC (track))
2085 		return NULL;
2086 
2087 	return brasero_track_disc_get_drive (BRASERO_TRACK_DISC (track));
2088 }
2089 
2090 gboolean
brasero_burn_session_same_src_dest_drive(BraseroBurnSession * self)2091 brasero_burn_session_same_src_dest_drive (BraseroBurnSession *self)
2092 {
2093 	BraseroTrack *track;
2094 	BraseroDrive *drive;
2095 	BraseroBurnSessionPrivate *priv;
2096 
2097 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), FALSE);
2098 
2099 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2100 
2101 	/* to be able to burn to a DVD we must:
2102 	 * - have only one track
2103 	 * - not have any audio track
2104 	 */
2105 
2106 	if (!priv->tracks)
2107 		return FALSE;
2108 
2109 	if (g_slist_length (priv->tracks) > 1)
2110 		return FALSE;
2111 
2112 	track = priv->tracks->data;
2113 	if (!BRASERO_IS_TRACK_DISC (track))
2114 		return FALSE;
2115 
2116 	drive = brasero_track_disc_get_drive (BRASERO_TRACK_DISC (track));
2117 	if (!drive)
2118 		return FALSE;
2119 
2120 	return (priv->settings->burner == drive);
2121 }
2122 
2123 
2124 /****************************** this part is for log ***************************/
2125 void
brasero_burn_session_logv(BraseroBurnSession * self,const gchar * format,va_list arg_list)2126 brasero_burn_session_logv (BraseroBurnSession *self,
2127 			   const gchar *format,
2128 			   va_list arg_list)
2129 {
2130 	int len;
2131 	int wlen;
2132 	gchar *message;
2133 	gchar *offending;
2134 	BraseroBurnSessionPrivate *priv;
2135 
2136 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
2137 
2138 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2139 
2140 	if (!format)
2141 		return;
2142 
2143 	if (!priv->session)
2144 		return;
2145 
2146 	message = g_strdup_vprintf (format, arg_list);
2147 
2148 	/* we also need to validate the messages to be in UTF-8 */
2149 	if (!g_utf8_validate (message, -1, (const gchar**) &offending))
2150 		*offending = '\0';
2151 
2152 	len = strlen (message);
2153 	wlen = write (priv->session, message, len);
2154 	if (wlen != len) {
2155 		int errnum = errno;
2156 
2157 		g_warning ("Some log data couldn't be written: %s (%i out of %i) (%s)\n",
2158 		           message, wlen, len,
2159 		           strerror (errnum));
2160 	}
2161 
2162 	g_free (message);
2163 
2164 	if (write (priv->session, "\n", 1) != 1)
2165 		g_warning ("Some log data could not be written");
2166 }
2167 
2168 void
brasero_burn_session_log(BraseroBurnSession * self,const gchar * format,...)2169 brasero_burn_session_log (BraseroBurnSession *self,
2170 			  const gchar *format,
2171 			  ...)
2172 {
2173 	va_list args;
2174 
2175 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
2176 
2177 	va_start (args, format);
2178 	brasero_burn_session_logv (self, format, args);
2179 	va_end (args);
2180 }
2181 
2182 const gchar *
brasero_burn_session_get_log_path(BraseroBurnSession * self)2183 brasero_burn_session_get_log_path (BraseroBurnSession *self)
2184 {
2185 	BraseroBurnSessionPrivate *priv;
2186 
2187 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), NULL);
2188 
2189 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2190 	return priv->session_path;
2191 }
2192 
2193 gboolean
brasero_burn_session_start(BraseroBurnSession * self)2194 brasero_burn_session_start (BraseroBurnSession *self)
2195 {
2196 	BraseroTrackType *type = NULL;
2197 	BraseroBurnSessionPrivate *priv;
2198 
2199 	g_return_val_if_fail (BRASERO_IS_BURN_SESSION (self), FALSE);
2200 
2201 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2202 
2203 	/* This must obey the path of the temporary directory if possible */
2204 	priv->session_path = g_build_path (G_DIR_SEPARATOR_S,
2205 					   priv->tmpdir,
2206 					   BRASERO_BURN_TMP_FILE_NAME,
2207 					   NULL);
2208 	priv->session = g_mkstemp_full (priv->session_path,
2209 	                                O_CREAT|O_WRONLY,
2210 	                                S_IRWXU);
2211 
2212 	if (priv->session < 0) {
2213 		g_free (priv->session_path);
2214 
2215 		priv->session_path = g_build_path (G_DIR_SEPARATOR_S,
2216 						   g_get_tmp_dir (),
2217 						   BRASERO_BURN_TMP_FILE_NAME,
2218 						   NULL);
2219 		priv->session = g_mkstemp_full (priv->session_path,
2220 		                                O_CREAT|O_WRONLY,
2221 		                                S_IRWXU);
2222 	}
2223 
2224 	if (priv->session < 0) {
2225 		g_free (priv->session_path);
2226 		priv->session_path = NULL;
2227 
2228 		g_warning ("Impossible to open a session file\n");
2229 		return FALSE;
2230 	}
2231 
2232 	BRASERO_BURN_LOG ("Session starting:");
2233 
2234 	type = brasero_track_type_new ();
2235 	brasero_burn_session_get_input_type (self, type);
2236 
2237 	BRASERO_BURN_LOG_TYPE (type, "Input\t=");
2238 	BRASERO_BURN_LOG_FLAGS (priv->settings->flags, "flags\t=");
2239 
2240 	/* also try all known tags */
2241 	if (brasero_track_type_get_has_stream (type)
2242 	&&  BRASERO_STREAM_FORMAT_HAS_VIDEO (brasero_track_type_get_stream_format (type))) {
2243 		GValue *value;
2244 
2245 		BRASERO_BURN_LOG ("Tags set:");
2246 
2247 		value = NULL;
2248 		brasero_burn_session_tag_lookup (self,
2249 						 BRASERO_DVD_STREAM_FORMAT,
2250 						 &value);
2251 		if (value)
2252 			BRASERO_BURN_LOG ("Stream format %i", g_value_get_int (value));
2253 
2254 		value = NULL;
2255 		brasero_burn_session_tag_lookup (self,
2256 						 BRASERO_VCD_TYPE,
2257 						 &value);
2258 		if (value)
2259 			BRASERO_BURN_LOG ("(S)VCD type %i", g_value_get_int (value));
2260 
2261 		value = NULL;
2262 		brasero_burn_session_tag_lookup (self,
2263 						 BRASERO_VIDEO_OUTPUT_FRAMERATE,
2264 						 &value);
2265 		if (value)
2266 			BRASERO_BURN_LOG ("Framerate %i", g_value_get_int (value));
2267 
2268 		value = NULL;
2269 		brasero_burn_session_tag_lookup (self,
2270 						 BRASERO_VIDEO_OUTPUT_ASPECT,
2271 						 &value);
2272 		if (value)
2273 			BRASERO_BURN_LOG ("Aspect %i", g_value_get_int (value));
2274 	}
2275 
2276 	if (!brasero_burn_session_is_dest_file (self)) {
2277 		BraseroMedium *medium;
2278 
2279 		medium = brasero_drive_get_medium (priv->settings->burner);
2280 		BRASERO_BURN_LOG_DISC_TYPE (brasero_medium_get_status (medium), "media type\t=");
2281 		BRASERO_BURN_LOG ("speed\t= %i", priv->settings->rate);
2282 	}
2283 	else {
2284 		brasero_track_type_set_has_image (type);
2285 		brasero_track_type_set_image_format (type, brasero_burn_session_get_output_format (self));
2286 		BRASERO_BURN_LOG_TYPE (type, "output format\t=");
2287 	}
2288 
2289 	brasero_track_type_free (type);
2290 
2291 	return TRUE;
2292 }
2293 
2294 void
brasero_burn_session_stop(BraseroBurnSession * self)2295 brasero_burn_session_stop (BraseroBurnSession *self)
2296 {
2297 	BraseroBurnSessionPrivate *priv;
2298 
2299 	g_return_if_fail (BRASERO_IS_BURN_SESSION (self));
2300 
2301 	priv = BRASERO_BURN_SESSION_PRIVATE (self);
2302 	if (priv->session > 0) {
2303 		close (priv->session);
2304 		priv->session = -1;
2305 	}
2306 
2307 	if (priv->session_path) {
2308 		g_free (priv->session_path);
2309 		priv->session_path = NULL;
2310 	}
2311 }
2312 
2313 static void
brasero_burn_session_track_list_free(GSList * list)2314 brasero_burn_session_track_list_free (GSList *list)
2315 {
2316 	g_slist_foreach (list, (GFunc) g_object_unref, NULL);
2317 	g_slist_free (list);
2318 }
2319 
2320 /**
2321  * Utility to clean tmp files
2322  */
2323 
2324 static gboolean
2325 brasero_burn_session_clean (const gchar *path);
2326 
2327 static gboolean
brasero_burn_session_clean_directory(const gchar * path)2328 brasero_burn_session_clean_directory (const gchar *path)
2329 {
2330 	GDir *dir;
2331 	const gchar *name;
2332 
2333 	dir = g_dir_open (path, 0, NULL);
2334 	if (!dir)
2335 		return FALSE;
2336 
2337 	while ((name = g_dir_read_name (dir))) {
2338 		gchar *tmp;
2339 
2340 		tmp = g_build_filename (G_DIR_SEPARATOR_S,
2341 					path,
2342 					name,
2343 					NULL);
2344 
2345 		if (!brasero_burn_session_clean (tmp)) {
2346 			g_dir_close (dir);
2347 			g_free (tmp);
2348 			return FALSE;
2349 		}
2350 
2351 		g_free (tmp);
2352 	}
2353 
2354 	g_dir_close (dir);
2355 	return TRUE;
2356 }
2357 
2358 static gboolean
brasero_burn_session_clean(const gchar * path)2359 brasero_burn_session_clean (const gchar *path)
2360 {
2361 	gboolean result = TRUE;
2362 
2363 	if (!path)
2364 		return TRUE;
2365 
2366 	BRASERO_BURN_LOG ("Cleaning %s", path);
2367 
2368 	/* NOTE: g_file_test follows symbolic links */
2369 	if (g_file_test (path, G_FILE_TEST_IS_DIR)
2370 	&& !g_file_test (path, G_FILE_TEST_IS_SYMLINK))
2371 		brasero_burn_session_clean_directory (path);
2372 
2373 	/* NOTE : we don't follow paths as certain files are simply linked */
2374 	if (g_remove (path)) {
2375 		BRASERO_BURN_LOG ("Cannot remove file %s (%s)", path, g_strerror (errno));
2376 		result = FALSE;
2377 	}
2378 
2379 	return result;
2380 }
2381 
2382 static void
brasero_burn_session_finalize(GObject * object)2383 brasero_burn_session_finalize (GObject *object)
2384 {
2385 	BraseroBurnSessionPrivate *priv;
2386 	GSList *iter;
2387 
2388 	BRASERO_BURN_LOG ("Cleaning session");
2389 
2390 	priv = BRASERO_BURN_SESSION_PRIVATE (object);
2391 
2392 	if (priv->tags) {
2393 		g_hash_table_destroy (priv->tags);
2394 		priv->tags = NULL;
2395 	}
2396 
2397 	if (priv->dest_added_sig) {
2398 		g_signal_handler_disconnect (priv->settings->burner,
2399 					     priv->dest_added_sig);
2400 		priv->dest_added_sig = 0;
2401 	}
2402 
2403 	if (priv->dest_removed_sig) {
2404 		g_signal_handler_disconnect (priv->settings->burner,
2405 					     priv->dest_removed_sig);
2406 		priv->dest_removed_sig = 0;
2407 	}
2408 
2409 	brasero_burn_session_stop_tracks_monitoring (BRASERO_BURN_SESSION (object));
2410 
2411 	if (priv->pile_tracks) {
2412 		g_slist_foreach (priv->pile_tracks,
2413 				(GFunc) brasero_burn_session_track_list_free,
2414 				NULL);
2415 
2416 		g_slist_free (priv->pile_tracks);
2417 		priv->pile_tracks = NULL;
2418 	}
2419 
2420 	if (priv->tracks) {
2421 		g_slist_foreach (priv->tracks,
2422 				 (GFunc) g_object_unref,
2423 				 NULL);
2424 		g_slist_free (priv->tracks);
2425 		priv->tracks = NULL;
2426 	}
2427 
2428 	if (priv->pile_settings) {
2429 		g_slist_foreach (priv->pile_settings,
2430 				(GFunc) brasero_session_settings_free,
2431 				NULL);
2432 		g_slist_free (priv->pile_settings);
2433 		priv->pile_settings = NULL;
2434 	}
2435 
2436 	if (priv->tmpdir) {
2437 		g_free (priv->tmpdir);
2438 		priv->tmpdir = NULL;
2439 	}
2440 
2441 	/* clean tmpfiles */
2442 	for (iter = priv->tmpfiles; iter; iter = iter->next) {
2443 		gchar *tmpfile;
2444 
2445 		tmpfile = iter->data;
2446 
2447 		brasero_burn_session_clean (tmpfile);
2448 		g_free (tmpfile);
2449 	}
2450 	g_slist_free (priv->tmpfiles);
2451 
2452 	if (priv->session > 0) {
2453 		close (priv->session);
2454 		priv->session = -1;
2455 	}
2456 
2457 	if (priv->session_path) {
2458 		g_remove (priv->session_path);
2459 		g_free (priv->session_path);
2460 		priv->session_path = NULL;
2461 	}
2462 
2463 	brasero_session_settings_clean (priv->settings);
2464 
2465 	G_OBJECT_CLASS (parent_class)->finalize (object);
2466 }
2467 
2468 static void
brasero_burn_session_init(BraseroBurnSession * obj)2469 brasero_burn_session_init (BraseroBurnSession *obj)
2470 {
2471 	BraseroBurnSessionPrivate *priv;
2472 
2473 	priv = BRASERO_BURN_SESSION_PRIVATE (obj);
2474 	priv->session = -1;
2475 }
2476 
2477 static void
brasero_burn_session_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2478 brasero_burn_session_set_property (GObject *object,
2479                                    guint prop_id,
2480                                    const GValue *value,
2481                                    GParamSpec *pspec)
2482 {
2483 	g_return_if_fail (BRASERO_IS_BURN_SESSION (object));
2484 
2485 	switch (prop_id)
2486 	{
2487 	case PROP_TMPDIR:
2488 		brasero_burn_session_set_tmpdir (BRASERO_BURN_SESSION (object),
2489 		                                 g_value_get_string (value));
2490 		break;
2491 	case PROP_RATE:
2492 		brasero_burn_session_set_rate (BRASERO_BURN_SESSION (object),
2493 		                               g_value_get_int64 (value));
2494 		break;
2495 	case PROP_FLAGS:
2496 		brasero_burn_session_set_flags (BRASERO_BURN_SESSION (object),
2497 		                                g_value_get_int (value));
2498 		break;
2499 	default:
2500 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2501 		break;
2502 	}
2503 }
2504 
2505 static void
brasero_burn_session_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2506 brasero_burn_session_get_property (GObject *object,
2507                                    guint prop_id,
2508                                    GValue *value,
2509                                    GParamSpec *pspec)
2510 {
2511 	BraseroBurnSessionPrivate *priv;
2512 
2513 	g_return_if_fail (BRASERO_IS_BURN_SESSION (object));
2514 
2515 	priv = BRASERO_BURN_SESSION_PRIVATE (object);
2516 
2517 	/* Here we do not call the accessors functions to honour the 0/NULL value
2518 	 * which means use system default. */
2519 	switch (prop_id)
2520 	{
2521 	case PROP_TMPDIR:
2522 		g_value_set_string (value, priv->tmpdir);
2523 		break;
2524 	case PROP_RATE:
2525 		g_value_set_int64 (value, priv->settings->rate);
2526 		break;
2527 	case PROP_FLAGS:
2528 		g_value_set_int (value, priv->settings->flags);
2529 		break;
2530 	default:
2531 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2532 		break;
2533 	}
2534 }
2535 
2536 static void
brasero_burn_session_class_init(BraseroBurnSessionClass * klass)2537 brasero_burn_session_class_init (BraseroBurnSessionClass *klass)
2538 {
2539 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
2540 
2541 	g_type_class_add_private (klass, sizeof (BraseroBurnSessionPrivate));
2542 
2543 	parent_class = g_type_class_peek_parent(klass);
2544 
2545 	object_class->finalize = brasero_burn_session_finalize;
2546 	object_class->set_property = brasero_burn_session_set_property;
2547 	object_class->get_property = brasero_burn_session_get_property;
2548 
2549 	klass->get_output_path = brasero_burn_session_get_output_path_real;
2550 	klass->get_output_format = brasero_burn_session_get_output_format_real;
2551 	klass->set_output_image = brasero_burn_session_set_output_image_real;
2552 
2553 	/**
2554  	* BraseroBurnSession::output-changed:
2555  	* @session: the object which received the signal
2556   	* @former_medium: the medium which was previously set
2557 	*
2558  	* This signal gets emitted when the medium to burn to changed.
2559  	*
2560  	*/
2561 	brasero_burn_session_signals [OUTPUT_CHANGED_SIGNAL] =
2562 	    g_signal_new ("output_changed",
2563 			  BRASERO_TYPE_BURN_SESSION,
2564 			  G_SIGNAL_RUN_LAST,
2565 			  G_STRUCT_OFFSET (BraseroBurnSessionClass, output_changed),
2566 			  NULL,
2567 			  NULL,
2568 			  g_cclosure_marshal_VOID__OBJECT,
2569 			  G_TYPE_NONE,
2570 			  1,
2571 			  BRASERO_TYPE_MEDIUM);
2572 
2573 	/**
2574  	* BraseroBurnSession::track-added:
2575  	* @session: the object which received the signal
2576   	* @track: the track that was added
2577 	*
2578  	* This signal gets emitted when a track is added to @session.
2579  	*
2580  	*/
2581 	brasero_burn_session_signals [TRACK_ADDED_SIGNAL] =
2582 	    g_signal_new ("track_added",
2583 			  BRASERO_TYPE_BURN_SESSION,
2584 			  G_SIGNAL_RUN_LAST,
2585 			  G_STRUCT_OFFSET (BraseroBurnSessionClass, track_added),
2586 			  NULL,
2587 			  NULL,
2588 			  g_cclosure_marshal_VOID__OBJECT,
2589 			  G_TYPE_NONE,
2590 			  1,
2591 			  BRASERO_TYPE_TRACK);
2592 
2593 	/**
2594  	* BraseroBurnSession::track-removed:
2595  	* @session: the object which received the signal
2596   	* @track: the track that was removed
2597 	* @former_position: the former position of @track
2598 	*
2599  	* This signal gets emitted when a track is removed from @session.
2600  	*
2601  	*/
2602 	brasero_burn_session_signals [TRACK_REMOVED_SIGNAL] =
2603 	    g_signal_new ("track_removed",
2604 			  BRASERO_TYPE_BURN_SESSION,
2605 			  G_SIGNAL_RUN_LAST,
2606 			  G_STRUCT_OFFSET (BraseroBurnSessionClass, track_removed),
2607 			  NULL,
2608 			  NULL,
2609 			  brasero_marshal_VOID__OBJECT_UINT,
2610 			  G_TYPE_NONE,
2611 			  2,
2612 			  BRASERO_TYPE_TRACK,
2613 			  G_TYPE_UINT);
2614 
2615 	/**
2616  	* BraseroBurnSession::track-changed:
2617  	* @session: the object which received the signal
2618   	* @track: the track that changed
2619 	*
2620  	* This signal gets emitted when the contents of a track changed.
2621  	*
2622  	*/
2623 	brasero_burn_session_signals [TRACK_CHANGED_SIGNAL] =
2624 	    g_signal_new ("track_changed",
2625 			  BRASERO_TYPE_BURN_SESSION,
2626 			  G_SIGNAL_RUN_LAST,
2627 			  G_STRUCT_OFFSET (BraseroBurnSessionClass, track_changed),
2628 			  NULL,
2629 			  NULL,
2630 			  g_cclosure_marshal_VOID__OBJECT,
2631 			  G_TYPE_NONE,
2632 			  1,
2633 			  BRASERO_TYPE_TRACK);
2634 
2635 	/**
2636  	* BraseroBurnSession::tag-changed:
2637  	* @session: the object which received the signal
2638 	*
2639  	* This signal gets emitted when a tag changed for @session (whether it
2640 	* was removed, added, or it changed).
2641  	*
2642  	*/
2643 	brasero_burn_session_signals [TAG_CHANGED_SIGNAL] =
2644 	    g_signal_new ("tag_changed",
2645 			  BRASERO_TYPE_BURN_SESSION,
2646 			  G_SIGNAL_RUN_FIRST,
2647 			  0,
2648 			  NULL,
2649 			  NULL,
2650 			  g_cclosure_marshal_VOID__STRING,
2651 			  G_TYPE_NONE,
2652 			  1,
2653 	                  G_TYPE_STRING);
2654 
2655 	g_object_class_install_property (object_class,
2656 	                                 PROP_TMPDIR,
2657 	                                 g_param_spec_string ("tmpdir",
2658 	                                                      "Temporary directory",
2659 	                                                      "The path to the temporary directory",
2660 	                                                      NULL,
2661 	                                                      G_PARAM_READABLE|G_PARAM_WRITABLE));
2662 	g_object_class_install_property (object_class,
2663 	                                 PROP_RATE,
2664 	                                 g_param_spec_int64 ("speed",
2665 	                                                     "Burning speed",
2666 	                                                     "The speed at which a disc should be burned",
2667 	                                                     0,
2668 	                                                     G_MAXINT64,
2669 	                                                     0,
2670 	                                                     G_PARAM_READABLE|G_PARAM_WRITABLE));
2671 	g_object_class_install_property (object_class,
2672 	                                 PROP_FLAGS,
2673 	                                 g_param_spec_int ("flags",
2674 	                                                   "Burning flags",
2675 	                                                   "The flags that will be used to burn",
2676 	                                                   0,
2677 	                                                   G_MAXINT,
2678 	                                                   0,
2679 	                                                   G_PARAM_READABLE|G_PARAM_WRITABLE));
2680 }
2681 
2682 /**
2683  * brasero_burn_session_new:
2684  *
2685  * Returns a new #BraseroBurnSession object.
2686  *
2687  * Return value: a #BraseroBurnSession.
2688  **/
2689 
2690 BraseroBurnSession *
brasero_burn_session_new()2691 brasero_burn_session_new ()
2692 {
2693 	BraseroBurnSession *obj;
2694 
2695 	obj = BRASERO_BURN_SESSION (g_object_new (BRASERO_TYPE_BURN_SESSION, NULL));
2696 
2697 	return obj;
2698 }
2699 
2700