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 <glib.h>
36 #include <glib-object.h>
37 #include <glib/gi18n-lib.h>
38
39 #include <gdk/gdk.h>
40
41 #include "burn-basics.h"
42 #include "burn-debug.h"
43 #include "brasero-session.h"
44 #include "burn-task.h"
45 #include "burn-task-item.h"
46 #include "burn-task-ctx.h"
47
48 #include "brasero-track-image.h"
49 #include "brasero-track-stream.h"
50
51 static void brasero_task_class_init (BraseroTaskClass *klass);
52 static void brasero_task_init (BraseroTask *sp);
53 static void brasero_task_finalize (GObject *object);
54
55 typedef struct _BraseroTaskPrivate BraseroTaskPrivate;
56
57 struct _BraseroTaskPrivate {
58 /* The loop for the task */
59 GMainLoop *loop;
60
61 /* used to poll for progress (every 0.5 sec) */
62 gint clock_id;
63
64 BraseroTaskItem *leader;
65 BraseroTaskItem *first;
66
67 /* result of the task */
68 BraseroBurnResult retval;
69 GError *error;
70 };
71
72 #define BRASERO_TASK_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_TASK, BraseroTaskPrivate))
73 G_DEFINE_TYPE (BraseroTask, brasero_task, BRASERO_TYPE_TASK_CTX);
74
75 static GObjectClass *parent_class = NULL;
76
77 #define MAX_JOB_START_ATTEMPTS 5
78 #define JOB_ATTEMPTS_WAIT_TIME 1
79
80 void
brasero_task_add_item(BraseroTask * task,BraseroTaskItem * item)81 brasero_task_add_item (BraseroTask *task, BraseroTaskItem *item)
82 {
83 BraseroTaskPrivate *priv;
84
85 g_return_if_fail (BRASERO_IS_TASK (task));
86 g_return_if_fail (BRASERO_IS_TASK_ITEM (item));
87
88 priv = BRASERO_TASK_PRIVATE (task);
89
90 if (priv->leader) {
91 brasero_task_item_link (priv->leader, item);
92 g_object_unref (priv->leader);
93 }
94
95 if (!priv->first)
96 priv->first = item;
97
98 priv->leader = item;
99 g_object_ref (priv->leader);
100 }
101
102 static void
brasero_task_reset_real(BraseroTask * task)103 brasero_task_reset_real (BraseroTask *task)
104 {
105 BraseroTaskPrivate *priv;
106
107 priv = BRASERO_TASK_PRIVATE (task);
108
109 if (priv->loop)
110 g_main_loop_unref (priv->loop);
111
112 priv->loop = NULL;
113 priv->clock_id = 0;
114 priv->retval = BRASERO_BURN_OK;
115
116 if (priv->error) {
117 g_error_free (priv->error);
118 priv->error = NULL;
119 }
120
121 brasero_task_ctx_reset (BRASERO_TASK_CTX (task));
122 }
123
124 void
brasero_task_reset(BraseroTask * task)125 brasero_task_reset (BraseroTask *task)
126 {
127 BraseroTaskPrivate *priv;
128
129 priv = BRASERO_TASK_PRIVATE (task);
130
131 if (brasero_task_is_running (task))
132 brasero_task_cancel (task, TRUE);
133
134 g_object_unref (priv->leader);
135 brasero_task_reset_real (task);
136 }
137
138 static gboolean
brasero_task_clock_tick(gpointer data)139 brasero_task_clock_tick (gpointer data)
140 {
141 BraseroTask *task = BRASERO_TASK (data);
142 BraseroTaskPrivate *priv;
143 BraseroTaskItem *item;
144
145 priv = BRASERO_TASK_PRIVATE (task);
146
147 /* some jobs need to be called periodically to update their status
148 * because the main process run in a thread. We do it before calling
149 * progress/action changed so they can update the task on time */
150 for (item = priv->leader; item; item = brasero_task_item_previous (item)) {
151 BraseroTaskItemIFace *klass;
152
153 klass = BRASERO_TASK_ITEM_GET_CLASS (item);
154 if (klass->clock_tick)
155 klass->clock_tick (item, BRASERO_TASK_CTX (task), NULL);
156 }
157
158 /* now call ctx to update progress */
159 brasero_task_ctx_report_progress (BRASERO_TASK_CTX (data));
160
161 return TRUE;
162 }
163
164 /**
165 * Used to run/stop task
166 */
167
168 static BraseroBurnResult
brasero_task_deactivate_item(BraseroTask * task,BraseroTaskItem * item,GError ** error)169 brasero_task_deactivate_item (BraseroTask *task,
170 BraseroTaskItem *item,
171 GError **error)
172 {
173 BraseroBurnResult result = BRASERO_BURN_OK;
174 BraseroTaskItemIFace *klass;
175
176 if (!brasero_task_item_is_active (item)) {
177 BRASERO_BURN_LOG ("%s already stopped", G_OBJECT_TYPE_NAME (item));
178 return BRASERO_BURN_OK;
179 }
180
181 /* stop task for real now */
182 BRASERO_BURN_LOG ("stopping %s", G_OBJECT_TYPE_NAME (item));
183
184 klass = BRASERO_TASK_ITEM_GET_CLASS (item);
185 if (klass->stop)
186 result = klass->stop (item,
187 BRASERO_TASK_CTX (task),
188 error);
189
190 BRASERO_BURN_LOG ("stopped %s", G_OBJECT_TYPE_NAME (item));
191 return result;
192 }
193
194 static BraseroBurnResult
brasero_task_send_stop_signal(BraseroTask * task,BraseroBurnResult retval,GError ** error)195 brasero_task_send_stop_signal (BraseroTask *task,
196 BraseroBurnResult retval,
197 GError **error)
198 {
199 BraseroTaskItem *item;
200 BraseroTaskPrivate *priv;
201 GError *local_error = NULL;
202 BraseroBurnResult result = retval;
203
204 priv = BRASERO_TASK_PRIVATE (task);
205
206 item = priv->leader;
207 while (brasero_task_item_previous (item))
208 item = brasero_task_item_previous (item);
209
210 /* we stop all the slaves first and then go up the list */
211 for (; item; item = brasero_task_item_next (item)) {
212 GError *item_error;
213
214 item_error = NULL;
215
216 /* stop task for real now */
217 result = brasero_task_deactivate_item (task, item, &item_error);
218 if (item_error) {
219 g_error_free (local_error);
220 local_error = item_error;
221 }
222 }
223
224 if (local_error) {
225 if (error && *error == NULL)
226 g_propagate_error (error, local_error);
227 else
228 g_error_free (local_error);
229 }
230
231 /* we don't want to lose the original result if it was not OK */
232 return (result == BRASERO_BURN_OK? retval:result);
233 }
234
235 static gboolean
brasero_task_wakeup(gpointer user_data)236 brasero_task_wakeup (gpointer user_data)
237 {
238 BraseroTaskPrivate *priv;
239
240 priv = BRASERO_TASK_PRIVATE (user_data);
241
242 if (priv->loop)
243 g_main_loop_quit (priv->loop);
244
245 priv->clock_id = 0;
246 priv->retval = BRASERO_BURN_OK;
247 return FALSE;
248 }
249
250 static BraseroBurnResult
brasero_task_sleep(BraseroTask * self,guint sec)251 brasero_task_sleep (BraseroTask *self, guint sec)
252 {
253 BraseroTaskPrivate *priv;
254
255 priv = BRASERO_TASK_PRIVATE (self);
256
257 BRASERO_BURN_LOG ("wait loop");
258
259 priv->loop = g_main_loop_new (NULL, FALSE);
260 priv->clock_id = g_timeout_add_seconds (sec,
261 brasero_task_wakeup,
262 self);
263
264 GDK_THREADS_LEAVE ();
265 g_main_loop_run (priv->loop);
266 GDK_THREADS_ENTER ();
267
268 g_main_loop_unref (priv->loop);
269 priv->loop = NULL;
270
271 if (priv->clock_id) {
272 g_source_remove (priv->clock_id);
273 priv->clock_id = 0;
274 }
275
276 return priv->retval;
277 }
278
279 static BraseroBurnResult
brasero_task_start_item(BraseroTask * task,BraseroTaskItem * item,GError ** error)280 brasero_task_start_item (BraseroTask *task,
281 BraseroTaskItem *item,
282 GError **error)
283 {
284 guint attempts = 0;
285 BraseroBurnResult result;
286 GError *ret_error = NULL;
287 BraseroTaskItemIFace *klass;
288
289 klass = BRASERO_TASK_ITEM_GET_CLASS (item);
290 if (!klass->start)
291 return BRASERO_BURN_ERR;
292
293 BRASERO_BURN_LOG ("::start method %s", G_OBJECT_TYPE_NAME (item));
294
295 result = klass->start (item, &ret_error);
296 while (result == BRASERO_BURN_RETRY) {
297 /* FIXME: a GError?? */
298 if (attempts >= MAX_JOB_START_ATTEMPTS) {
299 if (ret_error)
300 g_propagate_error (error, ret_error);
301
302 return BRASERO_BURN_ERR;
303 }
304
305 if (ret_error) {
306 g_error_free (ret_error);
307 ret_error = NULL;
308 }
309
310 result = brasero_task_sleep (task, 1);
311 if (result != BRASERO_BURN_OK)
312 return result;
313
314 attempts ++;
315 result = klass->start (item, &ret_error);
316 }
317
318 if (ret_error)
319 g_propagate_error (error, ret_error);
320
321 return result;
322 }
323
324 static BraseroBurnResult
brasero_task_activate_item(BraseroTask * task,BraseroTaskItem * item,GError ** error)325 brasero_task_activate_item (BraseroTask *task,
326 BraseroTaskItem *item,
327 GError **error)
328 {
329 BraseroTaskItemIFace *klass;
330 BraseroBurnResult result = BRASERO_BURN_OK;
331
332 klass = BRASERO_TASK_ITEM_GET_CLASS (item);
333 if (!klass->activate)
334 return BRASERO_BURN_ERR;
335
336 BRASERO_BURN_LOG ("::activate method %s", G_OBJECT_TYPE_NAME (item));
337
338 result = klass->activate (item, BRASERO_TASK_CTX (task), error);
339 return result;
340 }
341
342 static void
brasero_task_stop(BraseroTask * task,BraseroBurnResult retval,GError * error)343 brasero_task_stop (BraseroTask *task,
344 BraseroBurnResult retval,
345 GError *error)
346 {
347 BraseroBurnResult result;
348 BraseroTaskPrivate *priv;
349
350 priv = BRASERO_TASK_PRIVATE (task);
351
352 /* brasero_job_error/brasero_job_finished ()
353 * should not be called during ::init and ::start.
354 * Instead a job should return errors directly */
355 result = brasero_task_send_stop_signal (task, retval, &error);
356
357 priv->retval = retval;
358 priv->error = error;
359
360 if (priv->loop && g_main_loop_is_running (priv->loop))
361 g_main_loop_quit (priv->loop);
362 else
363 BRASERO_BURN_LOG ("task was asked to stop (%i/%i) during ::init or ::start",
364 result, retval);
365 }
366
367 BraseroBurnResult
brasero_task_cancel(BraseroTask * task,gboolean protect)368 brasero_task_cancel (BraseroTask *task,
369 gboolean protect)
370 {
371 if (protect && brasero_task_ctx_get_dangerous (BRASERO_TASK_CTX (task)))
372 return BRASERO_BURN_DANGEROUS;
373
374 brasero_task_stop (task, BRASERO_BURN_CANCEL, NULL);
375 return BRASERO_BURN_OK;
376 }
377
378 gboolean
brasero_task_is_running(BraseroTask * task)379 brasero_task_is_running (BraseroTask *task)
380 {
381 BraseroTaskPrivate *priv;
382
383 priv = BRASERO_TASK_PRIVATE (task);
384 return (priv->loop && g_main_loop_is_running (priv->loop));
385 }
386
387 static void
brasero_task_finished(BraseroTaskCtx * ctx,BraseroBurnResult retval,GError * error)388 brasero_task_finished (BraseroTaskCtx *ctx,
389 BraseroBurnResult retval,
390 GError *error)
391 {
392 BraseroTask *self;
393 BraseroTaskPrivate *priv;
394
395 self = BRASERO_TASK (ctx);
396 priv = BRASERO_TASK_PRIVATE (self);
397
398 /* see if we have really started a loop */
399 /* FIXME: shouldn't it be an error if it is called
400 * while the loop is not running ? */
401 if (!brasero_task_is_running (self))
402 return;
403
404 if (retval == BRASERO_BURN_RETRY) {
405 BraseroTaskItem *item;
406 GError *error_item = NULL;
407
408 /* There are some tracks left, get the first
409 * task item and restart it. */
410 item = priv->leader;
411 while (brasero_task_item_previous (item))
412 item = brasero_task_item_previous (item);
413
414 if (brasero_task_item_start (item, &error_item) != BRASERO_BURN_OK)
415 brasero_task_stop (self, BRASERO_BURN_ERR, error_item);
416
417 return;
418 }
419
420 brasero_task_stop (self, retval, error);
421 }
422
423 static BraseroBurnResult
brasero_task_run_loop(BraseroTask * self,GError ** error)424 brasero_task_run_loop (BraseroTask *self,
425 GError **error)
426 {
427 BraseroTaskPrivate *priv;
428
429 priv = BRASERO_TASK_PRIVATE (self);
430
431 brasero_task_ctx_report_progress (BRASERO_TASK_CTX (self));
432
433 priv->clock_id = g_timeout_add (500,
434 brasero_task_clock_tick,
435 self);
436
437 priv->loop = g_main_loop_new (NULL, FALSE);
438
439 BRASERO_BURN_LOG ("entering loop");
440
441 GDK_THREADS_LEAVE ();
442 g_main_loop_run (priv->loop);
443 GDK_THREADS_ENTER ();
444
445 BRASERO_BURN_LOG ("got out of loop");
446 g_main_loop_unref (priv->loop);
447 priv->loop = NULL;
448
449 if (priv->error) {
450 g_propagate_error (error, priv->error);
451 priv->error = NULL;
452 }
453
454 /* stop all progress reporting thing */
455 if (priv->clock_id) {
456 g_source_remove (priv->clock_id);
457 priv->clock_id = 0;
458 }
459
460 if (priv->retval == BRASERO_BURN_OK
461 && brasero_task_ctx_get_progress (BRASERO_TASK_CTX (self), NULL) == BRASERO_BURN_OK) {
462 brasero_task_ctx_set_progress (BRASERO_TASK_CTX (self), 1.0);
463 brasero_task_ctx_report_progress (BRASERO_TASK_CTX (self));
464 }
465
466 brasero_task_ctx_stop_progress (BRASERO_TASK_CTX (self));
467 return priv->retval;
468 }
469
470 static BraseroBurnResult
brasero_task_set_track_output_size_default(BraseroTask * self,GError ** error)471 brasero_task_set_track_output_size_default (BraseroTask *self,
472 GError **error)
473 {
474 BraseroTrack *track = NULL;
475
476 BRASERO_BURN_LOG ("Trying to set a default output size");
477
478 brasero_task_ctx_get_current_track (BRASERO_TASK_CTX (self), &track);
479 // BRASERO_BURN_LOG_TYPE (&input, "Track type");
480
481 if (BRASERO_IS_TRACK_IMAGE (track)
482 || BRASERO_IS_TRACK_STREAM (track)) {
483 BraseroBurnResult result;
484 goffset sectors = 0;
485 goffset bytes = 0;
486
487 result = brasero_track_get_size (track,
488 §ors,
489 &bytes);
490 if (result != BRASERO_BURN_OK)
491 return result;
492
493 BRASERO_BURN_LOG ("Got a default image or stream track length %lli", sectors);
494 brasero_task_ctx_set_output_size_for_current_track (BRASERO_TASK_CTX (self),
495 sectors,
496 bytes);
497 }
498
499 return BRASERO_BURN_OK;
500 }
501
502 static BraseroBurnResult
brasero_task_activate_items(BraseroTask * self,GError ** error)503 brasero_task_activate_items (BraseroTask *self,
504 GError **error)
505 {
506 BraseroTaskPrivate *priv;
507 BraseroBurnResult retval;
508 BraseroTaskItem *item;
509
510 priv = BRASERO_TASK_PRIVATE (self);
511
512 retval = BRASERO_BURN_NOT_RUNNING;
513 for (item = priv->first; item; item = brasero_task_item_next (item)) {
514 BraseroBurnResult result;
515
516 result = brasero_task_activate_item (self, item, error);
517 if (result == BRASERO_BURN_NOT_RUNNING) {
518 BRASERO_BURN_LOG ("::start skipped for %s",
519 G_OBJECT_TYPE_NAME (item));
520 continue;
521 }
522
523 if (result != BRASERO_BURN_OK)
524 return result;
525
526 retval = BRASERO_BURN_OK;
527 }
528
529 return retval;
530 }
531
532 static BraseroBurnResult
brasero_task_start_items(BraseroTask * self,GError ** error)533 brasero_task_start_items (BraseroTask *self,
534 GError **error)
535 {
536 BraseroBurnResult retval;
537 BraseroTaskPrivate *priv;
538 BraseroTaskItem *item;
539
540 priv = BRASERO_TASK_PRIVATE (self);
541
542 /* start from the master down to the slave */
543 retval = BRASERO_BURN_NOT_SUPPORTED;
544 for (item = priv->leader; item; item = brasero_task_item_previous (item)) {
545 BraseroBurnResult result;
546
547 if (!brasero_task_item_is_active (item))
548 continue;
549
550 result = brasero_task_start_item (self, item, error);
551 if (result == BRASERO_BURN_NOT_SUPPORTED) {
552 BRASERO_BURN_LOG ("%s doesn't support action",
553 G_OBJECT_TYPE_NAME (item));
554
555 /* "fake mode" to get size. Forgive the jobs that cannot
556 * retrieve the size for one track. Just deactivate and
557 * go on with the next.
558 * NOTE: after this result the job is no longer active */
559 continue;
560 }
561
562 /* if the following is true don't stop everything */
563 if (result == BRASERO_BURN_NOT_RUNNING)
564 return result;
565
566 if (result != BRASERO_BURN_OK)
567 return result;
568
569 retval = BRASERO_BURN_OK;
570 }
571
572 if (retval == BRASERO_BURN_NOT_SUPPORTED) {
573 /* if all jobs did not want/could not run then resort to a
574 * default function and return BRASERO_BURN_NOT_RUNNING */
575 retval = brasero_task_set_track_output_size_default (self, error);
576 if (retval != BRASERO_BURN_OK)
577 return retval;
578
579 return BRASERO_BURN_NOT_RUNNING;
580 }
581
582 return brasero_task_run_loop (self, error);
583 }
584
585 static BraseroBurnResult
brasero_task_start(BraseroTask * self,gboolean fake,GError ** error)586 brasero_task_start (BraseroTask *self,
587 gboolean fake,
588 GError **error)
589 {
590 BraseroBurnResult result = BRASERO_BURN_OK;
591 BraseroTaskPrivate *priv;
592
593 priv = BRASERO_TASK_PRIVATE (self);
594
595 BRASERO_BURN_LOG ("Starting %s task (%i)",
596 fake ? "fake":"normal",
597 brasero_task_ctx_get_action (BRASERO_TASK_CTX (self)));
598
599 /* check the task is not running */
600 if (brasero_task_is_running (self)) {
601 BRASERO_BURN_LOG ("task is already running");
602 return BRASERO_BURN_RUNNING;
603 }
604
605 if (!priv->leader) {
606 BRASERO_BURN_LOG ("no jobs");
607 return BRASERO_BURN_RUNNING;
608 }
609
610 brasero_task_ctx_set_fake (BRASERO_TASK_CTX (self), fake);
611 brasero_task_ctx_reset (BRASERO_TASK_CTX (self));
612
613 /* Activate all items that can be. If no item can be then skip */
614 result = brasero_task_activate_items (self, error);
615 if (result == BRASERO_BURN_NOT_RUNNING) {
616 BRASERO_BURN_LOG ("Task skipped");
617 return BRASERO_BURN_OK;
618 }
619
620 if (result != BRASERO_BURN_OK)
621 return result;
622
623 result = brasero_task_start_items (self, error);
624 while (result == BRASERO_BURN_NOT_RUNNING) {
625 BRASERO_BURN_LOG ("current track skipped");
626
627 /* this track was skipped without actual loop therefore see if
628 * there is another track and, if there is, start again */
629 result = brasero_task_ctx_next_track (BRASERO_TASK_CTX (self));
630 if (result != BRASERO_BURN_RETRY) {
631 brasero_task_send_stop_signal (self, result, NULL);
632 return result;
633 }
634
635 result = brasero_task_start_items (self, error);
636 }
637
638 if (result != BRASERO_BURN_OK)
639 brasero_task_send_stop_signal (self, result, NULL);
640
641 return result;
642 }
643
644 BraseroBurnResult
brasero_task_check(BraseroTask * self,GError ** error)645 brasero_task_check (BraseroTask *self,
646 GError **error)
647 {
648 BraseroTaskAction action;
649
650 g_return_val_if_fail (BRASERO_IS_TASK (self), BRASERO_BURN_ERR);
651
652 /* the task MUST be of a BRASERO_TASK_ACTION_NORMAL type */
653 action = brasero_task_ctx_get_action (BRASERO_TASK_CTX (self));
654 if (action != BRASERO_TASK_ACTION_NORMAL)
655 return BRASERO_BURN_OK;
656
657 /* The main purpose of this function is to get the final size of the
658 * task output whether it be recorded to disc or stored as a file later.
659 * That size will be stored by task-ctx.
660 * To do this we run all the task in fake mode that means we don't write
661 * anything to disc or hard drive. Only the last running job in the
662 * chain will be aware that we're running in fake mode / get-size mode.
663 * All others will be told to image. To determine what should be the
664 * last job and therefore the one telling the final size of the output,
665 * we start to call ::init for each job starting from the leader. we
666 * don't skip recording jobs in case they modify the contents (and
667 * therefore the output size). When a job returns NOT_RUNNING after
668 * ::init then we skip it; this return value will mean that it won't
669 * change the output size or that it has already determined the output
670 * size. Only the last running job is allowed to set the final size (see
671 * burn-jobs.c), all values from other jobs will be ignored. */
672
673 return brasero_task_start (self, TRUE, error);
674 }
675
676 BraseroBurnResult
brasero_task_run(BraseroTask * self,GError ** error)677 brasero_task_run (BraseroTask *self,
678 GError **error)
679 {
680 g_return_val_if_fail (BRASERO_IS_TASK (self), BRASERO_BURN_ERR);
681
682 return brasero_task_start (self, FALSE, error);
683 }
684
685 static void
brasero_task_class_init(BraseroTaskClass * klass)686 brasero_task_class_init (BraseroTaskClass *klass)
687 {
688 GObjectClass *object_class = G_OBJECT_CLASS (klass);
689 BraseroTaskCtxClass *ctx_class = BRASERO_TASK_CTX_CLASS (klass);
690
691 g_type_class_add_private (klass, sizeof (BraseroTaskPrivate));
692
693 parent_class = g_type_class_peek_parent(klass);
694 object_class->finalize = brasero_task_finalize;
695
696 ctx_class->finished = brasero_task_finished;
697 }
698
699 static void
brasero_task_init(BraseroTask * obj)700 brasero_task_init (BraseroTask *obj)
701 { }
702
703 static void
brasero_task_finalize(GObject * object)704 brasero_task_finalize (GObject *object)
705 {
706 BraseroTask *cobj;
707 BraseroTaskPrivate *priv;
708
709 cobj = BRASERO_TASK (object);
710 priv = BRASERO_TASK_PRIVATE (cobj);
711
712 if (priv->leader) {
713 g_object_unref (priv->leader);
714 priv->leader = NULL;
715 }
716
717 G_OBJECT_CLASS (parent_class)->finalize (object);
718 }
719
720 BraseroTask *
brasero_task_new()721 brasero_task_new ()
722 {
723 BraseroTask *obj;
724
725 obj = BRASERO_TASK (g_object_new (BRASERO_TYPE_TASK, NULL));
726 return obj;
727 }
728