~ubuntu-branches/debian/sid/brasero/sid

« back to all changes in this revision

Viewing changes to .pc/01_gcc-format-security-commit/plugins/libburnia/burn-libburn-common.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2011-11-19 14:00:13 UTC
  • mfrom: (5.1.6 experimental)
  • Revision ID: package-import@ubuntu.com-20111119140013-9dnkj4de9z9lzceo
Tags: 3.2.0-2
* Upload to unstable.
* debian/control.in:
  - Make libbrasero-media3-dev depend on gir1.2-brasero-3.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
37
#include <glib.h>
 
38
#include <glib-object.h>
 
39
#include <glib/gi18n-lib.h>
 
40
 
 
41
#include "burn-basics.h"
 
42
#include "burn-debug.h"
 
43
#include "burn-job.h"
 
44
#include "burn-libburn-common.h"
 
45
 
 
46
#include <libburn/libburn.h>
 
47
 
 
48
static void
 
49
brasero_libburn_common_ctx_free_real (BraseroLibburnCtx *ctx)
 
50
{
 
51
        BRASERO_BURN_LOG ("Drive stopped");
 
52
 
 
53
        if (ctx->disc) {
 
54
                burn_disc_free (ctx->disc);
 
55
                ctx->disc = NULL;
 
56
        }
 
57
 
 
58
        /* This must be done in this order since:
 
59
         * ctx->drive = ctx->drive_info->drive */
 
60
 
 
61
        if (ctx->drive) {
 
62
                burn_drive_release (ctx->drive, 0);
 
63
                ctx->drive = NULL;
 
64
        }
 
65
 
 
66
        if (ctx->drive_info) {
 
67
                burn_drive_info_free (ctx->drive_info);
 
68
                ctx->drive_info = NULL;
 
69
        }
 
70
 
 
71
        g_free (ctx);
 
72
 
 
73
        /* Since the library is not needed any more call burn_finish ().
 
74
         * NOTE: it itself calls burn_abort (). */
 
75
        burn_finish ();
 
76
}
 
77
 
 
78
static gboolean
 
79
brasero_libburn_common_ctx_wait_for_idle_drive (gpointer data)
 
80
{
 
81
        BraseroLibburnCtx *ctx = data;
 
82
        enum burn_drive_status status;
 
83
 
 
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);
 
89
        }
 
90
 
 
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);
 
95
        }
 
96
 
 
97
        if (status != BURN_DRIVE_IDLE) {
 
98
                BRASERO_BURN_LOG ("Drive not idle yet");
 
99
                return TRUE;
 
100
        }
 
101
 
 
102
        brasero_libburn_common_ctx_free_real (ctx);
 
103
        return FALSE;
 
104
}
 
105
 
 
106
void
 
107
brasero_libburn_common_ctx_free (BraseroLibburnCtx *ctx)
 
108
{
 
109
        enum burn_drive_status status;
 
110
 
 
111
        if (ctx->op_start) {
 
112
                g_timer_destroy (ctx->op_start);
 
113
                ctx->op_start = NULL;
 
114
        }
 
115
 
 
116
        BRASERO_BURN_LOG ("Stopping Drive");
 
117
 
 
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);
 
123
        }
 
124
 
 
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);
 
129
        }
 
130
        
 
131
        if (status != BURN_DRIVE_IDLE) {
 
132
                /* otherwise wait for the drive to calm down */
 
133
                BRASERO_BURN_LOG ("Drive not idle yet");
 
134
                g_timeout_add (200,
 
135
                               brasero_libburn_common_ctx_wait_for_idle_drive,
 
136
                               ctx);
 
137
                return;
 
138
        }
 
139
 
 
140
        brasero_libburn_common_ctx_free_real (ctx);
 
141
}
 
142
 
 
143
BraseroLibburnCtx *
 
144
brasero_libburn_common_ctx_new (BraseroJob *job,
 
145
                                gboolean is_burning,
 
146
                                GError **error)
 
147
{
 
148
        gchar libburn_device [BURN_DRIVE_ADR_LEN];
 
149
        BraseroLibburnCtx *ctx = NULL;
 
150
        gchar *device;
 
151
        int res;
 
152
 
 
153
        /* initialize the library */
 
154
        if (!burn_initialize ()) {
 
155
                g_set_error (error,
 
156
                             BRASERO_BURN_ERROR,
 
157
                             BRASERO_BURN_ERROR_GENERAL,
 
158
                             _("libburn library could not be initialized"));
 
159
                return NULL;
 
160
        }
 
161
 
 
162
        /* We want all types of messages but not them printed */
 
163
        burn_msgs_set_severities ("ALL", "NEVER", "");
 
164
 
 
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);
 
168
        g_free (device);
 
169
        if (res <= 0) {
 
170
                g_set_error (error,
 
171
                             BRASERO_BURN_ERROR,
 
172
                             BRASERO_BURN_ERROR_GENERAL,
 
173
                             _("The drive address could not be retrieved"));
 
174
                return NULL;
 
175
        }
 
176
 
 
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);
 
181
        if (res <= 0) {
 
182
                g_free (ctx);
 
183
                g_set_error (error,
 
184
                             BRASERO_BURN_ERROR,
 
185
                             BRASERO_BURN_ERROR_DRIVE_BUSY,
 
186
                             _("The drive is busy"));
 
187
                return NULL;
 
188
        }
 
189
 
 
190
        ctx->drive = ctx->drive_info->drive;
 
191
        return ctx;     
 
192
}
 
193
 
 
194
static gboolean
 
195
brasero_libburn_common_process_message (BraseroJob *self)
 
196
{
 
197
        int ret;
 
198
        GError *error;
 
199
        int err_code = 0;
 
200
        int err_errno = 0;
 
201
        char err_sev [80];
 
202
        char err_txt [BURN_MSGS_MESSAGE_LEN] = {0};
 
203
 
 
204
        /* Get all messages, indicating an error */
 
205
        memset (err_txt, 0, sizeof (err_txt));
 
206
        ret = burn_msgs_obtain ("ALL",
 
207
                                &err_code,
 
208
                                err_txt,
 
209
                                &err_errno,
 
210
                                err_sev);
 
211
        if (ret == 0)
 
212
                return TRUE;
 
213
 
 
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);
 
219
                return TRUE;
 
220
        }
 
221
 
 
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,
 
225
                             err_txt);
 
226
        brasero_job_error (BRASERO_JOB (self), error);
 
227
        return FALSE;
 
228
}
 
229
 
 
230
static gboolean
 
231
brasero_libburn_common_status_changed (BraseroJob *self,
 
232
                                       BraseroLibburnCtx *ctx,
 
233
                                       enum burn_drive_status status,
 
234
                                       struct burn_progress *progress)
 
235
{
 
236
        BraseroBurnAction action = BRASERO_BURN_ACTION_NONE;
 
237
 
 
238
        switch (status) {
 
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)
 
244
                                return TRUE;
 
245
 
 
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;
 
251
                        }
 
252
 
 
253
                        action = BRASERO_BURN_ACTION_RECORDING;
 
254
                        brasero_job_set_dangerous (BRASERO_JOB (self), TRUE);
 
255
                        break;
 
256
 
 
257
                case BURN_DRIVE_WRITING_LEADIN:         /* DAO */
 
258
                case BURN_DRIVE_WRITING_PREGAP:         /* TAO */
 
259
                        BRASERO_JOB_LOG (self, "Pregap/leadin");
 
260
                        ctx->has_leadin = 1;
 
261
                        action = BRASERO_BURN_ACTION_START_RECORDING;
 
262
                        brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
 
263
                        break;
 
264
 
 
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;
 
271
 
 
272
                        action = BRASERO_BURN_ACTION_FIXATING;
 
273
                        brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
 
274
                        break;
 
275
 
 
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);
 
282
                        }
 
283
                        else {
 
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);
 
288
                        }
 
289
                        break;
 
290
 
 
291
                case BURN_DRIVE_IDLE:
 
292
                        /* That's the end of activity */
 
293
                        return FALSE;
 
294
 
 
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;
 
299
                        else
 
300
                                action = BRASERO_BURN_ACTION_FIXATING;
 
301
                        brasero_job_set_dangerous (BRASERO_JOB (self), FALSE);
 
302
                        break;
 
303
 
 
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);
 
308
                        break;
 
309
 
 
310
                default:
 
311
                        BRASERO_JOB_LOG (self, "Unknown drive state (%i)", status);
 
312
                        return TRUE;
 
313
        }
 
314
 
 
315
        ctx->status = status;
 
316
        brasero_job_set_current_action (self,
 
317
                                        action,
 
318
                                        NULL,
 
319
                                        FALSE);
 
320
        return TRUE;
 
321
}
 
322
 
 
323
BraseroBurnResult
 
324
brasero_libburn_common_status (BraseroJob *self,
 
325
                               BraseroLibburnCtx *ctx)
 
326
{
 
327
        enum burn_drive_status status;
 
328
        struct burn_progress progress;
 
329
 
 
330
        /* see if there is any pending message */
 
331
        if (!brasero_libburn_common_process_message (self))
 
332
                return BRASERO_BURN_ERR;
 
333
 
 
334
        if (!ctx->drive)
 
335
                return BRASERO_BURN_ERR;
 
336
 
 
337
        status = burn_drive_get_status (ctx->drive, &progress);
 
338
 
 
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);
 
349
                }
 
350
                else {
 
351
                        gdouble elapsed = 0.0;
 
352
 
 
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);
 
358
                        if (elapsed > 2.0)
 
359
                                return BRASERO_BURN_OK;
 
360
                }
 
361
        }
 
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;
 
366
        }
 
367
 
 
368
        if (ctx->status != status) {
 
369
                gboolean running;
 
370
 
 
371
                running = brasero_libburn_common_status_changed (self,
 
372
                                                                 ctx,
 
373
                                                                 status,
 
374
                                                                 &progress);
 
375
                if (!running)
 
376
                        return BRASERO_BURN_OK;
 
377
        }
 
378
 
 
379
        if (status == BURN_DRIVE_IDLE
 
380
        ||  status == BURN_DRIVE_SPAWNING
 
381
        ||  !progress.sectors
 
382
        ||  !progress.sector) {
 
383
                ctx->sectors = 0;
 
384
                ctx->track_num = progress.track;
 
385
                ctx->track_sectors = progress.sectors;
 
386
                return BRASERO_BURN_RETRY;
 
387
        }
 
388
 
 
389
        if (ctx->status == BURN_DRIVE_WRITING) {
 
390
                gint64 cur_sector;
 
391
 
 
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;
 
397
                }
 
398
 
 
399
                cur_sector = progress.sector + ctx->sectors;
 
400
 
 
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;
 
405
 
 
406
                        brasero_job_get_session_output_size (self, &total_sectors, NULL);
 
407
 
 
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) {
 
412
                                gchar *string;
 
413
 
 
414
                                brasero_job_set_written_session (self, (gint64) ((gint64) cur_sector * 2048ULL));
 
415
                                brasero_job_start_progress (self, FALSE);
 
416
 
 
417
                                string = g_strdup_printf (_("Writing track %02i"), progress.track + 1);
 
418
                                brasero_job_set_current_action (self,
 
419
                                                                BRASERO_BURN_ACTION_RECORDING,
 
420
                                                                string,
 
421
                                                                TRUE);
 
422
                                g_free (string);
 
423
                        }
 
424
                        else
 
425
                                brasero_job_set_current_action (self,
 
426
                                                                BRASERO_BURN_ACTION_FIXATING,
 
427
                                                                NULL,
 
428
                                                                FALSE);
 
429
                }
 
430
                else
 
431
                             brasero_job_set_current_action (self,
 
432
                                                        BRASERO_BURN_ACTION_START_RECORDING,
 
433
                                                        NULL,
 
434
                                                        FALSE);
 
435
        }
 
436
        else if ((ctx->status == BURN_DRIVE_ERASING || ctx->status == BURN_DRIVE_FORMATTING)
 
437
             &&  progress.sector > 0) {
 
438
                gdouble fraction;
 
439
 
 
440
                /* NOTE: there is a strange behaviour which
 
441
                 * leads to progress being reset after 30%
 
442
                 * approx when blanking seq DVD-RW */
 
443
 
 
444
                /* when erasing only set progress */
 
445
                fraction = (gdouble) (progress.sector) /
 
446
                           (gdouble) (progress.sectors);
 
447
 
 
448
                brasero_job_set_progress (self, fraction);
 
449
                brasero_job_start_progress (self, FALSE);
 
450
        }
 
451
 
 
452
        return BRASERO_BURN_RETRY;
 
453
}