1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
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.
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.
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.
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.
38
#include <glib-object.h>
39
#include <glib/gi18n-lib.h>
41
#include "burn-basics.h"
42
#include "burn-debug.h"
44
#include "burn-libburn-common.h"
46
#include <libburn/libburn.h>
49
brasero_libburn_common_ctx_free_real (BraseroLibburnCtx *ctx)
51
BRASERO_BURN_LOG ("Drive stopped");
54
burn_disc_free (ctx->disc);
58
/* This must be done in this order since:
59
* ctx->drive = ctx->drive_info->drive */
62
burn_drive_release (ctx->drive, 0);
66
if (ctx->drive_info) {
67
burn_drive_info_free (ctx->drive_info);
68
ctx->drive_info = NULL;
73
/* Since the library is not needed any more call burn_finish ().
74
* NOTE: it itself calls burn_abort (). */
79
brasero_libburn_common_ctx_wait_for_idle_drive (gpointer data)
81
BraseroLibburnCtx *ctx = data;
82
enum burn_drive_status status;
84
/* try to properly cancel the drive */
85
status = burn_drive_get_status (ctx->drive, NULL);
86
if (status == BURN_DRIVE_WRITING || status == BURN_DRIVE_READING) {
87
BRASERO_BURN_LOG ("Cancelling operation");
88
burn_drive_cancel (ctx->drive);
91
if (status == BURN_DRIVE_GRABBING) {
92
/* This should probably never happen */
93
BRASERO_BURN_LOG ("Grabbing state, try to forget");
94
burn_drive_info_forget (ctx->drive_info, 1);
97
if (status != BURN_DRIVE_IDLE) {
98
BRASERO_BURN_LOG ("Drive not idle yet");
102
brasero_libburn_common_ctx_free_real (ctx);
107
brasero_libburn_common_ctx_free (BraseroLibburnCtx *ctx)
109
enum burn_drive_status status;
112
g_timer_destroy (ctx->op_start);
113
ctx->op_start = NULL;
116
BRASERO_BURN_LOG ("Stopping Drive");
118
/* try to properly cancel the drive */
119
status = burn_drive_get_status (ctx->drive, NULL);
120
if (status == BURN_DRIVE_WRITING || status == BURN_DRIVE_READING) {
121
BRASERO_BURN_LOG ("Cancelling operation");
122
burn_drive_cancel (ctx->drive);
125
if (status == BURN_DRIVE_GRABBING) {
126
/* This should probably never happen */
127
BRASERO_BURN_LOG ("Grabbing state, try to forget");
128
burn_drive_info_forget (ctx->drive_info, 1);
131
if (status != BURN_DRIVE_IDLE) {
132
/* otherwise wait for the drive to calm down */
133
BRASERO_BURN_LOG ("Drive not idle yet");
135
brasero_libburn_common_ctx_wait_for_idle_drive,
140
brasero_libburn_common_ctx_free_real (ctx);
144
brasero_libburn_common_ctx_new (BraseroJob *job,
148
gchar libburn_device [BURN_DRIVE_ADR_LEN];
149
BraseroLibburnCtx *ctx = NULL;
153
/* initialize the library */
154
if (!burn_initialize ()) {
157
BRASERO_BURN_ERROR_GENERAL,
158
_("libburn library could not be initialized"));
162
/* We want all types of messages but not them printed */
163
burn_msgs_set_severities ("ALL", "NEVER", "");
165
/* we just want to scan the drive proposed by drive */
166
brasero_job_get_device (job, &device);
167
res = burn_drive_convert_fs_adr (device, libburn_device);
172
BRASERO_BURN_ERROR_GENERAL,
173
_("The drive address could not be retrieved"));
177
ctx = g_new0 (BraseroLibburnCtx, 1);
178
ctx->is_burning = is_burning;
179
res = burn_drive_scan_and_grab (&ctx->drive_info, libburn_device, 0);
180
BRASERO_JOB_LOG (job, "Drive (%s) init result = %d", libburn_device, res);
185
BRASERO_BURN_ERROR_DRIVE_BUSY,
186
_("The drive is busy"));
190
ctx->drive = ctx->drive_info->drive;
195
brasero_libburn_common_process_message (BraseroJob *self)
202
char err_txt [BURN_MSGS_MESSAGE_LEN] = {0};
204
/* Get all messages, indicating an error */
205
memset (err_txt, 0, sizeof (err_txt));
206
ret = burn_msgs_obtain ("ALL",
214
if (strcmp ("FATAL", err_sev)
215
&& strcmp ("ABORT", err_sev)) {
216
/* libburn didn't reported any FATAL message but maybe it did
217
* report some debugging output */
218
BRASERO_JOB_LOG (self, err_txt);
222
BRASERO_JOB_LOG (self, "Libburn reported an error %s", err_txt);
223
error = g_error_new (BRASERO_BURN_ERROR,
224
BRASERO_BURN_ERROR_GENERAL,
226
brasero_job_error (BRASERO_JOB (self), error);
231
brasero_libburn_common_status_changed (BraseroJob *self,
232
BraseroLibburnCtx *ctx,
233
enum burn_drive_status status,
234
struct burn_progress *progress)
236
BraseroBurnAction action = BRASERO_BURN_ACTION_NONE;
239
case BURN_DRIVE_WRITING:
240
BRASERO_JOB_LOG (self, "Writing");
241
/* we ignore it if it happens after leadout */
242
if (ctx->status == BURN_DRIVE_WRITING_LEADOUT
243
|| ctx->status == BURN_DRIVE_CLOSING_SESSION)
246
if (!ctx->track_sectors) {
247
/* This is for when we just start writing
248
* the first bytes of the first tracks */
249
ctx->track_sectors = progress->sectors;
250
ctx->track_num = progress->track;
253
action = BRASERO_BURN_ACTION_RECORDING;
254
brasero_job_set_dangerous (BRASERO_JOB (self), TRUE);
257
case BURN_DRIVE_WRITING_LEADIN: /* DAO */
258
case BURN_DRIVE_WRITING_PREGAP: /* TAO */
259
BRASERO_JOB_LOG (self, "Pregap/leadin");
261
action = BRASERO_BURN_ACTION_START_RECORDING;
262
brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
265
case BURN_DRIVE_CLOSING_TRACK: /* TAO */
266
case BURN_DRIVE_WRITING_LEADOUT: /* DAO */
267
case BURN_DRIVE_CLOSING_SESSION: /* Multisession end */
268
BRASERO_JOB_LOG (self, "Closing");
269
ctx->sectors += ctx->track_sectors;
270
ctx->track_sectors = progress->sectors;
272
action = BRASERO_BURN_ACTION_FIXATING;
273
brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
276
case BURN_DRIVE_ERASING:
277
case BURN_DRIVE_FORMATTING:
278
BRASERO_JOB_LOG (self, "Blanking/Formatting");
279
if (!ctx->is_burning) {
280
action = BRASERO_BURN_ACTION_BLANKING;
281
brasero_job_set_dangerous (BRASERO_JOB (self), TRUE);
284
/* DVD+RW need a preformatting before being written.
285
* Adapt the message to "start recording". */
286
action = BRASERO_BURN_ACTION_START_RECORDING;
287
brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
291
case BURN_DRIVE_IDLE:
292
/* That's the end of activity */
295
case BURN_DRIVE_SPAWNING:
296
BRASERO_JOB_LOG (self, "Starting");
297
if (ctx->status == BURN_DRIVE_IDLE)
298
action = BRASERO_BURN_ACTION_START_RECORDING;
300
action = BRASERO_BURN_ACTION_FIXATING;
301
brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
304
case BURN_DRIVE_READING:
305
BRASERO_JOB_LOG (self, "Reading");
306
action = BRASERO_BURN_ACTION_DRIVE_COPY;
307
brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
311
BRASERO_JOB_LOG (self, "Unknown drive state (%i)", status);
315
ctx->status = status;
316
brasero_job_set_current_action (self,
324
brasero_libburn_common_status (BraseroJob *self,
325
BraseroLibburnCtx *ctx)
327
enum burn_drive_status status;
328
struct burn_progress progress;
330
/* see if there is any pending message */
331
if (!brasero_libburn_common_process_message (self))
332
return BRASERO_BURN_ERR;
335
return BRASERO_BURN_ERR;
337
status = burn_drive_get_status (ctx->drive, &progress);
339
/* For some operations that libburn can't perform
340
* the drive stays idle and we've got no way to tell
341
* that kind of use cases. For example, this
342
* happens when fast blanking a blank DVD-RW */
343
if (ctx->status == BURN_DRIVE_IDLE && status == BURN_DRIVE_IDLE) {
344
BRASERO_JOB_LOG (self, "Waiting for operation to start");
345
if (ctx->op_start == NULL) {
346
/* wait for action for 2 seconds until we timeout */
347
ctx->op_start = g_timer_new ();
348
g_timer_start (ctx->op_start);
351
gdouble elapsed = 0.0;
353
/* See how long elapsed since we started.
354
* NOTE: we do not consider this as an error.
355
* since it can be because of an unneeded
356
* operation like blanking on a blank disc. */
357
elapsed = g_timer_elapsed (ctx->op_start, NULL);
359
return BRASERO_BURN_OK;
362
else if (ctx->op_start) {
363
BRASERO_JOB_LOG (self, "Operation started");
364
g_timer_destroy (ctx->op_start);
365
ctx->op_start = NULL;
368
if (ctx->status != status) {
371
running = brasero_libburn_common_status_changed (self,
376
return BRASERO_BURN_OK;
379
if (status == BURN_DRIVE_IDLE
380
|| status == BURN_DRIVE_SPAWNING
382
|| !progress.sector) {
384
ctx->track_num = progress.track;
385
ctx->track_sectors = progress.sectors;
386
return BRASERO_BURN_RETRY;
389
if (ctx->status == BURN_DRIVE_WRITING) {
392
if (ctx->track_num != progress.track) {
393
/* This is when we change tracks */
394
ctx->sectors += ctx->track_sectors;
395
ctx->track_sectors = progress.sectors;
396
ctx->track_num = progress.track;
399
cur_sector = progress.sector + ctx->sectors;
401
/* With some media libburn writes only 16 blocks then wait
402
* which disrupt the whole process of time reporting */
403
if (cur_sector > 32) {
404
goffset total_sectors;
406
brasero_job_get_session_output_size (self, &total_sectors, NULL);
408
/* Sometimes we have to wait for a long
409
* time while libburn sync the cache.
410
* Tell the use we haven't given up. */
411
if (cur_sector < total_sectors) {
414
brasero_job_set_written_session (self, (gint64) ((gint64) cur_sector * 2048ULL));
415
brasero_job_start_progress (self, FALSE);
417
string = g_strdup_printf (_("Writing track %02i"), progress.track + 1);
418
brasero_job_set_current_action (self,
419
BRASERO_BURN_ACTION_RECORDING,
425
brasero_job_set_current_action (self,
426
BRASERO_BURN_ACTION_FIXATING,
431
brasero_job_set_current_action (self,
432
BRASERO_BURN_ACTION_START_RECORDING,
436
else if ((ctx->status == BURN_DRIVE_ERASING || ctx->status == BURN_DRIVE_FORMATTING)
437
&& progress.sector > 0) {
440
/* NOTE: there is a strange behaviour which
441
* leads to progress being reset after 30%
442
* approx when blanking seq DVD-RW */
444
/* when erasing only set progress */
445
fraction = (gdouble) (progress.sector) /
446
(gdouble) (progress.sectors);
448
brasero_job_set_progress (self, fraction);
449
brasero_job_start_progress (self, FALSE);
452
return BRASERO_BURN_RETRY;