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 <sys/param.h>
36 
37 #include <glib.h>
38 #include <glib/gstdio.h>
39 #include <glib/gi18n-lib.h>
40 
41 #include "brasero-track-data.h"
42 #include "burn-mkisofs-base.h"
43 #include "burn-debug.h"
44 
45 typedef struct _BraseroTrackDataPrivate BraseroTrackDataPrivate;
46 struct _BraseroTrackDataPrivate
47 {
48 	BraseroImageFS fs_type;
49 	GSList *grafts;
50 	GSList *excluded;
51 
52 	guint file_num;
53 	guint64 data_blocks;
54 };
55 
56 #define BRASERO_TRACK_DATA_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_TRACK_DATA, BraseroTrackDataPrivate))
57 
58 G_DEFINE_TYPE (BraseroTrackData, brasero_track_data, BRASERO_TYPE_TRACK);
59 
60 /**
61  * brasero_graft_point_free:
62  * @graft: a #BraseroGraftPt
63  *
64  * Frees @graft. Do not use @grafts afterwards.
65  *
66  **/
67 
68 void
brasero_graft_point_free(BraseroGraftPt * graft)69 brasero_graft_point_free (BraseroGraftPt *graft)
70 {
71 	if (graft->uri)
72 		g_free (graft->uri);
73 
74 	g_free (graft->path);
75 	g_free (graft);
76 }
77 
78 /**
79  * brasero_graft_point_copy:
80  * @graft: a #BraseroGraftPt
81  *
82  * Copies @graft.
83  *
84  * Return value: a #BraseroGraftPt.
85  **/
86 
87 BraseroGraftPt *
brasero_graft_point_copy(BraseroGraftPt * graft)88 brasero_graft_point_copy (BraseroGraftPt *graft)
89 {
90 	BraseroGraftPt *newgraft;
91 
92 	g_return_val_if_fail (graft != NULL, NULL);
93 
94 	newgraft = g_new0 (BraseroGraftPt, 1);
95 	newgraft->path = g_strdup (graft->path);
96 	if (graft->uri)
97 		newgraft->uri = g_strdup (graft->uri);
98 
99 	return newgraft;
100 }
101 
102 static BraseroBurnResult
brasero_track_data_set_source_real(BraseroTrackData * track,GSList * grafts,GSList * unreadable)103 brasero_track_data_set_source_real (BraseroTrackData *track,
104 				    GSList *grafts,
105 				    GSList *unreadable)
106 {
107 	BraseroTrackDataPrivate *priv;
108 
109 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
110 
111 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
112 
113 	if (priv->grafts) {
114 		g_slist_foreach (priv->grafts, (GFunc) brasero_graft_point_free, NULL);
115 		g_slist_free (priv->grafts);
116 	}
117 
118 	if (priv->excluded) {
119 		g_slist_foreach (priv->excluded, (GFunc) g_free, NULL);
120 		g_slist_free (priv->excluded);
121 	}
122 
123 	priv->grafts = grafts;
124 	priv->excluded = unreadable;
125 	brasero_track_changed (BRASERO_TRACK (track));
126 
127 	return BRASERO_BURN_OK;
128 }
129 
130 /**
131  * brasero_track_data_set_source:
132  * @track: a #BraseroTrackData.
133  * @grafts: (element-type BraseroBurn.GraftPt) (in) (transfer full): a #GSList of #BraseroGraftPt.
134  * @unreadable: (element-type utf8) (allow-none) (in) (transfer full): a #GSList of URIS as strings or %NULL.
135  *
136  * Sets the lists of grafts points (@grafts) and excluded
137  * URIs (@unreadable) to be used to create an image.
138  *
139  * Be careful @track takes ownership of @grafts and
140  * @unreadable which must not be freed afterwards.
141  *
142  * Return value: a #BraseroBurnResult.
143  * BRASERO_BURN_OK if it was successful,
144  * BRASERO_BURN_ERR otherwise.
145  **/
146 
147 BraseroBurnResult
brasero_track_data_set_source(BraseroTrackData * track,GSList * grafts,GSList * unreadable)148 brasero_track_data_set_source (BraseroTrackData *track,
149 			       GSList *grafts,
150 			       GSList *unreadable)
151 {
152 	BraseroTrackDataClass *klass;
153 
154 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_ERR);
155 
156 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
157 	return klass->set_source (track, grafts, unreadable);
158 }
159 
160 static BraseroBurnResult
brasero_track_data_add_fs_real(BraseroTrackData * track,BraseroImageFS fstype)161 brasero_track_data_add_fs_real (BraseroTrackData *track,
162 				BraseroImageFS fstype)
163 {
164 	BraseroTrackDataPrivate *priv;
165 
166 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
167 	priv->fs_type |= fstype;
168 	return BRASERO_BURN_OK;
169 }
170 
171 /**
172  * brasero_track_data_add_fs:
173  * @track: a #BraseroTrackData
174  * @fstype: a #BraseroImageFS
175  *
176  * Adds one or more parameters determining the file system type
177  * and various other options to create an image.
178  *
179  * Return value: a #BraseroBurnResult.
180  * BRASERO_BURN_OK if it was successful,
181  * BRASERO_BURN_ERR otherwise.
182  **/
183 
184 BraseroBurnResult
brasero_track_data_add_fs(BraseroTrackData * track,BraseroImageFS fstype)185 brasero_track_data_add_fs (BraseroTrackData *track,
186 			   BraseroImageFS fstype)
187 {
188 	BraseroTrackDataClass *klass;
189 	BraseroImageFS fs_before;
190 	BraseroBurnResult result;
191 
192 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
193 
194 	fs_before = brasero_track_data_get_fs (track);
195 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
196 	if (!klass->add_fs)
197 		return BRASERO_BURN_NOT_SUPPORTED;
198 
199 	result = klass->add_fs (track, fstype);
200 	if (result != BRASERO_BURN_OK)
201 		return result;
202 
203 	if (fs_before != brasero_track_data_get_fs (track))
204 		brasero_track_changed (BRASERO_TRACK (track));
205 
206 	return BRASERO_BURN_OK;
207 }
208 
209 static BraseroBurnResult
brasero_track_data_rm_fs_real(BraseroTrackData * track,BraseroImageFS fstype)210 brasero_track_data_rm_fs_real (BraseroTrackData *track,
211 			       BraseroImageFS fstype)
212 {
213 	BraseroTrackDataPrivate *priv;
214 
215 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
216 	priv->fs_type &= ~(fstype);
217 	return BRASERO_BURN_OK;
218 }
219 
220 /**
221  * brasero_track_data_rm_fs:
222  * @track: a #BraseroTrackData
223  * @fstype: a #BraseroImageFS
224  *
225  * Removes one or more parameters determining the file system type
226  * and various other options to create an image.
227  *
228  * Return value: a #BraseroBurnResult.
229  * BRASERO_BURN_OK if it was successful,
230  * BRASERO_BURN_ERR otherwise.
231  **/
232 
233 BraseroBurnResult
brasero_track_data_rm_fs(BraseroTrackData * track,BraseroImageFS fstype)234 brasero_track_data_rm_fs (BraseroTrackData *track,
235 			  BraseroImageFS fstype)
236 {
237 	BraseroTrackDataClass *klass;
238 	BraseroImageFS fs_before;
239 	BraseroBurnResult result;
240 
241 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
242 
243 	fs_before = brasero_track_data_get_fs (track);
244 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
245 	if (!klass->rm_fs);
246 		return BRASERO_BURN_NOT_SUPPORTED;
247 
248 	result = klass->rm_fs (track, fstype);
249 	if (result != BRASERO_BURN_OK)
250 		return result;
251 
252 	if (fs_before != brasero_track_data_get_fs (track))
253 		brasero_track_changed (BRASERO_TRACK (track));
254 
255 	return BRASERO_BURN_OK;
256 }
257 
258 /**
259  * brasero_track_data_set_data_blocks:
260  * @track: a #BraseroTrackData
261  * @blocks: a #goffset
262  *
263  * Sets the size of the image to be created (in sectors of 2048 bytes).
264  *
265  * Return value: a #BraseroBurnResult.
266  * BRASERO_BURN_OK if it was successful,
267  * BRASERO_BURN_ERR otherwise.
268  **/
269 
270 BraseroBurnResult
brasero_track_data_set_data_blocks(BraseroTrackData * track,goffset blocks)271 brasero_track_data_set_data_blocks (BraseroTrackData *track,
272 				    goffset blocks)
273 {
274 	BraseroTrackDataPrivate *priv;
275 
276 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
277 
278 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
279 	priv->data_blocks = blocks;
280 
281 	return BRASERO_BURN_OK;
282 }
283 
284 /**
285  * brasero_track_data_set_file_num:
286  * @track: a #BraseroTrackData
287  * @number: a #guint64
288  *
289  * Sets the number of files (not directories) in @track.
290  *
291  * Return value: a #BraseroBurnResult.
292  * BRASERO_BURN_OK if it was successful,
293  * BRASERO_BURN_ERR otherwise.
294  **/
295 
296 BraseroBurnResult
brasero_track_data_set_file_num(BraseroTrackData * track,guint64 number)297 brasero_track_data_set_file_num (BraseroTrackData *track,
298 				 guint64 number)
299 {
300 	BraseroTrackDataPrivate *priv;
301 
302 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
303 
304 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
305 
306 	priv->file_num = number;
307 	return BRASERO_BURN_OK;
308 }
309 
310 /**
311  * brasero_track_data_get_fs:
312  * @track: a #BraseroTrackData
313  *
314  * Returns the parameters determining the file system type
315  * and various other options to create an image.
316  *
317  * Return value: a #BraseroImageFS.
318  **/
319 
320 BraseroImageFS
brasero_track_data_get_fs(BraseroTrackData * track)321 brasero_track_data_get_fs (BraseroTrackData *track)
322 {
323 	BraseroTrackDataClass *klass;
324 
325 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_IMAGE_FS_NONE);
326 
327 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
328 	return klass->get_fs (track);
329 }
330 
331 static BraseroImageFS
brasero_track_data_get_fs_real(BraseroTrackData * track)332 brasero_track_data_get_fs_real (BraseroTrackData *track)
333 {
334 	BraseroTrackDataPrivate *priv;
335 
336 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
337 	return priv->fs_type;
338 }
339 
340 static GHashTable *
brasero_track_data_mangle_joliet_name(GHashTable * joliet,const gchar * path,gchar * buffer)341 brasero_track_data_mangle_joliet_name (GHashTable *joliet,
342 				       const gchar *path,
343 				       gchar *buffer)
344 {
345 	gboolean has_slash = FALSE;
346 	gint dot_pos = -1;
347 	gint dot_len = -1;
348 	gchar *name;
349 	gint width;
350 	gint start;
351 	gint num;
352 	gint end;
353 
354 	/* NOTE: this wouldn't work on windows (not a big deal) */
355 	end = strlen (path);
356 	if (!end) {
357 		buffer [0] = '\0';
358 		return joliet;
359 	}
360 
361 	memcpy (buffer, path, MIN (end, MAXPATHLEN));
362 	buffer [MIN (end, MAXPATHLEN)] = '\0';
363 
364 	/* move back until we find a character different from G_DIR_SEPARATOR */
365 	end --;
366 	while (end >= 0 && G_IS_DIR_SEPARATOR (path [end])) {
367 		end --;
368 		has_slash = TRUE;
369 	}
370 
371 	/* There are only slashes */
372 	if (end == -1)
373 		return joliet;
374 
375 	start = end - 1;
376 	while (start >= 0 && !G_IS_DIR_SEPARATOR (path [start])) {
377 		/* Find the extension while at it */
378 		if (dot_pos <= 0 && path [start] == '.')
379 			dot_pos = start;
380 
381 		start --;
382 	}
383 
384 	if (end - start <= 64)
385 		return joliet;
386 
387 	name = buffer + start + 1;
388 	if (dot_pos > 0)
389 		dot_len = end - dot_pos + 1;
390 
391 	if (dot_len > 1 && dot_len < 5)
392 		memcpy (name + 64 - dot_len,
393 			path + dot_pos,
394 			dot_len);
395 
396 	name [64] = '\0';
397 
398 	if (!joliet) {
399 		joliet = g_hash_table_new_full (g_str_hash,
400 						g_str_equal,
401 						g_free,
402 						NULL);
403 
404 		g_hash_table_insert (joliet, g_strdup (buffer), GINT_TO_POINTER (1));
405 		if (has_slash)
406 			strcat (buffer, G_DIR_SEPARATOR_S);
407 
408 		BRASERO_BURN_LOG ("Mangled name to %s (truncated)", buffer);
409 		return joliet;
410 	}
411 
412 	/* see if this path was already used */
413 	num = GPOINTER_TO_INT (g_hash_table_lookup (joliet, buffer));
414 	if (!num) {
415 		g_hash_table_insert (joliet, g_strdup (buffer), GINT_TO_POINTER (1));
416 
417 		if (has_slash)
418 			strcat (buffer, G_DIR_SEPARATOR_S);
419 
420 		BRASERO_BURN_LOG ("Mangled name to %s (truncated)", buffer);
421 		return joliet;
422 	}
423 
424 	/* NOTE: g_hash_table_insert frees key_path */
425 	num ++;
426 	g_hash_table_insert (joliet, g_strdup (buffer), GINT_TO_POINTER (num));
427 
428 	width = 1;
429 	while (num / (width * 10)) width ++;
430 
431 	/* try to keep the extension */
432 	if (dot_len < 5 && dot_len > 1 )
433 		sprintf (name + (64 - width - dot_len),
434 			 "%i%s",
435 			 num,
436 			 path + dot_pos);
437 	else
438 		sprintf (name + (64 - width),
439 			 "%i",
440 			 num);
441 
442 	if (has_slash)
443 		strcat (buffer, G_DIR_SEPARATOR_S);
444 
445 	BRASERO_BURN_LOG ("Mangled name to %s", buffer);
446 	return joliet;
447 }
448 
449 /**
450  * brasero_track_data_get_grafts:
451  * @track: a #BraseroTrackData
452  *
453  * Returns a list of #BraseroGraftPt.
454  *
455  * Do not free after usage as @track retains ownership.
456  *
457  * Return value: (transfer none) (element-type BraseroBurn.GraftPt) (allow-none): a #GSList of #BraseroGraftPt or %NULL if empty.
458  **/
459 
460 GSList *
brasero_track_data_get_grafts(BraseroTrackData * track)461 brasero_track_data_get_grafts (BraseroTrackData *track)
462 {
463 	BraseroTrackDataClass *klass;
464 	GHashTable *mangle = NULL;
465 	BraseroImageFS image_fs;
466 	GSList *grafts;
467 	GSList *iter;
468 
469 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), NULL);
470 
471 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
472 	grafts = klass->get_grafts (track);
473 
474 	image_fs = brasero_track_data_get_fs (track);
475 	if ((image_fs & BRASERO_IMAGE_FS_JOLIET) == 0)
476 		return grafts;
477 
478 	for (iter = grafts; iter; iter = iter->next) {
479 		BraseroGraftPt *graft;
480 		gchar newpath [MAXPATHLEN];
481 
482 		graft = iter->data;
483 		mangle = brasero_track_data_mangle_joliet_name (mangle,
484 								graft->path,
485 								newpath);
486 
487 		g_free (graft->path);
488 		graft->path = g_strdup (newpath);
489 	}
490 
491 	if (mangle)
492 		g_hash_table_destroy (mangle);
493 
494 	return grafts;
495 }
496 
497 static GSList *
brasero_track_data_get_grafts_real(BraseroTrackData * track)498 brasero_track_data_get_grafts_real (BraseroTrackData *track)
499 {
500 	BraseroTrackDataPrivate *priv;
501 
502 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
503 	return priv->grafts;
504 }
505 
506 /**
507  * brasero_track_data_get_excluded_list:
508  * @track: a #BraseroTrackData.
509  *
510  * Returns a list of URIs which must not be included in
511  * the image to be created.
512  * Do not free the list or any of the URIs after
513  * usage as @track retains ownership.
514  *
515  * Return value: (transfer none) (element-type utf8) (allow-none): a #GSList of #gchar * or %NULL if no
516  * URI should be excluded.
517  **/
518 
519 GSList *
brasero_track_data_get_excluded_list(BraseroTrackData * track)520 brasero_track_data_get_excluded_list (BraseroTrackData *track)
521 {
522 	BraseroTrackDataClass *klass;
523 
524 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), NULL);
525 
526 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
527 	return klass->get_excluded (track);
528 }
529 
530 static GSList *
brasero_track_data_get_excluded_real(BraseroTrackData * track)531 brasero_track_data_get_excluded_real (BraseroTrackData *track)
532 {
533 	BraseroTrackDataPrivate *priv;
534 
535 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
536 	return priv->excluded;
537 }
538 
539 /**
540  * brasero_track_data_write_to_paths:
541  * @track: a #BraseroTrackData.
542  * @grafts_path: a #gchar.
543  * @excluded_path: a #gchar.
544  * @emptydir: a #gchar.
545  * @videodir: (allow-none): a #gchar or %NULL.
546  * @error: a #GError.
547  *
548  * Write to @grafts_path (a path to a file) the graft points,
549  * and to @excluded_path (a path to a file) the list of paths to
550  * be excluded; @emptydir is (path) is an empty
551  * directory to be used for created directories;
552  * @videodir (a path) is a directory to be used to build the
553  * the video image.
554  *
555  * This is mostly for internal use by mkisofs and similar.
556  *
557  * This function takes care of file name mangling.
558  *
559  * Return value: a #BraseroBurnResult.
560  **/
561 
562 BraseroBurnResult
brasero_track_data_write_to_paths(BraseroTrackData * track,const gchar * grafts_path,const gchar * excluded_path,const gchar * emptydir,const gchar * videodir,GError ** error)563 brasero_track_data_write_to_paths (BraseroTrackData *track,
564                                    const gchar *grafts_path,
565                                    const gchar *excluded_path,
566                                    const gchar *emptydir,
567                                    const gchar *videodir,
568                                    GError **error)
569 {
570 	GSList *grafts;
571 	GSList *excluded;
572 	BraseroBurnResult result;
573 	BraseroTrackDataClass *klass;
574 
575 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), BRASERO_BURN_NOT_SUPPORTED);
576 
577 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
578 	grafts = klass->get_grafts (track);
579 	excluded = klass->get_excluded (track);
580 
581 	result = brasero_mkisofs_base_write_to_files (grafts,
582 						      excluded,
583 						      brasero_track_data_get_fs (track),
584 						      emptydir,
585 						      videodir,
586 						      grafts_path,
587 						      excluded_path,
588 						      error);
589 	return result;
590 }
591 
592 /**
593  * brasero_track_data_get_file_num:
594  * @track: a #BraseroTrackData.
595  * @file_num: (allow-none) (out): a #guint64 or %NULL.
596  *
597  * Sets the number of files (not directories) in @file_num.
598  *
599  * Return value: a #BraseroBurnResult. %TRUE if @file_num
600  * was set, %FALSE otherwise.
601  **/
602 
603 BraseroBurnResult
brasero_track_data_get_file_num(BraseroTrackData * track,guint64 * file_num)604 brasero_track_data_get_file_num (BraseroTrackData *track,
605 				 guint64 *file_num)
606 {
607 	BraseroTrackDataClass *klass;
608 
609 	g_return_val_if_fail (BRASERO_IS_TRACK_DATA (track), 0);
610 
611 	klass = BRASERO_TRACK_DATA_GET_CLASS (track);
612 	if (file_num)
613 		*file_num = klass->get_file_num (track);
614 
615 	return BRASERO_BURN_OK;
616 }
617 
618 static guint64
brasero_track_data_get_file_num_real(BraseroTrackData * track)619 brasero_track_data_get_file_num_real (BraseroTrackData *track)
620 {
621 	BraseroTrackDataPrivate *priv;
622 
623 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
624 	return priv->file_num;
625 }
626 
627 static BraseroBurnResult
brasero_track_data_get_size(BraseroTrack * track,goffset * blocks,goffset * block_size)628 brasero_track_data_get_size (BraseroTrack *track,
629 			     goffset *blocks,
630 			     goffset *block_size)
631 {
632 	BraseroTrackDataPrivate *priv;
633 
634 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
635 
636 	if (*block_size)
637 		*block_size = 2048;
638 
639 	if (*blocks)
640 		*blocks = priv->data_blocks;
641 
642 	return BRASERO_BURN_OK;
643 }
644 
645 static BraseroBurnResult
brasero_track_data_get_track_type(BraseroTrack * track,BraseroTrackType * type)646 brasero_track_data_get_track_type (BraseroTrack *track,
647 				   BraseroTrackType *type)
648 {
649 	BraseroTrackDataPrivate *priv;
650 
651 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
652 
653 	brasero_track_type_set_has_data (type);
654 	brasero_track_type_set_data_fs (type, priv->fs_type);
655 
656 	return BRASERO_BURN_OK;
657 }
658 
659 static BraseroBurnResult
brasero_track_data_get_status(BraseroTrack * track,BraseroStatus * status)660 brasero_track_data_get_status (BraseroTrack *track,
661 			       BraseroStatus *status)
662 {
663 	BraseroTrackDataPrivate *priv;
664 
665 	priv = BRASERO_TRACK_DATA_PRIVATE (track);
666 
667 	if (!priv->grafts) {
668 		if (status)
669 			brasero_status_set_error (status,
670 						  g_error_new (BRASERO_BURN_ERROR,
671 							       BRASERO_BURN_ERROR_EMPTY,
672 							       _("There are no files to write to disc")));
673 		return BRASERO_BURN_ERR;
674 	}
675 
676 	return BRASERO_BURN_OK;
677 }
678 
679 static void
brasero_track_data_init(BraseroTrackData * object)680 brasero_track_data_init (BraseroTrackData *object)
681 { }
682 
683 static void
brasero_track_data_finalize(GObject * object)684 brasero_track_data_finalize (GObject *object)
685 {
686 	BraseroTrackDataPrivate *priv;
687 
688 	priv = BRASERO_TRACK_DATA_PRIVATE (object);
689 	if (priv->grafts) {
690 		g_slist_foreach (priv->grafts, (GFunc) brasero_graft_point_free, NULL);
691 		g_slist_free (priv->grafts);
692 		priv->grafts = NULL;
693 	}
694 
695 	if (priv->excluded) {
696 		g_slist_foreach (priv->excluded, (GFunc) g_free, NULL);
697 		g_slist_free (priv->excluded);
698 		priv->excluded = NULL;
699 	}
700 
701 	G_OBJECT_CLASS (brasero_track_data_parent_class)->finalize (object);
702 }
703 
704 static void
brasero_track_data_class_init(BraseroTrackDataClass * klass)705 brasero_track_data_class_init (BraseroTrackDataClass *klass)
706 {
707 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
708 	BraseroTrackClass *track_class = BRASERO_TRACK_CLASS (klass);
709 	BraseroTrackDataClass *track_data_class = BRASERO_TRACK_DATA_CLASS (klass);
710 
711 	g_type_class_add_private (klass, sizeof (BraseroTrackDataPrivate));
712 
713 	object_class->finalize = brasero_track_data_finalize;
714 
715 	track_class->get_type = brasero_track_data_get_track_type;
716 	track_class->get_status = brasero_track_data_get_status;
717 	track_class->get_size = brasero_track_data_get_size;
718 
719 	track_data_class->set_source = brasero_track_data_set_source_real;
720 	track_data_class->add_fs = brasero_track_data_add_fs_real;
721 	track_data_class->rm_fs = brasero_track_data_rm_fs_real;
722 
723 	track_data_class->get_fs = brasero_track_data_get_fs_real;
724 	track_data_class->get_grafts = brasero_track_data_get_grafts_real;
725 	track_data_class->get_excluded = brasero_track_data_get_excluded_real;
726 	track_data_class->get_file_num = brasero_track_data_get_file_num_real;
727 }
728 
729 /**
730  * brasero_track_data_new:
731  *
732  * Creates a new #BraseroTrackData.
733  *
734  *This type of tracks is used to create a disc image
735  * from or burn a selection of files.
736  *
737  * Return value: a #BraseroTrackData
738  **/
739 
740 BraseroTrackData *
brasero_track_data_new(void)741 brasero_track_data_new (void)
742 {
743 	return g_object_new (BRASERO_TYPE_TRACK_DATA, NULL);
744 }
745