1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3  * Libbrasero-burn
4  * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5  *
6  * Libbrasero-burn is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12  * GStreamer plugins to be used and distributed together with GStreamer
13  * and Libbrasero-burn. This permission is above and beyond the permissions granted
14  * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15  * you may extend this exception to your version of the code, but you are not
16  * obligated to do so. If you do not wish to do so, delete this exception
17  * statement from your version.
18  *
19  * Libbrasero-burn is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to:
26  * 	The Free Software Foundation, Inc.,
27  * 	51 Franklin Street, Fifth Floor
28  * 	Boston, MA  02110-1301, USA.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #  include <config.h>
33 #endif
34 
35 #include <string.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <sys/time.h>
40 #include <sys/resource.h>
41 
42 #include <glib.h>
43 #include <glib-object.h>
44 #include <glib/gi18n-lib.h>
45 
46 #include <gio/gio.h>
47 
48 #include "brasero-drive.h"
49 #include "brasero-medium.h"
50 
51 #include "burn-basics.h"
52 #include "burn-debug.h"
53 #include "brasero-session.h"
54 #include "brasero-session-helper.h"
55 #include "brasero-plugin-information.h"
56 #include "burn-job.h"
57 #include "burn-task-ctx.h"
58 #include "burn-task-item.h"
59 #include "libbrasero-marshal.h"
60 
61 #include "brasero-track-type-private.h"
62 
63 typedef struct _BraseroJobOutput {
64 	gchar *image;
65 	gchar *toc;
66 } BraseroJobOutput;
67 
68 typedef struct _BraseroJobInput {
69 	int out;
70 	int in;
71 } BraseroJobInput;
72 
73 static void brasero_job_iface_init_task_item (BraseroTaskItemIFace *iface);
74 G_DEFINE_TYPE_WITH_CODE (BraseroJob, brasero_job, G_TYPE_OBJECT,
75 			 G_IMPLEMENT_INTERFACE (BRASERO_TYPE_TASK_ITEM,
76 						brasero_job_iface_init_task_item));
77 
78 typedef struct BraseroJobPrivate BraseroJobPrivate;
79 struct BraseroJobPrivate {
80 	BraseroJob *next;
81 	BraseroJob *previous;
82 
83 	BraseroTaskCtx *ctx;
84 
85 	/* used if job reads data from a pipe */
86 	BraseroJobInput *input;
87 
88 	/* output type (sets at construct time) */
89 	BraseroTrackType type;
90 
91 	/* used if job writes data to a pipe (link is then NULL) */
92 	BraseroJobOutput *output;
93 	BraseroJob *linked;
94 };
95 
96 #define BRASERO_JOB_DEBUG(job_MACRO)						\
97 {										\
98 	const gchar *class_name_MACRO = NULL;					\
99 	if (BRASERO_IS_JOB (job_MACRO))						\
100 		class_name_MACRO = G_OBJECT_TYPE_NAME (job_MACRO);		\
101 	brasero_job_log_message (job_MACRO, G_STRLOC,				\
102 				 "%s called %s", 				\
103 				 class_name_MACRO,				\
104 				 G_STRFUNC);					\
105 }
106 
107 #define BRASERO_JOB_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_JOB, BraseroJobPrivate))
108 
109 enum {
110 	PROP_NONE,
111 	PROP_OUTPUT,
112 };
113 
114 typedef enum {
115 	ERROR_SIGNAL,
116 	LAST_SIGNAL
117 } BraseroJobSignalType;
118 
119 static guint brasero_job_signals [LAST_SIGNAL] = { 0 };
120 
121 static GObjectClass *parent_class = NULL;
122 
123 
124 /**
125  * Task item virtual functions implementation
126  */
127 
128 static BraseroTaskItem *
brasero_job_item_next(BraseroTaskItem * item)129 brasero_job_item_next (BraseroTaskItem *item)
130 {
131 	BraseroJob *self;
132 	BraseroJobPrivate *priv;
133 
134 	self = BRASERO_JOB (item);
135 	priv = BRASERO_JOB_PRIVATE (self);
136 
137 	if (!priv->next)
138 		return NULL;
139 
140 	return BRASERO_TASK_ITEM (priv->next);
141 }
142 
143 static BraseroTaskItem *
brasero_job_item_previous(BraseroTaskItem * item)144 brasero_job_item_previous (BraseroTaskItem *item)
145 {
146 	BraseroJob *self;
147 	BraseroJobPrivate *priv;
148 
149 	self = BRASERO_JOB (item);
150 	priv = BRASERO_JOB_PRIVATE (self);
151 
152 	if (!priv->previous)
153 		return NULL;
154 
155 	return BRASERO_TASK_ITEM (priv->previous);
156 }
157 
158 static BraseroBurnResult
brasero_job_item_link(BraseroTaskItem * input,BraseroTaskItem * output)159 brasero_job_item_link (BraseroTaskItem *input,
160 		       BraseroTaskItem *output)
161 {
162 	BraseroJobPrivate *priv_input;
163 	BraseroJobPrivate *priv_output;
164 
165 	priv_input = BRASERO_JOB_PRIVATE (input);
166 	priv_output = BRASERO_JOB_PRIVATE (output);
167 
168 	priv_input->next = BRASERO_JOB (output);
169 	priv_output->previous = BRASERO_JOB (input);
170 
171 	g_object_ref (input);
172 	return BRASERO_BURN_OK;
173 }
174 
175 static gboolean
brasero_job_is_last_active(BraseroJob * self)176 brasero_job_is_last_active (BraseroJob *self)
177 {
178 	BraseroJobPrivate *priv;
179 	BraseroJob *next;
180 
181 	priv = BRASERO_JOB_PRIVATE (self);
182 	if (!priv->ctx)
183 		return FALSE;
184 
185 	next = priv->next;
186 	while (next) {
187 		priv = BRASERO_JOB_PRIVATE (next);
188 		if (priv->ctx)
189 			return FALSE;
190 		next = priv->next;
191 	}
192 
193 	return TRUE;
194 }
195 
196 static gboolean
brasero_job_is_first_active(BraseroJob * self)197 brasero_job_is_first_active (BraseroJob *self)
198 {
199 	BraseroJobPrivate *priv;
200 	BraseroJob *prev;
201 
202 	priv = BRASERO_JOB_PRIVATE (self);
203 	if (!priv->ctx)
204 		return FALSE;
205 
206 	prev = priv->previous;
207 	while (prev) {
208 		priv = BRASERO_JOB_PRIVATE (prev);
209 		if (priv->ctx)
210 			return FALSE;
211 		prev = priv->previous;
212 	}
213 
214 	return TRUE;
215 }
216 
217 static void
brasero_job_input_free(BraseroJobInput * input)218 brasero_job_input_free (BraseroJobInput *input)
219 {
220 	if (!input)
221 		return;
222 
223 	if (input->in > 0)
224 		close (input->in);
225 
226 	if (input->out > 0)
227 		close (input->out);
228 
229 	g_free (input);
230 }
231 
232 static void
brasero_job_output_free(BraseroJobOutput * output)233 brasero_job_output_free (BraseroJobOutput *output)
234 {
235 	if (!output)
236 		return;
237 
238 	if (output->image) {
239 		g_free (output->image);
240 		output->image = NULL;
241 	}
242 
243 	if (output->toc) {
244 		g_free (output->toc);
245 		output->toc = NULL;
246 	}
247 
248 	g_free (output);
249 }
250 
251 static void
brasero_job_deactivate(BraseroJob * self)252 brasero_job_deactivate (BraseroJob *self)
253 {
254 	BraseroJobPrivate *priv;
255 
256 	priv = BRASERO_JOB_PRIVATE (self);
257 
258 	BRASERO_JOB_LOG (self, "deactivating");
259 
260 	/* ::start hasn't been called yet */
261 	if (priv->ctx) {
262 		g_object_unref (priv->ctx);
263 		priv->ctx = NULL;
264 	}
265 
266 	if (priv->input) {
267 		brasero_job_input_free (priv->input);
268 		priv->input = NULL;
269 	}
270 
271 	if (priv->output) {
272 		brasero_job_output_free (priv->output);
273 		priv->output = NULL;
274 	}
275 
276 	if (priv->linked)
277 		priv->linked = NULL;
278 }
279 
280 static BraseroBurnResult
brasero_job_allow_deactivation(BraseroJob * self,BraseroBurnSession * session,GError ** error)281 brasero_job_allow_deactivation (BraseroJob *self,
282 				BraseroBurnSession *session,
283 				GError **error)
284 {
285 	BraseroJobPrivate *priv;
286 	BraseroTrackType input;
287 
288 	priv = BRASERO_JOB_PRIVATE (self);
289 
290 	/* This job refused to work. This is allowed in three cases:
291 	 * - the job is the only one in the task (no other job linked) and the
292 	 *   track type as input is the same as the track type of the output
293 	 *   except if type is DISC as input or output
294 	 * - if the job hasn't got any job linked before the next linked job
295 	 *   accepts the track type of the session as input
296 	 * - the output of the previous job is the same as this job output type
297 	 */
298 
299 	/* there can't be two recorders in a row so ... */
300 	if (priv->type.type == BRASERO_TRACK_TYPE_DISC)
301 		goto error;
302 
303 	if (priv->previous) {
304 		BraseroJobPrivate *previous;
305 		previous = BRASERO_JOB_PRIVATE (priv->previous);
306 		memcpy (&input, &previous->type, sizeof (BraseroTrackType));
307 	}
308 	else
309 		brasero_burn_session_get_input_type (session, &input);
310 
311 	if (!brasero_track_type_equal (&input, &priv->type))
312 		goto error;
313 
314 	return BRASERO_BURN_NOT_RUNNING;
315 
316 error:
317 
318 	g_set_error (error,
319 		     BRASERO_BURN_ERR,
320 		     BRASERO_BURN_ERROR_PLUGIN_MISBEHAVIOR,
321 		     /* Translators: %s is the plugin name */
322 		     _("\"%s\" did not behave properly"),
323 		     G_OBJECT_TYPE_NAME (self));
324 	return BRASERO_BURN_ERR;
325 }
326 
327 static BraseroBurnResult
brasero_job_item_activate(BraseroTaskItem * item,BraseroTaskCtx * ctx,GError ** error)328 brasero_job_item_activate (BraseroTaskItem *item,
329 			   BraseroTaskCtx *ctx,
330 			   GError **error)
331 {
332 	BraseroJob *self;
333 	BraseroJobClass *klass;
334 	BraseroJobPrivate *priv;
335 	BraseroBurnSession *session;
336 	BraseroBurnResult result = BRASERO_BURN_OK;
337 
338 	self = BRASERO_JOB (item);
339 	priv = BRASERO_JOB_PRIVATE (self);
340 	session = brasero_task_ctx_get_session (ctx);
341 
342 	g_object_ref (ctx);
343 	priv->ctx = ctx;
344 
345 	klass = BRASERO_JOB_GET_CLASS (self);
346 
347 	/* see if this job needs to be deactivated (if no function then OK) */
348 	if (klass->activate)
349 		result = klass->activate (self, error);
350 	else
351 		BRASERO_BURN_LOG ("no ::activate method %s",
352 				  G_OBJECT_TYPE_NAME (item));
353 
354 	if (result != BRASERO_BURN_OK) {
355 		g_object_unref (ctx);
356 		priv->ctx = NULL;
357 
358 		if (result == BRASERO_BURN_NOT_RUNNING)
359 			result = brasero_job_allow_deactivation (self, session, error);
360 
361 		return result;
362 	}
363 
364 	return BRASERO_BURN_OK;
365 }
366 
367 static gboolean
brasero_job_item_is_active(BraseroTaskItem * item)368 brasero_job_item_is_active (BraseroTaskItem *item)
369 {
370 	BraseroJob *self;
371 	BraseroJobPrivate *priv;
372 
373 	self = BRASERO_JOB (item);
374 	priv = BRASERO_JOB_PRIVATE (self);
375 
376 	return (priv->ctx != NULL);
377 }
378 
379 static BraseroBurnResult
brasero_job_check_output_disc_space(BraseroJob * self,GError ** error)380 brasero_job_check_output_disc_space (BraseroJob *self,
381 				     GError **error)
382 {
383 	BraseroBurnSession *session;
384 	goffset output_blocks = 0;
385 	goffset media_blocks = 0;
386 	BraseroJobPrivate *priv;
387 	BraseroBurnFlag flags;
388 	BraseroMedium *medium;
389 	BraseroDrive *drive;
390 
391 	priv = BRASERO_JOB_PRIVATE (self);
392 
393 	brasero_task_ctx_get_session_output_size (priv->ctx,
394 						  &output_blocks,
395 						  NULL);
396 
397 	session = brasero_task_ctx_get_session (priv->ctx);
398 	drive = brasero_burn_session_get_burner (session);
399 	medium = brasero_drive_get_medium (drive);
400 	flags = brasero_burn_session_get_flags (session);
401 
402 	/* FIXME: if we can't recover the size of the medium
403 	 * what should we do ? do as if we could ? */
404 
405 	/* see if we are appending or not */
406 	if (flags & (BRASERO_BURN_FLAG_APPEND|BRASERO_BURN_FLAG_MERGE))
407 		brasero_medium_get_free_space (medium, NULL, &media_blocks);
408 	else
409 		brasero_medium_get_capacity (medium, NULL, &media_blocks);
410 
411 	/* This is not really an error, we'll probably ask the
412 	 * user to load a new disc */
413 	if (output_blocks > media_blocks) {
414 		gchar *media_blocks_str;
415 		gchar *output_blocks_str;
416 
417 		BRASERO_BURN_LOG ("Insufficient space on disc %"G_GINT64_FORMAT"/%"G_GINT64_FORMAT,
418 				  media_blocks,
419 				  output_blocks);
420 
421 		media_blocks_str = g_strdup_printf ("%"G_GINT64_FORMAT, media_blocks);
422 		output_blocks_str = g_strdup_printf ("%"G_GINT64_FORMAT, output_blocks);
423 
424 		g_set_error (error,
425 			     BRASERO_BURN_ERROR,
426 			     BRASERO_BURN_ERROR_MEDIUM_SPACE,
427 			     /* Translators: the first %s is the size of the free space on the medium
428 			      * and the second %s is the size of the space required by the data to be
429 			      * burnt. */
430 			     _("Not enough space available on the disc (%s available for %s)"),
431 			     media_blocks_str,
432 			     output_blocks_str);
433 
434 		g_free (media_blocks_str);
435 		g_free (output_blocks_str);
436 		return BRASERO_BURN_NEED_RELOAD;
437 	}
438 
439 	return BRASERO_BURN_OK;
440 }
441 
442 static BraseroBurnResult
brasero_job_check_output_volume_space(BraseroJob * self,GError ** error)443 brasero_job_check_output_volume_space (BraseroJob *self,
444 				       GError **error)
445 {
446 	GFileInfo *info;
447 	gchar *directory;
448 	GFile *file = NULL;
449 	struct rlimit limit;
450 	guint64 vol_size = 0;
451 	gint64 output_size = 0;
452 	BraseroJobPrivate *priv;
453 	const gchar *filesystem;
454 
455 	/* now that the job has a known output we must check that the volume the
456 	 * job is writing to has enough space for all output */
457 
458 	priv = BRASERO_JOB_PRIVATE (self);
459 
460 	/* Get the size and filesystem type for the volume first.
461 	 * NOTE: since any plugin must output anything LOCALLY, we can then use
462 	 * all libc API. */
463 	if (!priv->output)
464 		return BRASERO_BURN_ERR;
465 
466 	directory = g_path_get_dirname (priv->output->image);
467 	file = g_file_new_for_path (directory);
468 	g_free (directory);
469 
470 	if (file == NULL)
471 		goto error;
472 
473 	info = g_file_query_info (file,
474 				  G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
475 				  G_FILE_QUERY_INFO_NONE,
476 				  NULL,
477 				  error);
478 	if (!info)
479 		goto error;
480 
481 	/* Check permissions first */
482 	if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) {
483 		BRASERO_JOB_LOG (self, "No permissions");
484 
485 		g_object_unref (info);
486 		g_object_unref (file);
487 		g_set_error (error,
488 			     BRASERO_BURN_ERROR,
489 			     BRASERO_BURN_ERROR_PERMISSION,
490 			     _("You do not have the required permission to write at this location"));
491 		return BRASERO_BURN_ERR;
492 	}
493 	g_object_unref (info);
494 
495 	/* Now size left */
496 	info = g_file_query_filesystem_info (file,
497 					     G_FILE_ATTRIBUTE_FILESYSTEM_FREE ","
498 					     G_FILE_ATTRIBUTE_FILESYSTEM_TYPE,
499 					     NULL,
500 					     error);
501 	if (!info)
502 		goto error;
503 
504 	g_object_unref (file);
505 	file = NULL;
506 
507 	/* Now check the filesystem type: the problem here is that some
508 	 * filesystems have a maximum file size limit of 4 GiB and more than
509 	 * often we need a temporary file size of 4 GiB or more. */
510 	filesystem = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE);
511 	BRASERO_BURN_LOG ("%s filesystem detected", filesystem);
512 
513 	brasero_job_get_session_output_size (self, NULL, &output_size);
514 
515 	if (output_size >= 2147483648ULL
516 	&&  filesystem
517 	&& !strcmp (filesystem, "msdos")) {
518 		g_object_unref (info);
519 		g_set_error (error,
520 			     BRASERO_BURN_ERROR,
521 			     BRASERO_BURN_ERROR_DISK_SPACE,
522 			     _("The filesystem you chose to store the temporary image on cannot hold files with a size over 2 GiB"));
523 		return BRASERO_BURN_ERR;
524 	}
525 
526 	vol_size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
527 	g_object_unref (info);
528 
529 	/* get the size of the output this job is supposed to create */
530 	BRASERO_BURN_LOG ("Volume size %lli, output size %lli", vol_size, output_size);
531 
532 	/* it's fine here to check size in bytes */
533 	if (output_size > vol_size) {
534 		g_set_error (error,
535 			     BRASERO_BURN_ERROR,
536 			     BRASERO_BURN_ERROR_DISK_SPACE,
537 			     _("The location you chose to store the temporary image on does not have enough free space for the disc image (%ld MiB needed)"),
538 			     (unsigned long) output_size / 1048576);
539 		return BRASERO_BURN_ERR;
540 	}
541 
542 	/* Last but not least, use getrlimit () to check that we are allowed to
543 	 * write a file of such length and that quotas won't get in our way */
544 	if (getrlimit (RLIMIT_FSIZE, &limit)) {
545 		g_set_error (error,
546 			     BRASERO_BURN_ERROR,
547 			     BRASERO_BURN_ERROR_DISK_SPACE,
548 			     "%s",
549 			     g_strerror (errno));
550 		return BRASERO_BURN_ERR;
551 	}
552 
553 	if (limit.rlim_cur < output_size) {
554 		BRASERO_BURN_LOG ("User not allowed to write such a large file");
555 
556 		g_set_error (error,
557 			     BRASERO_BURN_ERROR,
558 			     BRASERO_BURN_ERROR_DISK_SPACE,
559 			     _("The location you chose to store the temporary image on does not have enough free space for the disc image (%ld MiB needed)"),
560 			     (unsigned long) output_size / 1048576);
561 		return BRASERO_BURN_ERR;
562 	}
563 
564 	return BRASERO_BURN_OK;
565 
566 error:
567 
568 	if (error && *error == NULL)
569 		g_set_error (error,
570 			     BRASERO_BURN_ERROR,
571 			     BRASERO_BURN_ERROR_GENERAL,
572 			     _("The size of the volume could not be retrieved"));
573 
574 	if (file)
575 		g_object_unref (file);
576 
577 	return BRASERO_BURN_ERR;
578 }
579 
580 static BraseroBurnResult
brasero_job_set_output_file(BraseroJob * self,GError ** error)581 brasero_job_set_output_file (BraseroJob *self,
582 			     GError **error)
583 {
584 	BraseroTrackType *session_output;
585 	BraseroBurnSession *session;
586 	BraseroBurnResult result;
587 	BraseroJobPrivate *priv;
588 	goffset output_size = 0;
589 	gchar *image = NULL;
590 	gchar *toc = NULL;
591 	gboolean is_last;
592 
593 	priv = BRASERO_JOB_PRIVATE (self);
594 
595 	/* no next job so we need a file pad */
596 	session = brasero_task_ctx_get_session (priv->ctx);
597 
598 	/* If the plugin is not supposed to output anything, then don't test */
599 	brasero_job_get_session_output_size (BRASERO_JOB (self), NULL, &output_size);
600 
601 	/* This should be re-enabled when we make sure all plugins (like vcd)
602 	 * don't advertize an output of 0 whereas it's not true. Maybe we could
603 	 * use -1 for plugins that don't output. */
604 	/* if (!output_size)
605 		return BRASERO_BURN_OK; */
606 
607 	/* check if that's the last task */
608 	session_output = brasero_track_type_new ();
609 	brasero_burn_session_get_output_type (session, session_output);
610 	is_last = brasero_track_type_equal (session_output, &priv->type);
611 	brasero_track_type_free (session_output);
612 
613 	if (priv->type.type == BRASERO_TRACK_TYPE_IMAGE) {
614 		if (is_last) {
615 			BraseroTrackType input = { 0, };
616 
617 			result = brasero_burn_session_get_output (session,
618 								  &image,
619 								  &toc);
620 
621 			/* check paths are set */
622 			if (!image
623 			|| (priv->type.subtype.img_format != BRASERO_IMAGE_FORMAT_BIN && !toc)) {
624 				g_set_error (error,
625 					     BRASERO_BURN_ERROR,
626 					     BRASERO_BURN_ERROR_OUTPUT_NONE,
627 					     _("No path was specified for the image output"));
628 				return BRASERO_BURN_ERR;
629 			}
630 
631 			brasero_burn_session_get_input_type (session,
632 							     &input);
633 
634 			/* if input is the same as output, then that's a
635 			 * processing task and there's no need to check if the
636 			 * output already exists since it will (but that's OK) */
637 			if (input.type == BRASERO_TRACK_TYPE_IMAGE
638 			&&  input.subtype.img_format == priv->type.subtype.img_format) {
639 				BRASERO_BURN_LOG ("Processing task, skipping check size");
640 				priv->output = g_new0 (BraseroJobOutput, 1);
641 				priv->output->image = image;
642 				priv->output->toc = toc;
643 				return BRASERO_BURN_OK;
644 			}
645 		}
646 		else {
647 			/* NOTE: no need to check for the existence here */
648 			result = brasero_burn_session_get_tmp_image (session,
649 								     priv->type.subtype.img_format,
650 								     &image,
651 								     &toc,
652 								     error);
653 			if (result != BRASERO_BURN_OK)
654 				return result;
655 		}
656 
657 		BRASERO_JOB_LOG (self, "output set (IMAGE) image = %s toc = %s",
658 				 image,
659 				 toc ? toc : "none");
660 	}
661 	else if (priv->type.type == BRASERO_TRACK_TYPE_STREAM) {
662 		/* NOTE: this one can only a temporary file */
663 		result = brasero_burn_session_get_tmp_file (session,
664 							    ".cdr",
665 							    &image,
666 							    error);
667 		BRASERO_JOB_LOG (self, "Output set (AUDIO) image = %s", image);
668 	}
669 	else /* other types don't need an output */
670 		return BRASERO_BURN_OK;
671 
672 	if (result != BRASERO_BURN_OK)
673 		return result;
674 
675 	priv->output = g_new0 (BraseroJobOutput, 1);
676 	priv->output->image = image;
677 	priv->output->toc = toc;
678 
679 	if (brasero_burn_session_get_flags (session) & BRASERO_BURN_FLAG_CHECK_SIZE)
680 		return brasero_job_check_output_volume_space (self, error);
681 
682 	return result;
683 }
684 
685 static BraseroJob *
brasero_job_get_next_active(BraseroJob * self)686 brasero_job_get_next_active (BraseroJob *self)
687 {
688 	BraseroJobPrivate *priv;
689 	BraseroJob *next;
690 
691 	/* since some jobs can return NOT_RUNNING after ::init, skip them */
692 	priv = BRASERO_JOB_PRIVATE (self);
693 	if (!priv->next)
694 		return NULL;
695 
696 	next = priv->next;
697 	while (next) {
698 		priv = BRASERO_JOB_PRIVATE (next);
699 
700 		if (priv->ctx)
701 			return next;
702 
703 		next = priv->next;
704 	}
705 
706 	return NULL;
707 }
708 
709 static BraseroBurnResult
brasero_job_item_start(BraseroTaskItem * item,GError ** error)710 brasero_job_item_start (BraseroTaskItem *item,
711 		        GError **error)
712 {
713 	BraseroJob *self;
714 	BraseroJobClass *klass;
715 	BraseroJobAction action;
716 	BraseroJobPrivate *priv;
717 	BraseroBurnResult result;
718 
719 	/* This function is compulsory */
720 	self = BRASERO_JOB (item);
721 	priv = BRASERO_JOB_PRIVATE (self);
722 
723 	/* skip jobs that are not active */
724 	if (!priv->ctx)
725 		return BRASERO_BURN_OK;
726 
727 	/* set the output if need be */
728 	brasero_job_get_action (self, &action);
729 	priv->linked = brasero_job_get_next_active (self);
730 
731 	if (!priv->linked) {
732 		/* that's the last job so is action is image it needs a file */
733 		if (action == BRASERO_JOB_ACTION_IMAGE) {
734 			result = brasero_job_set_output_file (self, error);
735 			if (result != BRASERO_BURN_OK)
736 				return result;
737 		}
738 		else if (action == BRASERO_JOB_ACTION_RECORD) {
739 			BraseroBurnFlag flags;
740 			BraseroBurnSession *session;
741 
742 			session = brasero_task_ctx_get_session (priv->ctx);
743 			flags = brasero_burn_session_get_flags (session);
744 			if (flags & BRASERO_BURN_FLAG_CHECK_SIZE
745 			&& !(flags & BRASERO_BURN_FLAG_OVERBURN)) {
746 				result = brasero_job_check_output_disc_space (self, error);
747 				if (result != BRASERO_BURN_OK)
748 					return result;
749 			}
750 		}
751 	}
752 	else
753 		BRASERO_JOB_LOG (self, "linked to %s", G_OBJECT_TYPE_NAME (priv->linked));
754 
755 	if (!brasero_job_is_first_active (self)) {
756 		int fd [2];
757 
758 		BRASERO_JOB_LOG (self, "creating input");
759 
760 		/* setup a pipe */
761 		if (pipe (fd)) {
762                         int errsv = errno;
763 
764 			BRASERO_BURN_LOG ("A pipe couldn't be created");
765 			g_set_error (error,
766 				     BRASERO_BURN_ERROR,
767 				     BRASERO_BURN_ERROR_GENERAL,
768 				     _("An internal error occurred (%s)"),
769 				     g_strerror (errsv));
770 
771 			return BRASERO_BURN_ERR;
772 		}
773 
774 		/* NOTE: don't set O_NONBLOCK automatically as some plugins
775 		 * don't like that (genisoimage, mkisofs) */
776 		priv->input = g_new0 (BraseroJobInput, 1);
777 		priv->input->in = fd [0];
778 		priv->input->out = fd [1];
779 	}
780 
781 	klass = BRASERO_JOB_GET_CLASS (self);
782 	if (!klass->start) {
783 		BRASERO_JOB_LOG (self, "no ::start method");
784 		BRASERO_JOB_NOT_SUPPORTED (self);
785 	}
786 
787 	result = klass->start (self, error);
788 	if (result == BRASERO_BURN_NOT_RUNNING) {
789 		/* this means that the task is already completed. This
790 		 * must be returned by the last active job of the task
791 		 * (and usually the only one?) */
792 
793 		if (priv->linked) {
794 			g_set_error (error,
795 				     BRASERO_BURN_ERROR,
796 				     BRASERO_BURN_ERROR_PLUGIN_MISBEHAVIOR,
797 				     _("\"%s\" did not behave properly"),
798 				     G_OBJECT_TYPE_NAME (self));
799 			return BRASERO_BURN_ERR;
800 		}
801 	}
802 
803 	if (result == BRASERO_BURN_NOT_SUPPORTED) {
804 		/* only forgive this error when that's the last job and we're
805 		 * searching for a job to set the current track size */
806 		if (action != BRASERO_JOB_ACTION_SIZE) {
807 			g_set_error (error,
808 				     BRASERO_BURN_ERROR,
809 				     BRASERO_BURN_ERROR_PLUGIN_MISBEHAVIOR,
810 				     _("\"%s\" did not behave properly"),
811 				     G_OBJECT_TYPE_NAME (self));
812 			return BRASERO_BURN_ERR;
813 		}
814 
815 		/* deactivate it */
816 		brasero_job_deactivate (self);
817 	}
818 
819 	return result;
820 }
821 
822 static BraseroBurnResult
brasero_job_item_clock_tick(BraseroTaskItem * item,BraseroTaskCtx * ctx,GError ** error)823 brasero_job_item_clock_tick (BraseroTaskItem *item,
824 			     BraseroTaskCtx *ctx,
825 			     GError **error)
826 {
827 	BraseroJob *self;
828 	BraseroJobClass *klass;
829 	BraseroJobPrivate *priv;
830 	BraseroBurnResult result = BRASERO_BURN_OK;
831 
832 	self = BRASERO_JOB (item);
833 	priv = BRASERO_JOB_PRIVATE (self);
834 	if (!priv->ctx)
835 		return BRASERO_BURN_OK;
836 
837 	klass = BRASERO_JOB_GET_CLASS (self);
838 	if (klass->clock_tick)
839 		result = klass->clock_tick (self);
840 
841 	return result;
842 }
843 
844 static BraseroBurnResult
brasero_job_disconnect(BraseroJob * self,GError ** error)845 brasero_job_disconnect (BraseroJob *self,
846 			GError **error)
847 {
848 	BraseroJobPrivate *priv;
849 	BraseroBurnResult result = BRASERO_BURN_OK;
850 
851 	priv = BRASERO_JOB_PRIVATE (self);
852 
853 	/* NOTE: this function is only called when there are no more track to
854 	 * process */
855 
856 	if (priv->linked) {
857 		BraseroJobPrivate *priv_link;
858 
859 		BRASERO_JOB_LOG (self,
860 				 "disconnecting %s from %s",
861 				 G_OBJECT_TYPE_NAME (self),
862 				 G_OBJECT_TYPE_NAME (priv->linked));
863 
864 		priv_link = BRASERO_JOB_PRIVATE (priv->linked);
865 
866 		/* only close the input to tell the other end that we're
867 		 * finished with writing to the pipe */
868 		if (priv_link->input->out > 0) {
869 			close (priv_link->input->out);
870 			priv_link->input->out = 0;
871 		}
872 	}
873 	else if (priv->output) {
874 		brasero_job_output_free (priv->output);
875 		priv->output = NULL;
876 	}
877 
878 	if (priv->input) {
879 		BRASERO_JOB_LOG (self,
880 				 "closing connection for %s",
881 				 G_OBJECT_TYPE_NAME (self));
882 
883 		brasero_job_input_free (priv->input);
884 		priv->input = NULL;
885 	}
886 
887 	return result;
888 }
889 
890 static BraseroBurnResult
brasero_job_item_stop(BraseroTaskItem * item,BraseroTaskCtx * ctx,GError ** error)891 brasero_job_item_stop (BraseroTaskItem *item,
892 		       BraseroTaskCtx *ctx,
893 		       GError **error)
894 {
895 	BraseroJob *self;
896 	BraseroJobClass *klass;
897 	BraseroJobPrivate *priv;
898 	BraseroBurnResult result = BRASERO_BURN_OK;
899 
900 	self = BRASERO_JOB (item);
901 	priv = BRASERO_JOB_PRIVATE (self);
902 
903 	if (!priv->ctx)
904 		return BRASERO_BURN_OK;
905 
906 	BRASERO_JOB_LOG (self, "stopping");
907 
908 	/* the order is important here */
909 	klass = BRASERO_JOB_GET_CLASS (self);
910 	if (klass->stop)
911 		result = klass->stop (self, error);
912 
913 	brasero_job_disconnect (self, error);
914 
915 	if (priv->ctx) {
916 		g_object_unref (priv->ctx);
917 		priv->ctx = NULL;
918 	}
919 
920 	return result;
921 }
922 
923 static void
brasero_job_iface_init_task_item(BraseroTaskItemIFace * iface)924 brasero_job_iface_init_task_item (BraseroTaskItemIFace *iface)
925 {
926 	iface->next = brasero_job_item_next;
927 	iface->previous = brasero_job_item_previous;
928 	iface->link = brasero_job_item_link;
929 	iface->activate = brasero_job_item_activate;
930 	iface->is_active = brasero_job_item_is_active;
931 	iface->start = brasero_job_item_start;
932 	iface->stop = brasero_job_item_stop;
933 	iface->clock_tick = brasero_job_item_clock_tick;
934 }
935 
936 BraseroBurnResult
brasero_job_tag_lookup(BraseroJob * self,const gchar * tag,GValue ** value)937 brasero_job_tag_lookup (BraseroJob *self,
938 			const gchar *tag,
939 			GValue **value)
940 {
941 	BraseroJobPrivate *priv;
942 	BraseroBurnSession *session;
943 
944 	BRASERO_JOB_DEBUG (self);
945 
946 	priv = BRASERO_JOB_PRIVATE (self);
947 
948 	session = brasero_task_ctx_get_session (priv->ctx);
949 	return brasero_burn_session_tag_lookup (session,
950 						tag,
951 						value);
952 }
953 
954 BraseroBurnResult
brasero_job_tag_add(BraseroJob * self,const gchar * tag,GValue * value)955 brasero_job_tag_add (BraseroJob *self,
956 		     const gchar *tag,
957 		     GValue *value)
958 {
959 	BraseroJobPrivate *priv;
960 	BraseroBurnSession *session;
961 
962 	BRASERO_JOB_DEBUG (self);
963 
964 	priv = BRASERO_JOB_PRIVATE (self);
965 
966 	if (!brasero_job_is_last_active (self))
967 		return BRASERO_BURN_ERR;
968 
969 	session = brasero_task_ctx_get_session (priv->ctx);
970 	brasero_burn_session_tag_add (session,
971 				      tag,
972 				      value);
973 
974 	return BRASERO_BURN_OK;
975 }
976 
977 /**
978  * Means a job successfully completed its task.
979  * track can be NULL, depending on whether or not the job created a track.
980  */
981 
982 BraseroBurnResult
brasero_job_add_track(BraseroJob * self,BraseroTrack * track)983 brasero_job_add_track (BraseroJob *self,
984 		       BraseroTrack *track)
985 {
986 	BraseroJobPrivate *priv;
987 	BraseroJobAction action;
988 
989 	BRASERO_JOB_DEBUG (self);
990 
991 	priv = BRASERO_JOB_PRIVATE (self);
992 
993 	/* to add a track to the session, a job :
994 	 * - must be the last running in the chain
995 	 * - the action for the job must be IMAGE */
996 
997 	action = BRASERO_JOB_ACTION_NONE;
998 	brasero_job_get_action (self, &action);
999 	if (action != BRASERO_JOB_ACTION_IMAGE)
1000 		return BRASERO_BURN_ERR;
1001 
1002 	if (!brasero_job_is_last_active (self))
1003 		return BRASERO_BURN_ERR;
1004 
1005 	return brasero_task_ctx_add_track (priv->ctx, track);
1006 }
1007 
1008 BraseroBurnResult
brasero_job_finished_session(BraseroJob * self)1009 brasero_job_finished_session (BraseroJob *self)
1010 {
1011 	GError *error = NULL;
1012 	BraseroJobClass *klass;
1013 	BraseroJobPrivate *priv;
1014 	BraseroBurnResult result;
1015 
1016 	priv = BRASERO_JOB_PRIVATE (self);
1017 
1018 	BRASERO_JOB_LOG (self, "Finished successfully session");
1019 
1020 	if (brasero_job_is_last_active (self))
1021 		return brasero_task_ctx_finished (priv->ctx);
1022 
1023 	if (!brasero_job_is_first_active (self)) {
1024 		/* This job is apparently a go between job.
1025 		 * It should only call for a stop on an error. */
1026 		BRASERO_JOB_LOG (self, "is not a leader");
1027 		error = g_error_new (BRASERO_BURN_ERROR,
1028 				     BRASERO_BURN_ERROR_PLUGIN_MISBEHAVIOR,
1029 				     _("\"%s\" did not behave properly"),
1030 				     G_OBJECT_TYPE_NAME (self));
1031 		return brasero_task_ctx_error (priv->ctx,
1032 					       BRASERO_BURN_ERR,
1033 					       error);
1034 	}
1035 
1036 	/* call the stop method of the job since it's finished */
1037 	klass = BRASERO_JOB_GET_CLASS (self);
1038 	if (klass->stop) {
1039 		result = klass->stop (self, &error);
1040 		if (result != BRASERO_BURN_OK)
1041 			return brasero_task_ctx_error (priv->ctx,
1042 						       result,
1043 						       error);
1044 	}
1045 
1046 	/* this job is finished but it's not the leader so
1047 	 * the task is not finished. Close the pipe on
1048 	 * one side to let the next job know that there
1049 	 * isn't any more data to be expected */
1050 	result = brasero_job_disconnect (self, &error);
1051 	g_object_unref (priv->ctx);
1052 	priv->ctx = NULL;
1053 
1054 	if (result != BRASERO_BURN_OK)
1055 		return brasero_task_ctx_error (priv->ctx,
1056 					       result,
1057 					       error);
1058 
1059 	return BRASERO_BURN_OK;
1060 }
1061 
1062 BraseroBurnResult
brasero_job_finished_track(BraseroJob * self)1063 brasero_job_finished_track (BraseroJob *self)
1064 {
1065 	GError *error = NULL;
1066 	BraseroJobPrivate *priv;
1067 	BraseroBurnResult result;
1068 
1069 	priv = BRASERO_JOB_PRIVATE (self);
1070 
1071 	BRASERO_JOB_LOG (self, "Finished track successfully");
1072 
1073 	/* we first check if it's the first job */
1074 	if (brasero_job_is_first_active (self)) {
1075 		BraseroJobClass *klass;
1076 
1077 		/* call ::stop for the job since it's finished */
1078 		klass = BRASERO_JOB_GET_CLASS (self);
1079 		if (klass->stop) {
1080 			result = klass->stop (self, &error);
1081 
1082 			if (result != BRASERO_BURN_OK)
1083 				return brasero_task_ctx_error (priv->ctx,
1084 							       result,
1085 							       error);
1086 		}
1087 
1088 		/* see if there is another track to process */
1089 		result = brasero_task_ctx_next_track (priv->ctx);
1090 		if (result == BRASERO_BURN_RETRY) {
1091 			/* there is another track to process: don't close the
1092 			 * input of the next connected job. Leave it active */
1093 			return BRASERO_BURN_OK;
1094 		}
1095 
1096 		if (!brasero_job_is_last_active (self)) {
1097 			/* this job is finished but it's not the leader so the
1098 			 * task is not finished. Close the pipe on one side to
1099 			 * let the next job know that there isn't any more data
1100 			 * to be expected */
1101 			result = brasero_job_disconnect (self, &error);
1102 
1103 			brasero_job_deactivate (self);
1104 
1105 			if (result != BRASERO_BURN_OK)
1106 				return brasero_task_ctx_error (priv->ctx,
1107 							       result,
1108 							       error);
1109 
1110 			return BRASERO_BURN_OK;
1111 		}
1112 	}
1113 	else if (!brasero_job_is_last_active (self)) {
1114 		/* This job is apparently a go between job. It should only call
1115 		 * for a stop on an error. */
1116 		BRASERO_JOB_LOG (self, "is not a leader");
1117 		error = g_error_new (BRASERO_BURN_ERROR,
1118 				     BRASERO_BURN_ERROR_PLUGIN_MISBEHAVIOR,
1119 				     _("\"%s\" did not behave properly"),
1120 				     G_OBJECT_TYPE_NAME (self));
1121 		return brasero_task_ctx_error (priv->ctx, BRASERO_BURN_ERR, error);
1122 	}
1123 
1124 	return brasero_task_ctx_finished (priv->ctx);
1125 }
1126 
1127 /**
1128  * means a job didn't successfully completed its task
1129  */
1130 
1131 BraseroBurnResult
brasero_job_error(BraseroJob * self,GError * error)1132 brasero_job_error (BraseroJob *self, GError *error)
1133 {
1134 	GValue instance_and_params [2];
1135 	BraseroJobPrivate *priv;
1136 	GValue return_value;
1137 
1138 	BRASERO_JOB_DEBUG (self);
1139 
1140 	BRASERO_JOB_LOG (self, "finished with an error");
1141 
1142 	priv = BRASERO_JOB_PRIVATE (self);
1143 
1144 	instance_and_params [0].g_type = 0;
1145 	g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (self));
1146 	g_value_set_instance (instance_and_params, self);
1147 
1148 	instance_and_params [1].g_type = 0;
1149 	g_value_init (instance_and_params + 1, G_TYPE_INT);
1150 
1151 	if (error)
1152 		g_value_set_int (instance_and_params + 1, error->code);
1153 	else
1154 		g_value_set_int (instance_and_params + 1, BRASERO_BURN_ERROR_GENERAL);
1155 
1156 	return_value.g_type = 0;
1157 	g_value_init (&return_value, G_TYPE_INT);
1158 	g_value_set_int (&return_value, BRASERO_BURN_ERR);
1159 
1160 	/* There was an error: signal it. That's mainly done
1161 	 * for BraseroBurnCaps to override the result value */
1162 	g_signal_emitv (instance_and_params,
1163 			brasero_job_signals [ERROR_SIGNAL],
1164 			0,
1165 			&return_value);
1166 
1167 	g_value_unset (instance_and_params);
1168 
1169 	BRASERO_JOB_LOG (self,
1170 			 "asked to stop because of an error\n"
1171 			 "\terror\t\t= %i\n"
1172 			 "\tmessage\t= \"%s\"",
1173 			 error ? error->code:0,
1174 			 error ? error->message:"no message");
1175 
1176 	return brasero_task_ctx_error (priv->ctx, g_value_get_int (&return_value), error);
1177 }
1178 
1179 /**
1180  * Used to retrieve config for a job
1181  * If the parameter is missing for the next 4 functions
1182  * it allows to test if they could be used
1183  */
1184 
1185 BraseroBurnResult
brasero_job_get_fd_in(BraseroJob * self,int * fd_in)1186 brasero_job_get_fd_in (BraseroJob *self, int *fd_in)
1187 {
1188 	BraseroJobPrivate *priv;
1189 
1190 	BRASERO_JOB_DEBUG (self);
1191 
1192 	priv = BRASERO_JOB_PRIVATE (self);
1193 
1194 	if (!priv->input)
1195 		return BRASERO_BURN_ERR;
1196 
1197 	if (!fd_in)
1198 		return BRASERO_BURN_OK;
1199 
1200 	*fd_in = priv->input->in;
1201 	return BRASERO_BURN_OK;
1202 }
1203 
1204 static BraseroBurnResult
brasero_job_set_nonblocking_fd(int fd,GError ** error)1205 brasero_job_set_nonblocking_fd (int fd, GError **error)
1206 {
1207 	long flags = 0;
1208 
1209 	if (fcntl (fd, F_GETFL, &flags) != -1) {
1210 		/* Unfortunately some plugin (mkisofs/genisofs don't like
1211 		 * O_NONBLOCK (which is a shame) so we don't set them
1212 		 * automatically but still offer that possibility. */
1213 		flags |= O_NONBLOCK;
1214 		if (fcntl (fd, F_SETFL, flags) == -1) {
1215 			BRASERO_BURN_LOG ("couldn't set non blocking mode");
1216 			g_set_error (error,
1217 				     BRASERO_BURN_ERROR,
1218 				     BRASERO_BURN_ERROR_GENERAL,
1219 				     _("An internal error occurred"));
1220 			return BRASERO_BURN_ERR;
1221 		}
1222 	}
1223 	else {
1224 		BRASERO_BURN_LOG ("couldn't get pipe flags");
1225 		g_set_error (error,
1226 			     BRASERO_BURN_ERROR,
1227 			     BRASERO_BURN_ERROR_GENERAL,
1228 			     _("An internal error occurred"));
1229 		return BRASERO_BURN_ERR;
1230 	}
1231 
1232 	return BRASERO_BURN_OK;
1233 }
1234 
1235 BraseroBurnResult
brasero_job_set_nonblocking(BraseroJob * self,GError ** error)1236 brasero_job_set_nonblocking (BraseroJob *self,
1237 			     GError **error)
1238 {
1239 	BraseroBurnResult result;
1240 	int fd;
1241 
1242 	BRASERO_JOB_DEBUG (self);
1243 
1244 	fd = -1;
1245 	if (brasero_job_get_fd_in (self, &fd) == BRASERO_BURN_OK) {
1246 		result = brasero_job_set_nonblocking_fd (fd, error);
1247 		if (result != BRASERO_BURN_OK)
1248 			return result;
1249 	}
1250 
1251 	fd = -1;
1252 	if (brasero_job_get_fd_out (self, &fd) == BRASERO_BURN_OK) {
1253 		result = brasero_job_set_nonblocking_fd (fd, error);
1254 		if (result != BRASERO_BURN_OK)
1255 			return result;
1256 	}
1257 
1258 	return BRASERO_BURN_OK;
1259 }
1260 
1261 BraseroBurnResult
brasero_job_get_current_track(BraseroJob * self,BraseroTrack ** track)1262 brasero_job_get_current_track (BraseroJob *self,
1263 			       BraseroTrack **track)
1264 {
1265 	BraseroJobPrivate *priv;
1266 
1267 	BRASERO_JOB_DEBUG (self);
1268 
1269 	priv = BRASERO_JOB_PRIVATE (self);
1270 	if (!track)
1271 		return BRASERO_BURN_OK;
1272 
1273 	return brasero_task_ctx_get_current_track (priv->ctx, track);
1274 }
1275 
1276 BraseroBurnResult
brasero_job_get_done_tracks(BraseroJob * self,GSList ** tracks)1277 brasero_job_get_done_tracks (BraseroJob *self, GSList **tracks)
1278 {
1279 	BraseroJobPrivate *priv;
1280 
1281 	BRASERO_JOB_DEBUG (self);
1282 
1283 	/* tracks already done are those that are in session */
1284 	priv = BRASERO_JOB_PRIVATE (self);
1285 	return brasero_task_ctx_get_stored_tracks (priv->ctx, tracks);
1286 }
1287 
1288 BraseroBurnResult
brasero_job_get_tracks(BraseroJob * self,GSList ** tracks)1289 brasero_job_get_tracks (BraseroJob *self, GSList **tracks)
1290 {
1291 	BraseroJobPrivate *priv;
1292 	BraseroBurnSession *session;
1293 
1294 	BRASERO_JOB_DEBUG (self);
1295 
1296 	g_return_val_if_fail (tracks != NULL, BRASERO_BURN_ERR);
1297 
1298 	priv = BRASERO_JOB_PRIVATE (self);
1299 	session = brasero_task_ctx_get_session (priv->ctx);
1300 	*tracks = brasero_burn_session_get_tracks (session);
1301 	return BRASERO_BURN_OK;
1302 }
1303 
1304 BraseroBurnResult
brasero_job_get_fd_out(BraseroJob * self,int * fd_out)1305 brasero_job_get_fd_out (BraseroJob *self, int *fd_out)
1306 {
1307 	BraseroJobPrivate *priv;
1308 
1309 	BRASERO_JOB_DEBUG (self);
1310 
1311 	priv = BRASERO_JOB_PRIVATE (self);
1312 
1313 	if (!priv->linked)
1314 		return BRASERO_BURN_ERR;
1315 
1316 	if (!fd_out)
1317 		return BRASERO_BURN_OK;
1318 
1319 	priv = BRASERO_JOB_PRIVATE (priv->linked);
1320 	if (!priv->input)
1321 		return BRASERO_BURN_ERR;
1322 
1323 	*fd_out = priv->input->out;
1324 	return BRASERO_BURN_OK;
1325 }
1326 
1327 BraseroBurnResult
brasero_job_get_image_output(BraseroJob * self,gchar ** image,gchar ** toc)1328 brasero_job_get_image_output (BraseroJob *self,
1329 			      gchar **image,
1330 			      gchar **toc)
1331 {
1332 	BraseroJobPrivate *priv;
1333 
1334 	BRASERO_JOB_DEBUG (self);
1335 
1336 	priv = BRASERO_JOB_PRIVATE (self);
1337 
1338 	if (!priv->output)
1339 		return BRASERO_BURN_ERR;
1340 
1341 	if (image)
1342 		*image = g_strdup (priv->output->image);
1343 
1344 	if (toc)
1345 		*toc = g_strdup (priv->output->toc);
1346 
1347 	return BRASERO_BURN_OK;
1348 }
1349 
1350 BraseroBurnResult
brasero_job_get_audio_output(BraseroJob * self,gchar ** path)1351 brasero_job_get_audio_output (BraseroJob *self,
1352 			      gchar **path)
1353 {
1354 	BraseroJobPrivate *priv;
1355 
1356 	BRASERO_JOB_DEBUG (self);
1357 
1358 	priv = BRASERO_JOB_PRIVATE (self);
1359 	if (!priv->output)
1360 		return BRASERO_BURN_ERR;
1361 
1362 	if (path)
1363 		*path = g_strdup (priv->output->image);
1364 
1365 	return BRASERO_BURN_OK;
1366 }
1367 
1368 BraseroBurnResult
brasero_job_get_flags(BraseroJob * self,BraseroBurnFlag * flags)1369 brasero_job_get_flags (BraseroJob *self, BraseroBurnFlag *flags)
1370 {
1371 	BraseroBurnSession *session;
1372 	BraseroJobPrivate *priv;
1373 
1374 	BRASERO_JOB_DEBUG (self);
1375 
1376 	g_return_val_if_fail (flags != NULL, BRASERO_BURN_ERR);
1377 
1378 	priv = BRASERO_JOB_PRIVATE (self);
1379 	session = brasero_task_ctx_get_session (priv->ctx);
1380 	*flags = brasero_burn_session_get_flags (session);
1381 
1382 	return BRASERO_BURN_OK;
1383 }
1384 
1385 BraseroBurnResult
brasero_job_get_input_type(BraseroJob * self,BraseroTrackType * type)1386 brasero_job_get_input_type (BraseroJob *self, BraseroTrackType *type)
1387 {
1388 	BraseroBurnResult result = BRASERO_BURN_OK;
1389 	BraseroJobPrivate *priv;
1390 
1391 	BRASERO_JOB_DEBUG (self);
1392 
1393 	priv = BRASERO_JOB_PRIVATE (self);
1394 	if (!priv->previous) {
1395 		BraseroBurnSession *session;
1396 
1397 		session = brasero_task_ctx_get_session (priv->ctx);
1398 		result = brasero_burn_session_get_input_type (session, type);
1399 	}
1400 	else {
1401 		BraseroJobPrivate *prev_priv;
1402 
1403 		prev_priv = BRASERO_JOB_PRIVATE (priv->previous);
1404 		memcpy (type, &prev_priv->type, sizeof (BraseroTrackType));
1405 		result = BRASERO_BURN_OK;
1406 	}
1407 
1408 	return result;
1409 }
1410 
1411 BraseroBurnResult
brasero_job_get_output_type(BraseroJob * self,BraseroTrackType * type)1412 brasero_job_get_output_type (BraseroJob *self, BraseroTrackType *type)
1413 {
1414 	BraseroJobPrivate *priv;
1415 
1416 	BRASERO_JOB_DEBUG (self);
1417 
1418 	priv = BRASERO_JOB_PRIVATE (self);
1419 
1420 	memcpy (type, &priv->type, sizeof (BraseroTrackType));
1421 	return BRASERO_BURN_OK;
1422 }
1423 
1424 BraseroBurnResult
brasero_job_get_action(BraseroJob * self,BraseroJobAction * action)1425 brasero_job_get_action (BraseroJob *self, BraseroJobAction *action)
1426 {
1427 	BraseroJobPrivate *priv;
1428 	BraseroTaskAction task_action;
1429 
1430 	BRASERO_JOB_DEBUG (self);
1431 
1432 	g_return_val_if_fail (action != NULL, BRASERO_BURN_ERR);
1433 
1434 	priv = BRASERO_JOB_PRIVATE (self);
1435 
1436 	if (!brasero_job_is_last_active (self)) {
1437 		*action = BRASERO_JOB_ACTION_IMAGE;
1438 		return BRASERO_BURN_OK;
1439 	}
1440 
1441 	task_action = brasero_task_ctx_get_action (priv->ctx);
1442 	switch (task_action) {
1443 	case BRASERO_TASK_ACTION_NONE:
1444 		*action = BRASERO_JOB_ACTION_SIZE;
1445 		break;
1446 
1447 	case BRASERO_TASK_ACTION_ERASE:
1448 		*action = BRASERO_JOB_ACTION_ERASE;
1449 		break;
1450 
1451 	case BRASERO_TASK_ACTION_NORMAL:
1452 		if (priv->type.type == BRASERO_TRACK_TYPE_DISC)
1453 			*action = BRASERO_JOB_ACTION_RECORD;
1454 		else
1455 			*action = BRASERO_JOB_ACTION_IMAGE;
1456 		break;
1457 
1458 	case BRASERO_TASK_ACTION_CHECKSUM:
1459 		*action = BRASERO_JOB_ACTION_CHECKSUM;
1460 		break;
1461 
1462 	default:
1463 		*action = BRASERO_JOB_ACTION_NONE;
1464 		break;
1465 	}
1466 
1467 	return BRASERO_BURN_OK;
1468 }
1469 
1470 BraseroBurnResult
brasero_job_get_bus_target_lun(BraseroJob * self,gchar ** BTL)1471 brasero_job_get_bus_target_lun (BraseroJob *self, gchar **BTL)
1472 {
1473 	BraseroBurnSession *session;
1474 	BraseroJobPrivate *priv;
1475 	BraseroDrive *drive;
1476 
1477 	BRASERO_JOB_DEBUG (self);
1478 
1479 	g_return_val_if_fail (BTL != NULL, BRASERO_BURN_ERR);
1480 
1481 	priv = BRASERO_JOB_PRIVATE (self);
1482 	session = brasero_task_ctx_get_session (priv->ctx);
1483 
1484 	drive = brasero_burn_session_get_burner (session);
1485 	*BTL = brasero_drive_get_bus_target_lun_string (drive);
1486 
1487 	return BRASERO_BURN_OK;
1488 }
1489 
1490 BraseroBurnResult
brasero_job_get_device(BraseroJob * self,gchar ** device)1491 brasero_job_get_device (BraseroJob *self, gchar **device)
1492 {
1493 	BraseroBurnSession *session;
1494 	BraseroJobPrivate *priv;
1495 	BraseroDrive *drive;
1496 	const gchar *path;
1497 
1498 	BRASERO_JOB_DEBUG (self);
1499 
1500 	g_return_val_if_fail (device != NULL, BRASERO_BURN_ERR);
1501 
1502 	priv = BRASERO_JOB_PRIVATE (self);
1503 	session = brasero_task_ctx_get_session (priv->ctx);
1504 
1505 	drive = brasero_burn_session_get_burner (session);
1506 	path = brasero_drive_get_device (drive);
1507 	*device = g_strdup (path);
1508 
1509 	return BRASERO_BURN_OK;
1510 }
1511 
1512 BraseroBurnResult
brasero_job_get_media(BraseroJob * self,BraseroMedia * media)1513 brasero_job_get_media (BraseroJob *self, BraseroMedia *media)
1514 {
1515 	BraseroBurnSession *session;
1516 	BraseroJobPrivate *priv;
1517 
1518 	BRASERO_JOB_DEBUG (self);
1519 
1520 	g_return_val_if_fail (media != NULL, BRASERO_BURN_ERR);
1521 
1522 	priv = BRASERO_JOB_PRIVATE (self);
1523 	session = brasero_task_ctx_get_session (priv->ctx);
1524 	*media = brasero_burn_session_get_dest_media (session);
1525 
1526 	return BRASERO_BURN_OK;
1527 }
1528 
1529 BraseroBurnResult
brasero_job_get_medium(BraseroJob * job,BraseroMedium ** medium)1530 brasero_job_get_medium (BraseroJob *job, BraseroMedium **medium)
1531 {
1532 	BraseroBurnSession *session;
1533 	BraseroJobPrivate *priv;
1534 	BraseroDrive *drive;
1535 
1536 	BRASERO_JOB_DEBUG (job);
1537 
1538 	g_return_val_if_fail (medium != NULL, BRASERO_BURN_ERR);
1539 
1540 	priv = BRASERO_JOB_PRIVATE (job);
1541 	session = brasero_task_ctx_get_session (priv->ctx);
1542 	drive = brasero_burn_session_get_burner (session);
1543 	*medium = brasero_drive_get_medium (drive);
1544 
1545 	if (!(*medium))
1546 		return BRASERO_BURN_ERR;
1547 
1548 	g_object_ref (*medium);
1549 	return BRASERO_BURN_OK;
1550 }
1551 
1552 BraseroBurnResult
brasero_job_get_last_session_address(BraseroJob * self,goffset * address)1553 brasero_job_get_last_session_address (BraseroJob *self, goffset *address)
1554 {
1555 	BraseroBurnSession *session;
1556 	BraseroJobPrivate *priv;
1557 	BraseroMedium *medium;
1558 	BraseroDrive *drive;
1559 
1560 	BRASERO_JOB_DEBUG (self);
1561 
1562 	g_return_val_if_fail (address != NULL, BRASERO_BURN_ERR);
1563 
1564 	priv = BRASERO_JOB_PRIVATE (self);
1565 	session = brasero_task_ctx_get_session (priv->ctx);
1566 	drive = brasero_burn_session_get_burner (session);
1567 	medium = brasero_drive_get_medium (drive);
1568 	if (brasero_medium_get_last_data_track_address (medium, NULL, address))
1569 		return BRASERO_BURN_OK;
1570 
1571 	return BRASERO_BURN_ERR;
1572 }
1573 
1574 BraseroBurnResult
brasero_job_get_next_writable_address(BraseroJob * self,goffset * address)1575 brasero_job_get_next_writable_address (BraseroJob *self, goffset *address)
1576 {
1577 	BraseroBurnSession *session;
1578 	BraseroJobPrivate *priv;
1579 	BraseroMedium *medium;
1580 	BraseroDrive *drive;
1581 
1582 	BRASERO_JOB_DEBUG (self);
1583 
1584 	g_return_val_if_fail (address != NULL, BRASERO_BURN_ERR);
1585 
1586 	priv = BRASERO_JOB_PRIVATE (self);
1587 	session = brasero_task_ctx_get_session (priv->ctx);
1588 	drive = brasero_burn_session_get_burner (session);
1589 	medium = brasero_drive_get_medium (drive);
1590 	*address = brasero_medium_get_next_writable_address (medium);
1591 
1592 	return BRASERO_BURN_OK;
1593 }
1594 
1595 BraseroBurnResult
brasero_job_get_rate(BraseroJob * self,guint64 * rate)1596 brasero_job_get_rate (BraseroJob *self, guint64 *rate)
1597 {
1598 	BraseroBurnSession *session;
1599 	BraseroJobPrivate *priv;
1600 
1601 	g_return_val_if_fail (rate != NULL, BRASERO_BURN_ERR);
1602 
1603 	priv = BRASERO_JOB_PRIVATE (self);
1604 	session = brasero_task_ctx_get_session (priv->ctx);
1605 	*rate = brasero_burn_session_get_rate (session);
1606 
1607 	return BRASERO_BURN_OK;
1608 }
1609 
1610 static int
_round_speed(float number)1611 _round_speed (float number)
1612 {
1613 	int retval = (gint) number;
1614 
1615 	/* NOTE: number must always be positive */
1616 	number -= (float) retval;
1617 	if (number >= 0.5)
1618 		return retval + 1;
1619 
1620 	return retval;
1621 }
1622 
1623 BraseroBurnResult
brasero_job_get_speed(BraseroJob * self,guint * speed)1624 brasero_job_get_speed (BraseroJob *self, guint *speed)
1625 {
1626 	BraseroBurnSession *session;
1627 	BraseroJobPrivate *priv;
1628 	BraseroMedia media;
1629 	guint64 rate;
1630 
1631 	BRASERO_JOB_DEBUG (self);
1632 
1633 	g_return_val_if_fail (speed != NULL, BRASERO_BURN_ERR);
1634 
1635 	priv = BRASERO_JOB_PRIVATE (self);
1636 	session = brasero_task_ctx_get_session (priv->ctx);
1637 	rate = brasero_burn_session_get_rate (session);
1638 
1639 	media = brasero_burn_session_get_dest_media (session);
1640 	if (media & BRASERO_MEDIUM_DVD)
1641 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_DVD (rate));
1642 	else if (media & BRASERO_MEDIUM_BD)
1643 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_BD (rate));
1644 	else
1645 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_CD (rate));
1646 
1647 	return BRASERO_BURN_OK;
1648 }
1649 
1650 BraseroBurnResult
brasero_job_get_max_rate(BraseroJob * self,guint64 * rate)1651 brasero_job_get_max_rate (BraseroJob *self, guint64 *rate)
1652 {
1653 	BraseroBurnSession *session;
1654 	BraseroJobPrivate *priv;
1655 	BraseroMedium *medium;
1656 	BraseroDrive *drive;
1657 
1658 	BRASERO_JOB_DEBUG (self);
1659 
1660 	g_return_val_if_fail (rate != NULL, BRASERO_BURN_ERR);
1661 
1662 	priv = BRASERO_JOB_PRIVATE (self);
1663 	session = brasero_task_ctx_get_session (priv->ctx);
1664 
1665 	drive = brasero_burn_session_get_burner (session);
1666 	medium = brasero_drive_get_medium (drive);
1667 
1668 	if (!medium)
1669 		return BRASERO_BURN_NOT_READY;
1670 
1671 	*rate = brasero_medium_get_max_write_speed (medium);
1672 
1673 	return BRASERO_BURN_OK;
1674 }
1675 
1676 BraseroBurnResult
brasero_job_get_max_speed(BraseroJob * self,guint * speed)1677 brasero_job_get_max_speed (BraseroJob *self, guint *speed)
1678 {
1679 	BraseroBurnSession *session;
1680 	BraseroJobPrivate *priv;
1681 	BraseroMedium *medium;
1682 	BraseroDrive *drive;
1683 	BraseroMedia media;
1684 	guint64 rate;
1685 
1686 	BRASERO_JOB_DEBUG (self);
1687 
1688 	g_return_val_if_fail (speed != NULL, BRASERO_BURN_ERR);
1689 
1690 	priv = BRASERO_JOB_PRIVATE (self);
1691 	session = brasero_task_ctx_get_session (priv->ctx);
1692 
1693 	drive = brasero_burn_session_get_burner (session);
1694 	medium = brasero_drive_get_medium (drive);
1695 	if (!medium)
1696 		return BRASERO_BURN_NOT_READY;
1697 
1698 	rate = brasero_medium_get_max_write_speed (medium);
1699 	media = brasero_medium_get_status (medium);
1700 	if (media & BRASERO_MEDIUM_DVD)
1701 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_DVD (rate));
1702 	else if (media & BRASERO_MEDIUM_BD)
1703 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_BD (rate));
1704 	else
1705 		*speed = _round_speed (BRASERO_RATE_TO_SPEED_CD (rate));
1706 
1707 	return BRASERO_BURN_OK;
1708 }
1709 
1710 BraseroBurnResult
brasero_job_get_tmp_file(BraseroJob * self,const gchar * suffix,gchar ** output,GError ** error)1711 brasero_job_get_tmp_file (BraseroJob *self,
1712 			  const gchar *suffix,
1713 			  gchar **output,
1714 			  GError **error)
1715 {
1716 	BraseroBurnSession *session;
1717 	BraseroJobPrivate *priv;
1718 
1719 	priv = BRASERO_JOB_PRIVATE (self);
1720 	session = brasero_task_ctx_get_session (priv->ctx);
1721 	return brasero_burn_session_get_tmp_file (session,
1722 						  suffix,
1723 						  output,
1724 						  error);
1725 }
1726 
1727 BraseroBurnResult
brasero_job_get_tmp_dir(BraseroJob * self,gchar ** output,GError ** error)1728 brasero_job_get_tmp_dir (BraseroJob *self,
1729 			 gchar **output,
1730 			 GError **error)
1731 {
1732 	BraseroBurnSession *session;
1733 	BraseroJobPrivate *priv;
1734 
1735 	BRASERO_JOB_DEBUG (self);
1736 
1737 	priv = BRASERO_JOB_PRIVATE (self);
1738 	session = brasero_task_ctx_get_session (priv->ctx);
1739 	brasero_burn_session_get_tmp_dir (session,
1740 					  output,
1741 					  error);
1742 
1743 	return BRASERO_BURN_OK;
1744 }
1745 
1746 BraseroBurnResult
brasero_job_get_audio_title(BraseroJob * self,gchar ** album)1747 brasero_job_get_audio_title (BraseroJob *self, gchar **album)
1748 {
1749 	BraseroBurnSession *session;
1750 	BraseroJobPrivate *priv;
1751 
1752 	BRASERO_JOB_DEBUG (self);
1753 
1754 	g_return_val_if_fail (album != NULL, BRASERO_BURN_ERR);
1755 
1756 	priv = BRASERO_JOB_PRIVATE (self);
1757 	session = brasero_task_ctx_get_session (priv->ctx);
1758 
1759 	*album = g_strdup (brasero_burn_session_get_label (session));
1760 	return BRASERO_BURN_OK;
1761 }
1762 
1763 BraseroBurnResult
brasero_job_get_data_label(BraseroJob * self,gchar ** label)1764 brasero_job_get_data_label (BraseroJob *self, gchar **label)
1765 {
1766 	BraseroBurnSession *session;
1767 	BraseroJobPrivate *priv;
1768 
1769 	BRASERO_JOB_DEBUG (self);
1770 
1771 	g_return_val_if_fail (label != NULL, BRASERO_BURN_ERR);
1772 
1773 	priv = BRASERO_JOB_PRIVATE (self);
1774 	session = brasero_task_ctx_get_session (priv->ctx);
1775 
1776 	*label = g_strdup (brasero_burn_session_get_label (session));
1777 	return BRASERO_BURN_OK;
1778 }
1779 
1780 BraseroBurnResult
brasero_job_get_session_output_size(BraseroJob * self,goffset * blocks,goffset * bytes)1781 brasero_job_get_session_output_size (BraseroJob *self,
1782 				     goffset *blocks,
1783 				     goffset *bytes)
1784 {
1785 	BraseroJobPrivate *priv;
1786 
1787 	BRASERO_JOB_DEBUG (self);
1788 
1789 	priv = BRASERO_JOB_PRIVATE (self);
1790 	return brasero_task_ctx_get_session_output_size (priv->ctx, blocks, bytes);
1791 }
1792 
1793 /**
1794  * Starts task internal timer
1795  */
1796 
1797 BraseroBurnResult
brasero_job_start_progress(BraseroJob * self,gboolean force)1798 brasero_job_start_progress (BraseroJob *self,
1799 			    gboolean force)
1800 {
1801 	BraseroJobPrivate *priv;
1802 
1803 	/* Turn this off as otherwise it floods bug reports */
1804 	// BRASERO_JOB_DEBUG (self);
1805 
1806 	priv = BRASERO_JOB_PRIVATE (self);
1807 	if (priv->next)
1808 		return BRASERO_BURN_NOT_RUNNING;
1809 
1810 	return brasero_task_ctx_start_progress (priv->ctx, force);
1811 }
1812 
1813 BraseroBurnResult
brasero_job_reset_progress(BraseroJob * self)1814 brasero_job_reset_progress (BraseroJob *self)
1815 {
1816 	BraseroJobPrivate *priv;
1817 
1818 	priv = BRASERO_JOB_PRIVATE (self);
1819 	if (priv->next)
1820 		return BRASERO_BURN_ERR;
1821 
1822 	return brasero_task_ctx_reset_progress (priv->ctx);
1823 }
1824 
1825 /**
1826  * these should be used to set the different values of the task by the jobs
1827  */
1828 
1829 BraseroBurnResult
brasero_job_set_progress(BraseroJob * self,gdouble progress)1830 brasero_job_set_progress (BraseroJob *self,
1831 			  gdouble progress)
1832 {
1833 	BraseroJobPrivate *priv;
1834 
1835 	/* Turn this off as it floods bug reports */
1836 	//BRASERO_JOB_LOG (self, "Called brasero_job_set_progress (%lf)", progress);
1837 
1838 	priv = BRASERO_JOB_PRIVATE (self);
1839 	if (priv->next)
1840 		return BRASERO_BURN_ERR;
1841 
1842 	if (progress < 0.0 || progress > 1.0) {
1843 		BRASERO_JOB_LOG (self, "Tried to set an insane progress value (%lf)", progress);
1844 		return BRASERO_BURN_ERR;
1845 	}
1846 
1847 	return brasero_task_ctx_set_progress (priv->ctx, progress);
1848 }
1849 
1850 BraseroBurnResult
brasero_job_set_current_action(BraseroJob * self,BraseroBurnAction action,const gchar * string,gboolean force)1851 brasero_job_set_current_action (BraseroJob *self,
1852 				BraseroBurnAction action,
1853 				const gchar *string,
1854 				gboolean force)
1855 {
1856 	BraseroJobPrivate *priv;
1857 
1858 	BRASERO_JOB_DEBUG (self);
1859 
1860 	priv = BRASERO_JOB_PRIVATE (self);
1861 	if (!brasero_job_is_last_active (self))
1862 		return BRASERO_BURN_NOT_RUNNING;
1863 
1864 	return brasero_task_ctx_set_current_action (priv->ctx,
1865 						    action,
1866 						    string,
1867 						    force);
1868 }
1869 
1870 BraseroBurnResult
brasero_job_get_current_action(BraseroJob * self,BraseroBurnAction * action)1871 brasero_job_get_current_action (BraseroJob *self,
1872 				BraseroBurnAction *action)
1873 {
1874 	BraseroJobPrivate *priv;
1875 
1876 	BRASERO_JOB_DEBUG (self);
1877 
1878 	g_return_val_if_fail (action != NULL, BRASERO_BURN_ERR);
1879 
1880 	priv = BRASERO_JOB_PRIVATE (self);
1881 
1882 	if (!priv->ctx) {
1883 		BRASERO_JOB_LOG (self,
1884 				 "called %s whereas it wasn't running",
1885 				 G_STRFUNC);
1886 		return BRASERO_BURN_NOT_RUNNING;
1887 	}
1888 
1889 	return brasero_task_ctx_get_current_action (priv->ctx, action);
1890 }
1891 
1892 BraseroBurnResult
brasero_job_set_rate(BraseroJob * self,gint64 rate)1893 brasero_job_set_rate (BraseroJob *self,
1894 		      gint64 rate)
1895 {
1896 	BraseroJobPrivate *priv;
1897 
1898 	/* Turn this off as otherwise it floods bug reports */
1899 	// BRASERO_JOB_DEBUG (self);
1900 
1901 	priv = BRASERO_JOB_PRIVATE (self);
1902 	if (priv->next)
1903 		return BRASERO_BURN_NOT_RUNNING;
1904 
1905 	return brasero_task_ctx_set_rate (priv->ctx, rate);
1906 }
1907 
1908 BraseroBurnResult
brasero_job_set_output_size_for_current_track(BraseroJob * self,goffset sectors,goffset bytes)1909 brasero_job_set_output_size_for_current_track (BraseroJob *self,
1910 					       goffset sectors,
1911 					       goffset bytes)
1912 {
1913 	BraseroJobPrivate *priv;
1914 
1915 	/* this function can only be used by the last job which is not recording
1916 	 * all other jobs trying to set this value will be ignored.
1917 	 * It should be used mostly during a fake running. This value is stored
1918 	 * by the task context as the amount of bytes/blocks produced by a task.
1919 	 * That's why it's not possible to set the DATA type number of files.
1920 	 * NOTE: the values passed on by this function to context may be added
1921 	 * to other when there are multiple tracks. */
1922 	BRASERO_JOB_DEBUG (self);
1923 
1924 	priv = BRASERO_JOB_PRIVATE (self);
1925 
1926 	if (!brasero_job_is_last_active (self))
1927 		return BRASERO_BURN_ERR;
1928 
1929 	return brasero_task_ctx_set_output_size_for_current_track (priv->ctx,
1930 								   sectors,
1931 								   bytes);
1932 }
1933 
1934 BraseroBurnResult
brasero_job_set_written_track(BraseroJob * self,goffset written)1935 brasero_job_set_written_track (BraseroJob *self,
1936 			       goffset written)
1937 {
1938 	BraseroJobPrivate *priv;
1939 
1940 	/* Turn this off as otherwise it floods bug reports */
1941 	// BRASERO_JOB_DEBUG (self);
1942 
1943 	priv = BRASERO_JOB_PRIVATE (self);
1944 	if (priv->next)
1945 		return BRASERO_BURN_NOT_RUNNING;
1946 
1947 	return brasero_task_ctx_set_written_track (priv->ctx, written);
1948 }
1949 
1950 BraseroBurnResult
brasero_job_set_written_session(BraseroJob * self,goffset written)1951 brasero_job_set_written_session (BraseroJob *self,
1952 				 goffset written)
1953 {
1954 	BraseroJobPrivate *priv;
1955 
1956 	/* Turn this off as otherwise it floods bug reports */
1957 	// BRASERO_JOB_DEBUG (self);
1958 
1959 	priv = BRASERO_JOB_PRIVATE (self);
1960 	if (priv->next)
1961 		return BRASERO_BURN_NOT_RUNNING;
1962 
1963 	return brasero_task_ctx_set_written_session (priv->ctx, written);
1964 }
1965 
1966 BraseroBurnResult
brasero_job_set_use_average_rate(BraseroJob * self,gboolean value)1967 brasero_job_set_use_average_rate (BraseroJob *self, gboolean value)
1968 {
1969 	BraseroJobPrivate *priv;
1970 
1971 	BRASERO_JOB_DEBUG (self);
1972 
1973 	priv = BRASERO_JOB_PRIVATE (self);
1974 	if (priv->next)
1975 		return BRASERO_BURN_NOT_RUNNING;
1976 
1977 	return brasero_task_ctx_set_use_average (priv->ctx, value);
1978 }
1979 
1980 void
brasero_job_set_dangerous(BraseroJob * self,gboolean value)1981 brasero_job_set_dangerous (BraseroJob *self, gboolean value)
1982 {
1983 	BraseroJobPrivate *priv;
1984 
1985 	BRASERO_JOB_DEBUG (self);
1986 
1987 	priv = BRASERO_JOB_PRIVATE (self);
1988 	if (priv->ctx)
1989 		brasero_task_ctx_set_dangerous (priv->ctx, value);
1990 }
1991 
1992 /**
1993  * used for debugging
1994  */
1995 
1996 void
brasero_job_log_message(BraseroJob * self,const gchar * location,const gchar * format,...)1997 brasero_job_log_message (BraseroJob *self,
1998 			 const gchar *location,
1999 			 const gchar *format,
2000 			 ...)
2001 {
2002 	va_list arg_list;
2003 	BraseroJobPrivate *priv;
2004 	BraseroBurnSession *session;
2005 
2006 	g_return_if_fail (BRASERO_IS_JOB (self));
2007 	g_return_if_fail (format != NULL);
2008 
2009 	priv = BRASERO_JOB_PRIVATE (self);
2010 	session = brasero_task_ctx_get_session (priv->ctx);
2011 
2012 	va_start (arg_list, format);
2013 	brasero_burn_session_logv (session, format, arg_list);
2014 	va_end (arg_list);
2015 
2016 	va_start (arg_list, format);
2017 	brasero_burn_debug_messagev (location, format, arg_list);
2018 	va_end (arg_list);
2019 }
2020 
2021 /**
2022  * Object creation stuff
2023  */
2024 
2025 static void
brasero_job_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2026 brasero_job_get_property (GObject *object,
2027 			  guint prop_id,
2028 			  GValue *value,
2029 			  GParamSpec *pspec)
2030 {
2031 	BraseroJobPrivate *priv;
2032 	BraseroTrackType *ptr;
2033 
2034 	priv = BRASERO_JOB_PRIVATE (object);
2035 
2036 	switch (prop_id) {
2037 	case PROP_OUTPUT:
2038 		ptr = g_value_get_pointer (value);
2039 		memcpy (ptr, &priv->type, sizeof (BraseroTrackType));
2040 		break;
2041 	default:
2042 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2043 		break;
2044 	}
2045 }
2046 
2047 static void
brasero_job_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2048 brasero_job_set_property (GObject *object,
2049 			  guint prop_id,
2050 			  const GValue *value,
2051 			  GParamSpec *pspec)
2052 {
2053 	BraseroJobPrivate *priv;
2054 	BraseroTrackType *ptr;
2055 
2056 	priv = BRASERO_JOB_PRIVATE (object);
2057 
2058 	switch (prop_id) {
2059 	case PROP_OUTPUT:
2060 		ptr = g_value_get_pointer (value);
2061 		if (!ptr) {
2062 			priv->type.type = BRASERO_TRACK_TYPE_NONE;
2063 			priv->type.subtype.media = BRASERO_MEDIUM_NONE;
2064 		}
2065 		else
2066 			memcpy (&priv->type, ptr, sizeof (BraseroTrackType));
2067 		break;
2068 	default:
2069 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2070 		break;
2071 	}
2072 }
2073 
2074 static void
brasero_job_finalize(GObject * object)2075 brasero_job_finalize (GObject *object)
2076 {
2077 	BraseroJobPrivate *priv;
2078 
2079 	priv = BRASERO_JOB_PRIVATE (object);
2080 
2081 	if (priv->ctx) {
2082 		g_object_unref (priv->ctx);
2083 		priv->ctx = NULL;
2084 	}
2085 
2086 	if (priv->previous) {
2087 		g_object_unref (priv->previous);
2088 		priv->previous = NULL;
2089 	}
2090 
2091 	if (priv->input) {
2092 		brasero_job_input_free (priv->input);
2093 		priv->input = NULL;
2094 	}
2095 
2096 	if (priv->linked)
2097 		priv->linked = NULL;
2098 
2099 	if (priv->output) {
2100 		brasero_job_output_free (priv->output);
2101 		priv->output = NULL;
2102 	}
2103 
2104 	G_OBJECT_CLASS (parent_class)->finalize (object);
2105 }
2106 
2107 static void
brasero_job_class_init(BraseroJobClass * klass)2108 brasero_job_class_init (BraseroJobClass *klass)
2109 {
2110 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
2111 
2112 	g_type_class_add_private (klass, sizeof (BraseroJobPrivate));
2113 
2114 	parent_class = g_type_class_peek_parent (klass);
2115 	object_class->finalize = brasero_job_finalize;
2116 	object_class->set_property = brasero_job_set_property;
2117 	object_class->get_property = brasero_job_get_property;
2118 
2119 	brasero_job_signals [ERROR_SIGNAL] =
2120 	    g_signal_new ("error",
2121 			  G_TYPE_FROM_CLASS (klass),
2122 			  G_SIGNAL_RUN_LAST|G_SIGNAL_NO_RECURSE,
2123 			  G_STRUCT_OFFSET (BraseroJobClass, error),
2124 			  NULL, NULL,
2125 			  brasero_marshal_INT__INT,
2126 			  G_TYPE_INT, 1, G_TYPE_INT);
2127 
2128 	g_object_class_install_property (object_class,
2129 					 PROP_OUTPUT,
2130 					 g_param_spec_pointer ("output",
2131 							       "The type the job must output",
2132 							       "The type the job must output",
2133 							       G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
2134 }
2135 
2136 static void
brasero_job_init(BraseroJob * obj)2137 brasero_job_init (BraseroJob *obj)
2138 { }
2139