~ubuntu-branches/debian/experimental/brasero/experimental

« back to all changes in this revision

Viewing changes to libbrasero-media/brasero-medium.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette, Pedro Fragoso, Luca Bruno, Josselin Mouette, Emilio Pozuelo Monfort
  • Date: 2009-06-24 18:59:46 UTC
  • mfrom: (1.2.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624185946-iyxkgf3gjptir5y3
Tags: 2.26.2-1
[ Pedro Fragoso ]
* Add myself to Maintainer field
  - Thanks Ondřej Surý
* New upstream version (Closes: #528945)
  - Split package into brasero, libbrasero-media0 and libbrasero-dev
  - Add Replaces to libbrasero-media0
  - Bump libgtk to 2.14.0
  - Remove libnotify Build-dep
  - Add Build-dep libnautilus-extension-dev (>= 2.22.2)
    and install it.
  - Add Build-dep to libsm-dev
  - Add Build-dep on intltool
* Install omf files to prevent crash on Help
* Move gstreamer0.10-plugins-bad to Suggests, and add
  dvdauthor and vcdimager
* Recommends gvfs (Closes: #491827)
* Pass --disable-scrollkeeper in DEB_CONFIGURE_EXTRA_FLAGS
* debian/patches/007-fix-gnome-doc-utils-path.patch:
  - Removed, not needed anymore
* debian/patches/008-fix-volume-identifier-crash.patch:
  - Removed, merged upstream
* debian/patches/011_nautilus_menu_move.patch:
 - Move CD/DVD Creator Menu to Acessories, taken from Ubuntu

[ Luca Bruno ]
* debian/control.in:
  - Add Build-Depend gtk-doc-tools 1.9.
* debian/patches/006-fix-libdvdcss.patch:
  - Removed as applied upstream.

[ Josselin Mouette ]
* New upstream release.
* Update build-dependencies.
* Move the translations and data to a new brasero-common package.
* Rewrite the descriptions.
* Add -dev depends to the development package.
* Remove inappropriate recommends in the library package.
* Let’s not forget dvd+rw-tools so that we can write DVDs too.
* Rework dependencies accordingly.
* Put the nautilus extension in brasero.
* Conflict against nautilus-cd-burner to avoid having two burning 
  extensions.
* Include clean-la.mk and gnome-version.mk; build-depend on 
  gnome-pkg-tools 0.7.
* Don’t run dh_makeshlibs on brasero and libbrasero-plugins.
* 011_nautilus_menu_move.patch: add NoDisplay=true, this icon is 
  duplicating existing functionality (brasero icon in sound&video 
  menu, and nautilus autorun).
* Update list of copyright holders.

[ Emilio Pozuelo Monfort ]
* debian/copyright: updated.

[ Josselin Mouette ]
* copyright: improve indentation, and point to versioned LGPL.
* 090_relibtoolize.patch: add a relibtoolization patch to avoid the 
  rpath crap.

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-media
 
4
 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
 
5
 *
 
6
 * Libbrasero-media 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-media authors hereby grant permission for non-GPL compatible
 
12
 * GStreamer plugins to be used and distributed together with GStreamer
 
13
 * and Libbrasero-media. This permission is above and beyond the permissions granted
 
14
 * by the GPL license by which Libbrasero-media 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-media is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU Library General Public License for more details.
 
23
 * 
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program; if not, write to:
 
26
 *      The Free Software Foundation, Inc.,
 
27
 *      51 Franklin Street, Fifth Floor
 
28
 *      Boston, MA  02110-1301, USA.
 
29
 */
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#  include <config.h>
 
33
#endif
 
34
 
 
35
#include <sys/types.h>
 
36
#include <sys/stat.h>
 
37
#include <fcntl.h>
 
38
#include <errno.h>
 
39
#include <unistd.h>
 
40
 
 
41
#include <glib.h>
 
42
#include <glib/gi18n-lib.h>
 
43
#include <gdk/gdk.h>
 
44
 
 
45
#include "burn-basics.h"
 
46
 
 
47
#include "brasero-media-private.h"
 
48
 
 
49
#include "brasero-medium.h"
 
50
#include "brasero-drive.h"
 
51
 
 
52
#include "scsi-device.h"
 
53
#include "scsi-mmc1.h"
 
54
#include "scsi-mmc2.h"
 
55
#include "scsi-mmc3.h"
 
56
#include "scsi-spc1.h"
 
57
#include "scsi-utils.h"
 
58
#include "scsi-mode-pages.h"
 
59
#include "scsi-status-page.h"
 
60
#include "scsi-write-page.h"
 
61
#include "scsi-q-subchannel.h"
 
62
#include "scsi-dvd-structures.h"
 
63
#include "burn-volume.h"
 
64
 
 
65
 
 
66
const gchar *types [] = {       N_("File"),
 
67
                                N_("CDROM"),
 
68
                                N_("CD-R"),
 
69
                                N_("CD-RW"),
 
70
                                N_("DVDROM"),
 
71
                                N_("DVD-R"),
 
72
                                N_("DVD-RW"),
 
73
                                N_("DVD+R"),
 
74
                                N_("DVD+RW"),
 
75
                                N_("DVD+R dual layer"),
 
76
                                N_("DVD+RW dual layer"),
 
77
                                N_("DVD-R dual layer"),
 
78
                                N_("DVD-RAM"),
 
79
                                N_("Blu-ray disc"),
 
80
                                N_("Writable Blu-ray disc"),
 
81
                                N_("Rewritable Blu-ray disc"),
 
82
                                NULL };
 
83
 
 
84
typedef enum {
 
85
        BRASERO_MEDIUM_CAP_INVALID      = 0,
 
86
        BRASERO_MEDIUM_CAP_TRUE         = 1,
 
87
        BRASERO_MEDIUM_CAP_FALSE                = 2
 
88
} BraseroMediumCapState;
 
89
 
 
90
typedef struct _BraseroMediumPrivate BraseroMediumPrivate;
 
91
struct _BraseroMediumPrivate
 
92
{
 
93
        GThread *probe;
 
94
        gint probe_id;
 
95
 
 
96
        GSList *tracks;
 
97
 
 
98
        const gchar *type;
 
99
 
 
100
        gchar *id;
 
101
 
 
102
        guint max_rd;
 
103
        guint max_wrt;
 
104
 
 
105
        guint *rd_speeds;
 
106
        guint *wr_speeds;
 
107
 
 
108
        gint64 block_num;
 
109
        gint64 block_size;
 
110
 
 
111
        guint first_open_track;
 
112
        guint64 next_wr_add;
 
113
 
 
114
        BraseroMedia info;
 
115
        BraseroDrive *drive;
 
116
 
 
117
        gchar *CD_TEXT_title;
 
118
 
 
119
        /* Do we really need both? */
 
120
        guint dummy_sao:2;
 
121
        guint dummy_tao:2;
 
122
        guint burnfree:2;
 
123
 
 
124
        guint probe_cancelled:1;
 
125
};
 
126
 
 
127
#define BRASERO_MEDIUM_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM, BraseroMediumPrivate))
 
128
 
 
129
/**
 
130
 * Try to open the drive exclusively but don't block; if drive can't be opened
 
131
 * exclusively then retry every second until we're shut or the drive state
 
132
 * changes to not busy.
 
133
 * No exclusive at the moment since when the medium is mounted we can't use excl
 
134
 */
 
135
 
 
136
#define BUSY_RETRY_TIME                 1000
 
137
 
 
138
typedef enum {
 
139
        BRASERO_MEDIUM_TRACK_NONE               = 0,
 
140
        BRASERO_MEDIUM_TRACK_DATA               = 1,
 
141
        BRASERO_MEDIUM_TRACK_AUDIO              = 1 << 1,
 
142
        BRASERO_MEDIUM_TRACK_COPY               = 1 << 2,
 
143
        BRASERO_MEDIUM_TRACK_PREEMP             = 1 << 3,
 
144
        BRASERO_MEDIUM_TRACK_4_CHANNELS         = 1 << 4,
 
145
        BRASERO_MEDIUM_TRACK_INCREMENTAL        = 1 << 5,
 
146
        BRASERO_MEDIUM_TRACK_LEADOUT            = 1 << 6
 
147
} BraseroMediumTrackType;
 
148
 
 
149
typedef struct _BraseroMediumTrack BraseroMediumTrack;
 
150
 
 
151
struct _BraseroMediumTrack {
 
152
        guint session;
 
153
        BraseroMediumTrackType type;
 
154
        guint64 start;
 
155
        guint64 blocks_num;
 
156
};
 
157
 
 
158
enum
 
159
{
 
160
        PROP_0,
 
161
        PROP_DRIVE,
 
162
};
 
163
 
 
164
enum {
 
165
        PROBED,
 
166
        LAST_SIGNAL
 
167
};
 
168
static gulong medium_signals [LAST_SIGNAL] = {0, };
 
169
 
 
170
#define BRASERO_MEDIUM_OPEN_ATTEMPTS                    5
 
171
 
 
172
static GObjectClass* parent_class = NULL;
 
173
 
 
174
/**
 
175
 * This one is not supposed to be public API. It's declared in burn-caps.c
 
176
 */
 
177
 
 
178
BraseroBurnFlag
 
179
brasero_medium_supported_flags (BraseroMedium *self,
 
180
                                BraseroBurnFlag flags)
 
181
{
 
182
        BraseroMediumPrivate *priv;
 
183
 
 
184
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
185
 
 
186
        /* This is always FALSE */
 
187
        if (priv->info & BRASERO_MEDIUM_PLUS)
 
188
                flags &= ~BRASERO_BURN_FLAG_DUMMY;
 
189
        /* Simulation is only possible according to write modes. This mode is
 
190
         * mostly used by cdrecord/wodim for CLONE images. */
 
191
        else if (priv->info & BRASERO_MEDIUM_DVD) {
 
192
                if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
 
193
                        flags &= ~BRASERO_BURN_FLAG_DUMMY;
 
194
        }
 
195
        else if (flags & BRASERO_BURN_FLAG_DAO) {
 
196
                if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
 
197
                        flags &= ~BRASERO_BURN_FLAG_DUMMY;
 
198
        }
 
199
        else if (priv->dummy_tao != BRASERO_MEDIUM_CAP_TRUE)
 
200
                flags &= ~BRASERO_BURN_FLAG_DUMMY;
 
201
 
 
202
        if (!priv->burnfree)
 
203
                flags &= ~BRASERO_BURN_FLAG_BURNPROOF;
 
204
 
 
205
        return flags;
 
206
}
 
207
 
 
208
/**
 
209
 * This one is not supposed to be public API. It's declared in burn-caps.c
 
210
 */
 
211
 
 
212
gboolean
 
213
brasero_medium_support_flags (BraseroMedium *self,
 
214
                              BraseroBurnFlag flags)
 
215
{
 
216
        BraseroMediumPrivate *priv;
 
217
 
 
218
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
219
 
 
220
        if (flags & BRASERO_BURN_FLAG_DUMMY) {
 
221
                /* This is always FALSE */
 
222
                if (priv->info & BRASERO_MEDIUM_PLUS)
 
223
                        return FALSE;
 
224
 
 
225
                if (priv->info & BRASERO_MEDIUM_DVD) {
 
226
                        if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
 
227
                                return FALSE;
 
228
                }
 
229
                else if (flags & BRASERO_BURN_FLAG_DAO) {
 
230
                        if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
 
231
                                return FALSE;
 
232
                }
 
233
                else if (priv->dummy_tao != BRASERO_MEDIUM_CAP_TRUE)
 
234
                        return FALSE;
 
235
        }
 
236
 
 
237
        if (flags & BRASERO_BURN_FLAG_BURNPROOF) {
 
238
                if (!priv->burnfree)
 
239
                        return FALSE;
 
240
        }
 
241
 
 
242
        return TRUE;
 
243
}
 
244
 
 
245
/**
 
246
 * brasero_medium_get_tooltip:
 
247
 * @medium: #BraseroMedium
 
248
 *
 
249
 * Returns a tooltip to be displayed in the UI.
 
250
 * It is of the form {content type} {disc type} in {drive name}.
 
251
 *
 
252
 * Return value: a #gchar *.
 
253
 *
 
254
 **/
 
255
gchar *
 
256
brasero_medium_get_tooltip (BraseroMedium *medium)
 
257
{
 
258
        BraseroMediumPrivate *priv;
 
259
        BraseroDrive *drive;
 
260
        BraseroMedia media;
 
261
        const gchar *type;
 
262
        gchar *label;
 
263
        gchar *name;
 
264
 
 
265
        g_return_val_if_fail (medium != NULL, NULL);
 
266
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
 
267
 
 
268
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
269
 
 
270
        media = brasero_medium_get_status (BRASERO_MEDIUM (medium));
 
271
        if (media & BRASERO_MEDIUM_FILE) {
 
272
                /* Translators: This is a fake drive, a file, and means that
 
273
                 * when we're writing, we're writing to a file and create an
 
274
                 * image on the hard drive. */
 
275
                return g_strdup (_("Image File"));
 
276
        }
 
277
 
 
278
        type = brasero_medium_get_type_string (BRASERO_MEDIUM (medium));
 
279
        drive = brasero_medium_get_drive (BRASERO_MEDIUM (medium));
 
280
        name = brasero_drive_get_display_name (drive);
 
281
 
 
282
        if (media & BRASERO_MEDIUM_BLANK) {
 
283
                /* NOTE for translators: the first %s is the disc type and the
 
284
                 * second %s the name of the drive this disc is in. */
 
285
                label = g_strdup_printf (_("Blank %s in %s"),
 
286
                                         type,
 
287
                                         name);
 
288
        }
 
289
        else if (BRASERO_MEDIUM_IS (media, BRASERO_MEDIUM_HAS_AUDIO|BRASERO_MEDIUM_HAS_DATA)) {
 
290
                /* NOTE for translators: the first %s is the disc type and the
 
291
                 * second %s the name of the drive this disc is in. */
 
292
                label = g_strdup_printf (_("Audio and data %s in %s"),
 
293
                                         type,
 
294
                                         name);
 
295
        }
 
296
        else if (media & BRASERO_MEDIUM_HAS_AUDIO) {
 
297
                /* NOTE for translators: the first %s is the disc type and the
 
298
                 * second %s the name of the drive this disc is in. */
 
299
                label = g_strdup_printf (_("Audio %s in %s"),
 
300
                                         type,
 
301
                                         name);
 
302
        }
 
303
        else if (media & BRASERO_MEDIUM_HAS_DATA) {
 
304
                /* NOTE for translators: the first %s is the disc type and the
 
305
                * second %s the name of the drive this disc is in. */
 
306
                label = g_strdup_printf (_("Data %s in %s"),
 
307
                                         type,
 
308
                                         name);
 
309
        }
 
310
        else {
 
311
                /* NOTE for translators: the first %s is the disc type and the
 
312
                * second %s the name of the drive this disc is in. */
 
313
                label = g_strdup_printf (_("%s in %s"),
 
314
                                         type,
 
315
                                         name);
 
316
        }
 
317
 
 
318
        g_free (name);
 
319
        return label;
 
320
}
 
321
 
 
322
/**
 
323
 * brasero_medium_get_type_string:
 
324
 * @medium: #BraseroMedium
 
325
 *
 
326
 * Returns the medium type as a string to be displayed in a UI.
 
327
 *
 
328
 * Return value: a #gchar *.
 
329
 *
 
330
 **/
 
331
const gchar *
 
332
brasero_medium_get_type_string (BraseroMedium *medium)
 
333
{
 
334
        BraseroMediumPrivate *priv;
 
335
 
 
336
        g_return_val_if_fail (medium != NULL, NULL);
 
337
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
 
338
 
 
339
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
340
        return priv->type;
 
341
}
 
342
 
 
343
/**
 
344
 * brasero_medium_get_status:
 
345
 * @medium: #BraseroMedium
 
346
 *
 
347
 * Gets the medium type and state.
 
348
 *
 
349
 * Return value: a #BraseroMedia.
 
350
 *
 
351
 **/
 
352
BraseroMedia
 
353
brasero_medium_get_status (BraseroMedium *medium)
 
354
{
 
355
        BraseroMediumPrivate *priv;
 
356
 
 
357
        if (!medium)
 
358
                return BRASERO_MEDIUM_NONE;
 
359
 
 
360
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), BRASERO_MEDIUM_NONE);
 
361
 
 
362
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
363
        return priv->info;
 
364
}
 
365
 
 
366
/**
 
367
 * brasero_medium_get_last_data_track_address:
 
368
 * @medium: #BraseroMedium
 
369
 * @byte: a #gint64 * or NULL
 
370
 * @sector: a #gint64 * or NULL
 
371
 *
 
372
 * Stores in either @byte (in bytes) or in @sector (in blocks) the address where
 
373
 * the last session starts. This is useful when creating a multisession image or
 
374
 * when reading the contents of this last track.
 
375
 *
 
376
 **/
 
377
gboolean
 
378
brasero_medium_get_last_data_track_address (BraseroMedium *medium,
 
379
                                            gint64 *byte,
 
380
                                            gint64 *sector)
 
381
{
 
382
        GSList *iter;
 
383
        BraseroMediumPrivate *priv;
 
384
        BraseroMediumTrack *track = NULL;
 
385
 
 
386
        g_return_val_if_fail (medium != NULL, FALSE);
 
387
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
388
 
 
389
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
390
 
 
391
        for (iter = priv->tracks; iter; iter = iter->next) {
 
392
                BraseroMediumTrack *current;
 
393
 
 
394
                current = iter->data;
 
395
                if (current->type & BRASERO_MEDIUM_TRACK_DATA)
 
396
                        track = current;
 
397
        }
 
398
 
 
399
        if (!track) {
 
400
                if (byte)
 
401
                        *byte = -1;
 
402
                if (sector)
 
403
                        *sector = -1;
 
404
                return FALSE;
 
405
        }
 
406
 
 
407
        if (byte)
 
408
                *byte = track->start * priv->block_size;
 
409
 
 
410
        if (sector)
 
411
                *sector = track->start;
 
412
 
 
413
        return TRUE;
 
414
}
 
415
 
 
416
/**
 
417
 * brasero_medium_get_last_data_track_space:
 
418
 * @medium: #BraseroMedium
 
419
 * @size: a #gint64 * or NULL
 
420
 * @blocks: a #gint64 * or NULL
 
421
 *
 
422
 * Stores in either @size (in bytes) or in @blocks (in blocks) the space used by
 
423
 * the last track on the medium.
 
424
 *
 
425
 **/
 
426
gboolean
 
427
brasero_medium_get_last_data_track_space (BraseroMedium *medium,
 
428
                                          gint64 *size,
 
429
                                          gint64 *blocks)
 
430
{
 
431
        GSList *iter;
 
432
        BraseroMediumPrivate *priv;
 
433
        BraseroMediumTrack *track = NULL;
 
434
 
 
435
        g_return_val_if_fail (medium != NULL, FALSE);
 
436
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
437
 
 
438
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
439
 
 
440
        for (iter = priv->tracks; iter; iter = iter->next) {
 
441
                BraseroMediumTrack *current;
 
442
 
 
443
                current = iter->data;
 
444
                if (current->type & BRASERO_MEDIUM_TRACK_DATA)
 
445
                        track = current;
 
446
        }
 
447
 
 
448
        if (!track) {
 
449
                if (size)
 
450
                        *size = -1;
 
451
                if (blocks)
 
452
                        *blocks = -1;
 
453
                return FALSE;
 
454
        }
 
455
 
 
456
        if (size)
 
457
                *size = track->blocks_num * priv->block_size;
 
458
        if (blocks)
 
459
                *blocks = track->blocks_num;
 
460
 
 
461
        return TRUE;
 
462
}
 
463
 
 
464
/**
 
465
 * brasero_medium_get_track_num:
 
466
 * @medium: #BraseroMedium
 
467
 *
 
468
 * Gets the number of tracks on the medium.
 
469
 *
 
470
 * Return value: a #guint.
 
471
 *
 
472
 **/
 
473
guint
 
474
brasero_medium_get_track_num (BraseroMedium *medium)
 
475
{
 
476
        GSList *iter;
 
477
        guint retval = 0;
 
478
        BraseroMediumPrivate *priv;
 
479
 
 
480
        g_return_val_if_fail (medium != NULL, 0);
 
481
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
 
482
 
 
483
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
484
        for (iter = priv->tracks; iter; iter = iter->next) {
 
485
                BraseroMediumTrack *current;
 
486
 
 
487
                current = iter->data;
 
488
                if (current->type & BRASERO_MEDIUM_TRACK_LEADOUT)
 
489
                        break;
 
490
 
 
491
                retval ++;
 
492
        }
 
493
 
 
494
        return retval;
 
495
}
 
496
 
 
497
static BraseroMediumTrack *
 
498
brasero_medium_get_track (BraseroMedium *medium,
 
499
                          guint num)
 
500
{
 
501
        guint i = 1;
 
502
        GSList *iter;
 
503
        BraseroMediumPrivate *priv;
 
504
 
 
505
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
506
 
 
507
        for (iter = priv->tracks; iter; iter = iter->next) {
 
508
                BraseroMediumTrack *current;
 
509
 
 
510
                current = iter->data;
 
511
                if (current->type == BRASERO_MEDIUM_TRACK_LEADOUT)
 
512
                        break;
 
513
 
 
514
                if (i == num)
 
515
                        return current;
 
516
 
 
517
                i++;
 
518
        }
 
519
 
 
520
        return NULL;
 
521
}
 
522
 
 
523
/**
 
524
 * brasero_medium_get_track_space:
 
525
 * @medium: a #BraseroMedium
 
526
 * @num: a #guint
 
527
 * @size: a #gint64 * or NULL
 
528
 * @blocks: a #gint64 * or NULL
 
529
 *
 
530
 * Stores in either @size (in bytes) or in @blocks (in blocks) the space used
 
531
 * by session @num on the disc.
 
532
 *
 
533
 * Return value: a #gboolean. Returns TRUE if information could be retrieved;
 
534
 * FALSE otherwise (usually when track @num doesn't exist).
 
535
 *
 
536
 **/
 
537
gboolean
 
538
brasero_medium_get_track_space (BraseroMedium *medium,
 
539
                                guint num,
 
540
                                gint64 *size,
 
541
                                gint64 *blocks)
 
542
{
 
543
        BraseroMediumPrivate *priv;
 
544
        BraseroMediumTrack *track;
 
545
 
 
546
        g_return_val_if_fail (medium != NULL, FALSE);
 
547
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
548
 
 
549
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
550
 
 
551
        track = brasero_medium_get_track (medium, num);
 
552
        if (!track) {
 
553
                if (size)
 
554
                        *size = -1;
 
555
                if (blocks)
 
556
                        *blocks = -1;
 
557
                return FALSE;
 
558
        }
 
559
 
 
560
        if (size)
 
561
                *size = track->blocks_num * priv->block_size;
 
562
        if (blocks)
 
563
                *blocks = track->blocks_num;
 
564
 
 
565
        return TRUE;
 
566
}
 
567
 
 
568
/**
 
569
 * brasero_medium_get_track_address:
 
570
 * @medium: a #BraseroMedium
 
571
 * @num: a #guint
 
572
 * @byte: a #gint64 * or NULL
 
573
 * @sector: a #gint64 * or NULL
 
574
 *
 
575
 * Stores in either @byte (in bytes) or in @sector (in blocks) the address at
 
576
 * which the session identified by @num starts.
 
577
 *
 
578
 * Return value: a #gboolean. Returns TRUE if information could be retrieved;
 
579
 * FALSE otherwise (usually when track @num doesn't exist).
 
580
 *
 
581
 **/
 
582
gboolean
 
583
brasero_medium_get_track_address (BraseroMedium *medium,
 
584
                                  guint num,
 
585
                                  gint64 *byte,
 
586
                                  gint64 *sector)
 
587
{
 
588
        BraseroMediumPrivate *priv;
 
589
        BraseroMediumTrack *track;
 
590
 
 
591
        g_return_val_if_fail (medium != NULL, FALSE);
 
592
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
593
 
 
594
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
595
 
 
596
        track = brasero_medium_get_track (medium, num);
 
597
        if (!track) {
 
598
                if (byte)
 
599
                        *byte = -1;
 
600
                if (sector)
 
601
                        *sector = -1;
 
602
                return FALSE;
 
603
        }
 
604
 
 
605
        if (byte)
 
606
                *byte = track->start * priv->block_size;
 
607
        if (sector)
 
608
                *sector = track->start;
 
609
 
 
610
        return TRUE;    
 
611
}
 
612
 
 
613
/**
 
614
 * brasero_medium_get_next_writable_address:
 
615
 * @medium: #BraseroMedium
 
616
 *
 
617
 * Gets the address (block number) that can be used to write a new session on @medium
 
618
 *
 
619
 * Return value: a #gint64.
 
620
 *
 
621
 **/
 
622
gint64
 
623
brasero_medium_get_next_writable_address (BraseroMedium *medium)
 
624
{
 
625
        BraseroMediumPrivate *priv;
 
626
 
 
627
        g_return_val_if_fail (medium != NULL, 0);
 
628
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
 
629
 
 
630
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
631
 
 
632
        /* There is one exception to this with closed DVD+RW/DVD-RW restricted */
 
633
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)
 
634
        ||  BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED)
 
635
        ||  BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS_DL)) {
 
636
                BraseroMediumTrack *first;
 
637
 
 
638
                /* These are always writable so give the next address after the 
 
639
                 * last volume. */
 
640
                if (!priv->tracks)
 
641
                        return 0;
 
642
 
 
643
                first = priv->tracks->data;
 
644
 
 
645
                /* round to the nearest 16th block */
 
646
                return (((first->start + first->blocks_num) + 15) / 16) * 16;
 
647
        }
 
648
 
 
649
        return priv->next_wr_add;
 
650
}
 
651
 
 
652
/**
 
653
 * brasero_medium_get_max_write_speed:
 
654
 * @medium: #BraseroMedium
 
655
 *
 
656
 * Gets the maximum speed that can be used to write to @medium.
 
657
 * Note: the speed are in B/sec.
 
658
 *
 
659
 * Return value: a #gint64.
 
660
 *
 
661
 **/
 
662
guint64
 
663
brasero_medium_get_max_write_speed (BraseroMedium *medium)
 
664
{
 
665
        BraseroMediumPrivate *priv;
 
666
 
 
667
        g_return_val_if_fail (medium != NULL, 0);
 
668
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
 
669
 
 
670
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
671
        return priv->max_wrt * 1000;
 
672
}
 
673
 
 
674
/**
 
675
 * brasero_medium_get_write_speeds:
 
676
 * @medium: #BraseroMedium
 
677
 *
 
678
 * Gets an array holding all possible speeds to write to @medium.
 
679
 * Note: the speed are in B/sec.
 
680
 *
 
681
 * Return value: a #gint64 *.
 
682
 *
 
683
 **/
 
684
guint64 *
 
685
brasero_medium_get_write_speeds (BraseroMedium *medium)
 
686
{
 
687
        BraseroMediumPrivate *priv;
 
688
        guint64 *speeds;
 
689
        guint max = 0;
 
690
        guint i;
 
691
 
 
692
        g_return_val_if_fail (medium != NULL, NULL);
 
693
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
 
694
 
 
695
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
696
 
 
697
        if (!priv->wr_speeds)
 
698
                return NULL;
 
699
 
 
700
        while (priv->wr_speeds [max] != 0) max ++;
 
701
 
 
702
        speeds = g_new0 (guint64, max + 1);
 
703
 
 
704
        /* NOTE: about the following, it's not KiB here but KB */
 
705
        for (i = 0; i < max; i ++)
 
706
                speeds [i] = priv->wr_speeds [i] * 1000;
 
707
 
 
708
        return speeds;
 
709
}
 
710
 
 
711
/**
 
712
 * NOTEs about the following functions:
 
713
 * for all closed media (including ROM types) capacity == size of data and 
 
714
 * should be the size of all data on the disc, free space is 0
 
715
 * for all blank -R types capacity == free space and size of data == 0
 
716
 * for all multisession -R types capacity == free space since having the real
 
717
 * capacity of the media would be useless as we can only use this type of media
 
718
 * to append more data
 
719
 * for all -RW types capacity = free space + size of data. Here they can be 
 
720
 * appended (use free space) or rewritten (whole capacity).
 
721
 *
 
722
 * Usually:
 
723
 * the free space is the size of the leadout track
 
724
 * the size of data is the sum of track sizes (excluding leadout)
 
725
 * the capacity depends on the media:
 
726
 * for closed discs == sum of track sizes
 
727
 * for multisession discs == free space (leadout size)
 
728
 * for blank discs == (free space) leadout size
 
729
 * for rewritable/blank == use SCSI functions to get capacity (see below)
 
730
 *
 
731
 * In fact we should really need the size of data in DVD+/-RW cases since the
 
732
 * session is always equal to the size of the disc. 
 
733
 */
 
734
 
 
735
/**
 
736
 * brasero_medium_get_data_size:
 
737
 * @medium: #BraseroMedium
 
738
 * @size: a #gint64 * or NULL
 
739
 * @blocks: a #gint64 * or NULL
 
740
 *
 
741
 * Stores in either @size (in bytes) or @blocks (the number of blocks) the size
 
742
 * used to store data (including audio on CDs) on the disc.
 
743
 *
 
744
 **/
 
745
void
 
746
brasero_medium_get_data_size (BraseroMedium *medium,
 
747
                              gint64 *size,
 
748
                              gint64 *blocks)
 
749
{
 
750
        GSList *iter;
 
751
        BraseroMediumPrivate *priv;
 
752
        BraseroMediumTrack *track = NULL;
 
753
 
 
754
        g_return_if_fail (medium != NULL);
 
755
        g_return_if_fail (BRASERO_IS_MEDIUM (medium));
 
756
 
 
757
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
758
 
 
759
        if (!priv->tracks) {
 
760
                /* that's probably because it wasn't possible to retrieve info */
 
761
                if (size)
 
762
                        *size = 0;
 
763
 
 
764
                if (blocks)
 
765
                        *blocks = 0;
 
766
 
 
767
                return;
 
768
        }
 
769
 
 
770
        for (iter = priv->tracks; iter; iter = iter->next) {
 
771
                BraseroMediumTrack *tmp;
 
772
 
 
773
                tmp = iter->data;
 
774
                if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT)
 
775
                        break;
 
776
 
 
777
                track = iter->data;
 
778
        }
 
779
 
 
780
        if (size)
 
781
                *size = track ? (track->start + track->blocks_num) * priv->block_size: 0;
 
782
 
 
783
        if (blocks)
 
784
                *blocks = track ? track->start + track->blocks_num: 0;
 
785
}
 
786
 
 
787
/**
 
788
 * brasero_medium_get_free_space:
 
789
 * @medium: #BraseroMedium
 
790
 * @size: a #gint64 * or NULL
 
791
 * @blocks: a #gint64 * or NULL
 
792
 *
 
793
 * Stores in either @size (in bytes) or @blocks (the number of blocks) the space
 
794
 * on the disc that can be used for writing.
 
795
 *
 
796
 **/
 
797
void
 
798
brasero_medium_get_free_space (BraseroMedium *medium,
 
799
                               gint64 *size,
 
800
                               gint64 *blocks)
 
801
{
 
802
        GSList *iter;
 
803
        BraseroMediumPrivate *priv;
 
804
        BraseroMediumTrack *track = NULL;
 
805
 
 
806
        g_return_if_fail (medium != NULL);
 
807
        g_return_if_fail (BRASERO_IS_MEDIUM (medium));
 
808
 
 
809
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
810
 
 
811
        if (!priv->tracks) {
 
812
                /* that's probably because it wasn't possible to retrieve info.
 
813
                 * maybe it also happens with unformatted DVD+RW */
 
814
 
 
815
                if (priv->info & BRASERO_MEDIUM_CLOSED) {
 
816
                        if (size)
 
817
                                *size = 0;
 
818
 
 
819
                        if (blocks)
 
820
                                *blocks = 0;
 
821
                }
 
822
                else {
 
823
                        if (size)
 
824
                                *size = priv->block_num * priv->block_size;
 
825
 
 
826
                        if (blocks)
 
827
                                *blocks = priv->block_num;
 
828
                }
 
829
 
 
830
                return;
 
831
        }
 
832
 
 
833
        for (iter = priv->tracks; iter; iter = iter->next) {
 
834
                BraseroMediumTrack *tmp;
 
835
 
 
836
                tmp = iter->data;
 
837
                if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT) {
 
838
                        track = iter->data;
 
839
                        break;
 
840
                }
 
841
        }
 
842
 
 
843
        if (size) {
 
844
                if (!track) {
 
845
                        /* No leadout was found so the disc is probably closed:
 
846
                         * no free space left. */
 
847
                        *size = 0;
 
848
                }
 
849
                else if (track->blocks_num <= 0)
 
850
                        *size = (priv->block_num - track->start) * priv->block_size;
 
851
                else
 
852
                        *size = track->blocks_num * priv->block_size;
 
853
        }
 
854
 
 
855
        if (blocks) {
 
856
                if (!track) {
 
857
                        /* No leadout was found so the disc is probably closed:
 
858
                         * no free space left. */
 
859
                        *blocks = 0;
 
860
                }
 
861
                else if (track->blocks_num <= 0)
 
862
                        *blocks = priv->block_num - track->blocks_num;
 
863
                else
 
864
                        *blocks = track->blocks_num;
 
865
        }
 
866
}
 
867
 
 
868
/**
 
869
 * brasero_medium_get_capacity:
 
870
 * @medium: #BraseroMedium
 
871
 * @size: a #gint64 * or NULL
 
872
 * @blocks: a #gint64 * or NULL
 
873
 *
 
874
 * Stores in either @size (in bytes) or @blocks (the number of blocks) the total
 
875
 * disc space.
 
876
 * Note that when the disc is closed this space is the one occupied by data. 
 
877
 * Otherwise it is the sum of free and used space.
 
878
 *
 
879
 **/
 
880
void
 
881
brasero_medium_get_capacity (BraseroMedium *medium,
 
882
                             gint64 *size,
 
883
                             gint64 *blocks)
 
884
{
 
885
        BraseroMediumPrivate *priv;
 
886
 
 
887
        g_return_if_fail (medium != NULL);
 
888
        g_return_if_fail (BRASERO_IS_MEDIUM (medium));
 
889
 
 
890
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
891
 
 
892
        if (priv->info & BRASERO_MEDIUM_REWRITABLE) {
 
893
                if (size)
 
894
                        *size = priv->block_num * priv->block_size;
 
895
 
 
896
                if (blocks)
 
897
                        *blocks = priv->block_num;
 
898
        }
 
899
        else  if (priv->info & BRASERO_MEDIUM_CLOSED)
 
900
                brasero_medium_get_data_size (medium, size, blocks);
 
901
        else
 
902
                brasero_medium_get_free_space (medium, size, blocks);
 
903
}
 
904
 
 
905
/**
 
906
 * Test presence of simulate burning
 
907
 */
 
908
 
 
909
static BraseroBurnResult
 
910
brasero_medium_test_simulate_CD_SAO (BraseroMedium *self,
 
911
                                     BraseroDeviceHandle *handle,
 
912
                                     BraseroScsiErrCode *code)
 
913
{
 
914
        BraseroScsiGetConfigHdr *hdr = NULL;
 
915
        BraseroScsiCDTAODesc *tao_desc;
 
916
        BraseroScsiFeatureDesc *desc;
 
917
        BraseroMediumPrivate *priv;
 
918
        BraseroScsiResult result;
 
919
        int size;
 
920
 
 
921
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
922
 
 
923
        /* Try TAO and then SAO if it isn't persistent */
 
924
        BRASERO_MEDIA_LOG ("Checking simulate (CD TAO)");
 
925
        result = brasero_mmc2_get_configuration_feature (handle,
 
926
                                                         BRASERO_SCSI_FEAT_WRT_TAO,
 
927
                                                         &hdr,
 
928
                                                         &size,
 
929
                                                         code);
 
930
        if (result != BRASERO_SCSI_OK) {
 
931
                BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
 
932
                return BRASERO_BURN_ERR;
 
933
        }
 
934
 
 
935
        desc = hdr->desc;
 
936
        if (!desc->current)
 
937
                BRASERO_MEDIA_LOG ("Feature is not current");
 
938
 
 
939
        tao_desc = (BraseroScsiCDTAODesc *) desc->data;
 
940
        priv->dummy_tao = tao_desc->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
941
        priv->burnfree = tao_desc->buf ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
942
        g_free (hdr);
 
943
        return BRASERO_BURN_OK;
 
944
}
 
945
 
 
946
static BraseroBurnResult
 
947
brasero_medium_test_simulate_CD_TAO (BraseroMedium *self,
 
948
                                     BraseroDeviceHandle *handle,
 
949
                                     BraseroScsiErrCode *code)
 
950
{
 
951
        BraseroScsiGetConfigHdr *hdr = NULL;
 
952
        BraseroScsiCDSAODesc *sao_desc;
 
953
        BraseroScsiFeatureDesc *desc;
 
954
        BraseroMediumPrivate *priv;
 
955
        BraseroScsiResult result;
 
956
        int size;
 
957
 
 
958
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
959
 
 
960
        BRASERO_MEDIA_LOG ("Checking simulate (CD SAO)");
 
961
        result = brasero_mmc2_get_configuration_feature (handle,
 
962
                                                         BRASERO_SCSI_FEAT_WRT_SAO_RAW,
 
963
                                                         &hdr,
 
964
                                                         &size,
 
965
                                                         code);
 
966
        if (result != BRASERO_SCSI_OK) {
 
967
                BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
 
968
                return BRASERO_BURN_ERR;
 
969
        }
 
970
 
 
971
        desc = hdr->desc;
 
972
        if (!desc->current)
 
973
                BRASERO_MEDIA_LOG ("Feature is not current");
 
974
 
 
975
        sao_desc = (BraseroScsiCDSAODesc *) desc->data;
 
976
        priv->dummy_sao = sao_desc->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
977
        priv->burnfree = sao_desc->buf ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
978
        g_free (hdr);
 
979
        return BRASERO_BURN_OK;
 
980
}
 
981
 
 
982
static BraseroBurnResult
 
983
brasero_medium_test_simulate_DVDRW (BraseroMedium *self,
 
984
                                    BraseroDeviceHandle *handle,
 
985
                                    BraseroScsiErrCode *code)
 
986
{
 
987
        BraseroScsiDVDRWlessWrtDesc *less_wrt_desc;
 
988
        BraseroScsiGetConfigHdr *hdr = NULL;
 
989
        BraseroScsiFeatureDesc *desc;
 
990
        BraseroMediumPrivate *priv;
 
991
        BraseroScsiResult result;
 
992
        int size;
 
993
 
 
994
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
995
 
 
996
        /* Only DVD-R(W) support simulation */
 
997
        BRASERO_MEDIA_LOG ("Checking simulate (DVD-R/W)");
 
998
        result = brasero_mmc2_get_configuration_feature (handle,
 
999
                                                         BRASERO_SCSI_FEAT_WRT_DVD_LESS,
 
1000
                                                         &hdr,
 
1001
                                                         &size,
 
1002
                                                         code);
 
1003
        if (result != BRASERO_SCSI_OK) {
 
1004
                BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
 
1005
                return BRASERO_BURN_ERR;
 
1006
        }
 
1007
 
 
1008
        desc = hdr->desc;
 
1009
        if (!desc->current)
 
1010
                BRASERO_MEDIA_LOG ("Feature is not current");
 
1011
 
 
1012
        less_wrt_desc = (BraseroScsiDVDRWlessWrtDesc *) desc->data;
 
1013
        priv->dummy_sao = less_wrt_desc->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1014
        priv->dummy_tao = less_wrt_desc->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1015
        priv->burnfree = less_wrt_desc->buf ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1016
        g_free (hdr);
 
1017
        return BRASERO_BURN_OK;
 
1018
}
 
1019
 
 
1020
/**
 
1021
 * This is a last resort when the initialization has failed.
 
1022
 */
 
1023
 
 
1024
static void
 
1025
brasero_medium_test_simulate_2A (BraseroMedium *self,
 
1026
                                 BraseroDeviceHandle *handle,
 
1027
                                 BraseroScsiErrCode *code)
 
1028
{
 
1029
        BraseroScsiStatusPage *page_2A = NULL;
 
1030
        BraseroScsiModeData *data = NULL;
 
1031
        BraseroMediumPrivate *priv;
 
1032
        BraseroScsiResult result;
 
1033
        int size = 0;
 
1034
 
 
1035
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1036
 
 
1037
        result = brasero_spc1_mode_sense_get_page (handle,
 
1038
                                                   BRASERO_SPC_PAGE_STATUS,
 
1039
                                                   &data,
 
1040
                                                   &size,
 
1041
                                                   code);
 
1042
        if (result != BRASERO_SCSI_OK) {
 
1043
                BRASERO_MEDIA_LOG ("MODE SENSE failed");
 
1044
                return;
 
1045
        }
 
1046
 
 
1047
        /* NOTE: this bit is only valid:
 
1048
         * - for CDs when mode write is TAO or SAO
 
1049
         * - for DVDs when mode write is incremental or SAO
 
1050
         */
 
1051
 
 
1052
        page_2A = (BraseroScsiStatusPage *) &data->page;
 
1053
        priv->dummy_sao = page_2A->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1054
        priv->dummy_tao = page_2A->dummy ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1055
        priv->burnfree = page_2A->buffer ? BRASERO_MEDIUM_CAP_TRUE:BRASERO_MEDIUM_CAP_FALSE;
 
1056
        g_free (data);
 
1057
}
 
1058
 
 
1059
static void
 
1060
brasero_medium_init_caps (BraseroMedium *self,
 
1061
                          BraseroDeviceHandle *handle,
 
1062
                          BraseroScsiErrCode *code)
 
1063
{
 
1064
        BraseroMediumPrivate *priv;
 
1065
        BraseroScsiResult res;
 
1066
 
 
1067
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1068
 
 
1069
        /* These special media don't support/need burnfree and simulation */
 
1070
        if (priv->info & (BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_BD))
 
1071
                return;
 
1072
 
 
1073
        if (priv->info & BRASERO_MEDIUM_CD) {
 
1074
                /* we have to do both */
 
1075
                res = brasero_medium_test_simulate_CD_SAO (self, handle, code);
 
1076
                if (res == BRASERO_SCSI_OK)
 
1077
                        brasero_medium_test_simulate_CD_TAO (self, handle, code);
 
1078
        }
 
1079
        else
 
1080
                res = brasero_medium_test_simulate_DVDRW (self, handle, code);
 
1081
 
 
1082
        BRASERO_MEDIA_LOG ("Tested simulation %d %d, burnfree %d",
 
1083
                          priv->dummy_tao,
 
1084
                          priv->dummy_sao,
 
1085
                          priv->burnfree);
 
1086
 
 
1087
        if (res == BRASERO_SCSI_OK)
 
1088
                return;
 
1089
 
 
1090
        /* it didn't work out as expected use fallback */
 
1091
        BRASERO_MEDIA_LOG ("Using fallback 2A page for testing simulation and burnfree");
 
1092
        brasero_medium_test_simulate_2A (self, handle, code);
 
1093
 
 
1094
        BRASERO_MEDIA_LOG ("Re-tested simulation %d %d, burnfree %d",
 
1095
                          priv->dummy_tao,
 
1096
                          priv->dummy_sao,
 
1097
                          priv->burnfree);
 
1098
}
 
1099
 
 
1100
/**
 
1101
 * Function to retrieve the capacity of a media
 
1102
 */
 
1103
 
 
1104
static BraseroBurnResult
 
1105
brasero_medium_get_capacity_CD_RW (BraseroMedium *self,
 
1106
                                   BraseroDeviceHandle *handle,
 
1107
                                   BraseroScsiErrCode *code)
 
1108
{
 
1109
        BraseroScsiAtipData *atip_data = NULL;
 
1110
        BraseroMediumPrivate *priv;
 
1111
        BraseroScsiResult result;
 
1112
        int size = 0;
 
1113
 
 
1114
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1115
 
 
1116
        BRASERO_MEDIA_LOG ("Retrieving capacity from atip");
 
1117
 
 
1118
        result = brasero_mmc1_read_atip (handle,
 
1119
                                         &atip_data,
 
1120
                                         &size,
 
1121
                                         NULL);
 
1122
 
 
1123
        if (result != BRASERO_SCSI_OK) {
 
1124
                BRASERO_MEDIA_LOG ("READ ATIP failed (scsi error)");
 
1125
                return BRASERO_BURN_ERR;
 
1126
        }
 
1127
 
 
1128
        /* check the size of the structure: it must be at least 16 bytes long */
 
1129
        if (size < 16) {
 
1130
                if (size)
 
1131
                        g_free (atip_data);
 
1132
 
 
1133
                BRASERO_MEDIA_LOG ("READ ATIP failed (wrong size)");
 
1134
                return BRASERO_BURN_ERR;
 
1135
        }
 
1136
 
 
1137
        priv->block_num = BRASERO_MSF_TO_LBA (atip_data->desc->leadout_mn,
 
1138
                                              atip_data->desc->leadout_sec,
 
1139
                                              atip_data->desc->leadout_frame);
 
1140
        g_free (atip_data);
 
1141
 
 
1142
        BRASERO_MEDIA_LOG ("Format capacity %lli %lli",
 
1143
                           priv->block_num,
 
1144
                           priv->block_size);
 
1145
 
 
1146
        return BRASERO_BURN_OK;
 
1147
}
 
1148
 
 
1149
static BraseroBurnResult
 
1150
brasero_medium_get_capacity_DVD_RW (BraseroMedium *self,
 
1151
                                    BraseroDeviceHandle *handle,
 
1152
                                    BraseroScsiErrCode *code)
 
1153
{
 
1154
        BraseroScsiFormatCapacitiesHdr *hdr = NULL;
 
1155
        BraseroScsiFormattableCapacityDesc *desc;
 
1156
        BraseroScsiMaxCapacityDesc *current;
 
1157
        BraseroMediumPrivate *priv;
 
1158
        BraseroScsiResult result;
 
1159
        gint i, max;
 
1160
        gint size;
 
1161
 
 
1162
        BRASERO_MEDIA_LOG ("Retrieving format capacity");
 
1163
 
 
1164
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1165
        result = brasero_mmc2_read_format_capacities (handle,
 
1166
                                                      &hdr,
 
1167
                                                      &size,
 
1168
                                                      code);
 
1169
        if (result != BRASERO_SCSI_OK) {
 
1170
                BRASERO_MEDIA_LOG ("READ FORMAT CAPACITIES failed");
 
1171
                return BRASERO_BURN_ERR;
 
1172
        }
 
1173
 
 
1174
        /* NOTE: for BD-RE there is a slight problem to determine the exact
 
1175
         * capacity of the medium when it is unformatted. Indeed the final size
 
1176
         * of the User Data Area will depend on the size of the Spare areas.
 
1177
         * On the other hand if it's formatted then that's OK, just take the 
 
1178
         * current one.
 
1179
         * NOTE: that could work also for BD-R SRM+POW and BD-R RRM */
 
1180
 
 
1181
        /* see if the media is already formatted */
 
1182
        current = hdr->max_caps;
 
1183
        if (!(current->type & BRASERO_SCSI_DESC_FORMATTED)) {
 
1184
                BRASERO_MEDIA_LOG ("Unformatted media");
 
1185
                priv->info |= BRASERO_MEDIUM_UNFORMATTED;
 
1186
 
 
1187
                /* if unformatted, a DVD-RAM will return its maximum formattable
 
1188
                 * size in this descriptor and that's what we're looking for. */
 
1189
                if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVD_RAM)) {
 
1190
                        priv->block_num = BRASERO_GET_32 (current->blocks_num);
 
1191
                        priv->block_size = 2048;
 
1192
                        goto end;
 
1193
                }
 
1194
        }
 
1195
        else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE)) {
 
1196
                priv->block_num = BRASERO_GET_32 (current->blocks_num);
 
1197
                priv->block_size = 2048;
 
1198
                goto end;
 
1199
        }
 
1200
 
 
1201
        max = (hdr->len - 
 
1202
              sizeof (BraseroScsiMaxCapacityDesc)) /
 
1203
              sizeof (BraseroScsiFormattableCapacityDesc);
 
1204
 
 
1205
        desc = hdr->desc;
 
1206
        for (i = 0; i < max; i ++, desc ++) {
 
1207
                /* search for the correct descriptor */
 
1208
                if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)) {
 
1209
                        if (desc->format_type == BRASERO_SCSI_DVDRW_PLUS) {
 
1210
                                priv->block_num = BRASERO_GET_32 (desc->blocks_num);
 
1211
                                priv->block_size = BRASERO_GET_24 (desc->type_param);
 
1212
 
 
1213
                                /* that can happen */
 
1214
                                if (!priv->block_size)
 
1215
                                        priv->block_size = 2048;
 
1216
 
 
1217
                                break;
 
1218
                        }
 
1219
                }
 
1220
                else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE)) {
 
1221
                        /* This is for unformatted BDRE: since we can't know the
 
1222
                         * size of the Spare Area in advance, we take the vendor
 
1223
                         * preferred one. Always following are the smallest one
 
1224
                         * and the biggest one. */
 
1225
                        if (desc->format_type == BRASERO_SCSI_BDRE_FORMAT) {
 
1226
                                priv->block_num = BRASERO_GET_32 (desc->blocks_num);
 
1227
                                break;
 
1228
                        }
 
1229
                }
 
1230
                else if (desc->format_type == BRASERO_SCSI_MAX_PACKET_SIZE_FORMAT) {
 
1231
                        priv->block_num = BRASERO_GET_32 (desc->blocks_num);
 
1232
                        break;
 
1233
                }
 
1234
        }
 
1235
 
 
1236
end:
 
1237
 
 
1238
        BRASERO_MEDIA_LOG ("Format capacity %lli %lli",
 
1239
                          priv->block_num,
 
1240
                          priv->block_size);
 
1241
 
 
1242
        g_free (hdr);
 
1243
        return BRASERO_BURN_OK;
 
1244
}
 
1245
 
 
1246
static BraseroBurnResult
 
1247
brasero_medium_get_capacity_by_type (BraseroMedium *self,
 
1248
                                     BraseroDeviceHandle *handle,
 
1249
                                     BraseroScsiErrCode *code)
 
1250
{
 
1251
        BraseroMediumPrivate *priv;
 
1252
 
 
1253
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1254
 
 
1255
        /* For DVDs/BDs that's always that block size */
 
1256
        priv->block_size = 2048;
 
1257
 
 
1258
        if (!(priv->info & BRASERO_MEDIUM_REWRITABLE))
 
1259
                return BRASERO_BURN_OK;
 
1260
 
 
1261
        if (priv->info & BRASERO_MEDIUM_CD)
 
1262
                brasero_medium_get_capacity_CD_RW (self, handle, code);
 
1263
        else    /* Works for BD-RE as well */
 
1264
                brasero_medium_get_capacity_DVD_RW (self, handle, code);
 
1265
 
 
1266
        return BRASERO_BURN_OK;
 
1267
}
 
1268
 
 
1269
/**
 
1270
 * Functions to retrieve the speed
 
1271
 */
 
1272
 
 
1273
static BraseroBurnResult
 
1274
brasero_medium_get_speed_mmc3 (BraseroMedium *self,
 
1275
                               BraseroDeviceHandle *handle,
 
1276
                               BraseroScsiErrCode *code)
 
1277
{
 
1278
        int size = 0;
 
1279
        int num_desc, i;
 
1280
        gint max_rd, max_wrt;
 
1281
        BraseroScsiResult result;
 
1282
        BraseroMediumPrivate *priv;
 
1283
        BraseroScsiWrtSpdDesc *desc;
 
1284
        BraseroScsiGetPerfData *wrt_perf = NULL;
 
1285
 
 
1286
        BRASERO_MEDIA_LOG ("Retrieving speed (Get Performance)");
 
1287
 
 
1288
        /* NOTE: this only work if there is RT streaming feature with
 
1289
         * wspd bit set to 1. At least an MMC3 drive. */
 
1290
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1291
        result = brasero_mmc3_get_performance_wrt_spd_desc (handle,
 
1292
                                                            &wrt_perf,
 
1293
                                                            &size,
 
1294
                                                            code);
 
1295
 
 
1296
        if (result != BRASERO_SCSI_OK) {
 
1297
                BRASERO_MEDIA_LOG ("GET PERFORMANCE failed");
 
1298
                return BRASERO_BURN_ERR;
 
1299
        }
 
1300
 
 
1301
        BRASERO_MEDIA_LOG ("Successfully retrieved a header: size %d, address %p", size, wrt_perf);
 
1302
 
 
1303
        /* Choose the smallest value for size */
 
1304
        size = MIN (size, BRASERO_GET_32 (wrt_perf->hdr.len) + sizeof (wrt_perf->hdr.len));
 
1305
        BRASERO_MEDIA_LOG ("Updated header size = %d", size);
 
1306
 
 
1307
        /* NOTE: I don't know why but on some architecture/with some compilers
 
1308
         * when size < sizeof (BraseroScsiGetPerfHdr) the whole operation below
 
1309
         * is treated as signed which leads to have an outstanding number of 
 
1310
         * descriptors instead of a negative one. So be anal when checking. */
 
1311
        if (size <= (sizeof (BraseroScsiGetPerfHdr) + sizeof (BraseroScsiWrtSpdDesc))) {
 
1312
                BRASERO_MEDIA_LOG ("No descriptors");
 
1313
                goto end;
 
1314
        }
 
1315
 
 
1316
        /* Calculate the number of descriptors */
 
1317
        num_desc = (size - sizeof (BraseroScsiGetPerfHdr)) / sizeof (BraseroScsiWrtSpdDesc);
 
1318
        BRASERO_MEDIA_LOG ("Got %d descriptor(s)", num_desc);
 
1319
 
 
1320
        if (num_desc <= 0)
 
1321
                goto end; 
 
1322
 
 
1323
        priv->rd_speeds = g_new0 (guint, num_desc + 1);
 
1324
        priv->wr_speeds = g_new0 (guint, num_desc + 1);
 
1325
 
 
1326
        max_rd = 0;
 
1327
        max_wrt = 0;
 
1328
 
 
1329
        desc = (BraseroScsiWrtSpdDesc*) &wrt_perf->data;
 
1330
 
 
1331
        for (i = 0; i < num_desc; i ++) {
 
1332
                BRASERO_MEDIA_LOG ("Descriptor n° %d, address = %p", i, (desc + i));
 
1333
 
 
1334
                priv->rd_speeds [i] = BRASERO_GET_32 (desc [i].rd_speed);
 
1335
                priv->wr_speeds [i] = BRASERO_GET_32 (desc [i].wr_speed);
 
1336
 
 
1337
                BRASERO_MEDIA_LOG ("RD = %u / WRT = %u",
 
1338
                                   priv->rd_speeds [i],
 
1339
                                   priv->wr_speeds [i]);
 
1340
 
 
1341
                max_rd = MAX (max_rd, priv->rd_speeds [i]);
 
1342
                max_wrt = MAX (max_wrt, priv->wr_speeds [i]);
 
1343
        }
 
1344
 
 
1345
        priv->max_rd = max_rd;
 
1346
        priv->max_wrt = max_wrt;
 
1347
 
 
1348
        BRASERO_MEDIA_LOG ("Maximum Speed (mmc3) %i", max_wrt);
 
1349
 
 
1350
end:
 
1351
 
 
1352
        g_free (wrt_perf);
 
1353
 
 
1354
        /* strangely there are so drives (I know one case) which support this
 
1355
         * function but don't report any speed. So if our top speed is 0 then
 
1356
         * use the other way to get the speed. It was a Teac */
 
1357
        if (!priv->max_wrt)
 
1358
                return BRASERO_BURN_ERR;
 
1359
 
 
1360
        return BRASERO_BURN_OK;
 
1361
}
 
1362
 
 
1363
static BraseroBurnResult
 
1364
brasero_medium_get_page_2A_write_speed_desc (BraseroMedium *self,
 
1365
                                             BraseroDeviceHandle *handle,
 
1366
                                             BraseroScsiErrCode *code)
 
1367
{
 
1368
        BraseroScsiStatusPage *page_2A = NULL;
 
1369
        BraseroScsiStatusWrSpdDesc *desc;
 
1370
        BraseroScsiModeData *data = NULL;
 
1371
        BraseroMediumPrivate *priv;
 
1372
        BraseroScsiResult result;
 
1373
        gint desc_num, i;
 
1374
        gint max_wrt = 0;
 
1375
        gint max_num;
 
1376
        int size = 0;
 
1377
 
 
1378
        BRASERO_MEDIA_LOG ("Retrieving speed (2A speeds)");
 
1379
 
 
1380
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1381
        result = brasero_spc1_mode_sense_get_page (handle,
 
1382
                                                   BRASERO_SPC_PAGE_STATUS,
 
1383
                                                   &data,
 
1384
                                                   &size,
 
1385
                                                   code);
 
1386
        if (result != BRASERO_SCSI_OK) {
 
1387
                BRASERO_MEDIA_LOG ("MODE SENSE failed");
 
1388
                return BRASERO_BURN_ERR;
 
1389
        }
 
1390
 
 
1391
        page_2A = (BraseroScsiStatusPage *) &data->page;
 
1392
 
 
1393
        /* Reminder: size = sizeof (BraseroScsiStatusPage) + sizeof (BraseroScsiModeHdr) */
 
1394
        size = MIN (size, sizeof (data->hdr.len) + BRASERO_GET_16 (data->hdr.len));
 
1395
 
 
1396
        if (size < (G_STRUCT_OFFSET (BraseroScsiStatusPage, copy_mngt_rev) + sizeof (BraseroScsiModeHdr))) {
 
1397
                g_free (data);
 
1398
                BRASERO_MEDIA_LOG ("wrong page size");
 
1399
                return BRASERO_BURN_ERR;
 
1400
        }
 
1401
 
 
1402
        priv->max_rd = BRASERO_GET_16 (page_2A->rd_max_speed);
 
1403
        priv->max_wrt = BRASERO_GET_16 (page_2A->wr_max_speed);
 
1404
 
 
1405
        /* Check if we can use the speed descriptors. There must be at least one
 
1406
         * available; if not use maximum speed member. */
 
1407
        if (size < (G_STRUCT_OFFSET (BraseroScsiStatusPage, wr_spd_desc) +
 
1408
                    sizeof (BraseroScsiModeHdr) +
 
1409
                    sizeof (BraseroScsiWrtSpdDesc))) {
 
1410
                BRASERO_MEDIA_LOG ("Maximum Speed (Page 2A [old]) %i", priv->max_wrt);
 
1411
 
 
1412
                /* also add fake speed descriptors */
 
1413
                priv->wr_speeds = g_new0 (gint, 2);
 
1414
                priv->wr_speeds [0] = BRASERO_GET_16 (page_2A->wr_max_speed);
 
1415
                priv->rd_speeds = g_new0 (gint, 2);
 
1416
                priv->rd_speeds [0] = BRASERO_GET_16 (page_2A->rd_max_speed);
 
1417
 
 
1418
                g_free (data);
 
1419
                return BRASERO_BURN_OK;
 
1420
        }
 
1421
 
 
1422
        desc_num = BRASERO_GET_16 (page_2A->wr_speed_desc_num);
 
1423
        max_num = size -
 
1424
                  sizeof (BraseroScsiStatusPage) -
 
1425
                  sizeof (BraseroScsiModeHdr);
 
1426
        max_num /= sizeof (BraseroScsiWrtSpdDesc);
 
1427
 
 
1428
        if (max_num < 0)
 
1429
                max_num = 0;
 
1430
 
 
1431
        if (desc_num > max_num)
 
1432
                desc_num = max_num;
 
1433
 
 
1434
        priv->wr_speeds = g_new0 (gint, desc_num + 1);
 
1435
 
 
1436
        desc = page_2A->wr_spd_desc;
 
1437
        for (i = 0; i < desc_num; i ++) {
 
1438
                priv->wr_speeds [i] = BRASERO_GET_16 (desc [i].speed);
 
1439
                max_wrt = MAX (max_wrt, priv->wr_speeds [i]);
 
1440
        }
 
1441
 
 
1442
        if (max_wrt)
 
1443
                priv->max_wrt = max_wrt;
 
1444
 
 
1445
        BRASERO_MEDIA_LOG ("Maximum Speed (Page 2A) %i", priv->max_wrt);
 
1446
        g_free (data);
 
1447
 
 
1448
        return BRASERO_BURN_OK;
 
1449
}
 
1450
 
 
1451
static BraseroBurnResult
 
1452
brasero_medium_get_speed (BraseroMedium *self,
 
1453
                          BraseroDeviceHandle *handle,
 
1454
                          BraseroScsiErrCode *code)
 
1455
{
 
1456
        BraseroScsiResult result;
 
1457
 
 
1458
        BRASERO_MEDIA_LOG ("Retrieving media available speeds");
 
1459
 
 
1460
        result = brasero_medium_get_speed_mmc3 (self, handle, code);
 
1461
        if (result == BRASERO_BURN_OK)
 
1462
                return result;
 
1463
 
 
1464
        /* Fallback */
 
1465
        result = brasero_medium_get_page_2A_write_speed_desc (self, handle, code);
 
1466
        return result;
 
1467
}
 
1468
 
 
1469
/**
 
1470
 * Functions to get information about disc contents
 
1471
 */
 
1472
 
 
1473
static BraseroBurnResult
 
1474
brasero_medium_track_volume_size (BraseroMedium *self,
 
1475
                                  BraseroMediumTrack *track,
 
1476
                                  BraseroDeviceHandle *handle)
 
1477
{
 
1478
        BraseroMediumPrivate *priv;
 
1479
        BraseroBurnResult res;
 
1480
        GError *error = NULL;
 
1481
        BraseroVolSrc *vol;
 
1482
        gint64 nb_blocks;
 
1483
 
 
1484
        if (!track)
 
1485
                return BRASERO_BURN_ERR;
 
1486
 
 
1487
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1488
 
 
1489
        /* This is a special case. For DVD+RW and DVD-RW in restricted
 
1490
         * mode, there is only one session that takes the whole disc size
 
1491
         * once formatted. That doesn't necessarily means they have data
 
1492
         * Note also that they are reported as complete though you can
 
1493
         * still add data (with growisofs). It is nevertheless on the 
 
1494
         * condition that the fs is valid.
 
1495
         * So we check if their first and only volume is valid. 
 
1496
         * That's also used when the track size is reported 300 KiB
 
1497
         * see below */
 
1498
        vol = brasero_volume_source_open_device_handle (handle, NULL);
 
1499
        res = brasero_volume_get_size (vol,
 
1500
                                       track->start,
 
1501
                                       &nb_blocks,
 
1502
                                       &error);
 
1503
        brasero_volume_source_close (vol);
 
1504
 
 
1505
        if (!res) {
 
1506
                BRASERO_MEDIA_LOG ("Failed to retrieve the volume size: %s",
 
1507
                                  error && error->message ? 
 
1508
                                  error->message:"unknown error");
 
1509
 
 
1510
                if (error)
 
1511
                        g_error_free (error);
 
1512
 
 
1513
                return BRASERO_BURN_ERR;
 
1514
        }
 
1515
 
 
1516
        track->blocks_num = nb_blocks;
 
1517
        return BRASERO_BURN_OK;
 
1518
}
 
1519
 
 
1520
static gboolean
 
1521
brasero_medium_track_written_SAO (BraseroDeviceHandle *handle,
 
1522
                                  int track_num,
 
1523
                                  int track_start)
 
1524
{
 
1525
        unsigned char buffer [2048];
 
1526
        BraseroScsiResult result;
 
1527
 
 
1528
        BRASERO_MEDIA_LOG ("Checking for TDBs in track pregap.");
 
1529
 
 
1530
        /* The two following sectors are readable */
 
1531
        result = brasero_mmc1_read_block (handle,
 
1532
                                          TRUE,
 
1533
                                          BRASERO_SCSI_BLOCK_TYPE_ANY,
 
1534
                                          BRASERO_SCSI_BLOCK_HEADER_NONE,
 
1535
                                          BRASERO_SCSI_BLOCK_NO_SUBCHANNEL,
 
1536
                                          track_start - 1,
 
1537
                                          1,
 
1538
                                          buffer,
 
1539
                                          sizeof (buffer),
 
1540
                                          NULL);
 
1541
 
 
1542
        if (result == BRASERO_SCSI_OK) {
 
1543
                int i;
 
1544
 
 
1545
                if (buffer [0] != 'T' || buffer [1] != 'D' || buffer [2] != 'I') {
 
1546
                        BRASERO_MEDIA_LOG ("Track was probably recorded in SAO mode - no TDB.");
 
1547
                        return TRUE;
 
1548
                }
 
1549
 
 
1550
                /* Find the TDU (16 bytes) for the track (there can be for other tracks).
 
1551
                 * i must be < 128 = ((2048 - 8 (size TDB)) / 16 (size TDU). */
 
1552
                for (i = 0; i < 128; i ++) {
 
1553
                        if (BRASERO_GET_BCD (buffer [8 + i * 16]) != track_num)
 
1554
                                break;
 
1555
                }
 
1556
 
 
1557
                if (i >= 128) {
 
1558
                        BRASERO_MEDIA_LOG ("No appropriate TDU for track");
 
1559
                        return TRUE;
 
1560
                }
 
1561
 
 
1562
                if (buffer [8 + i * 16] == 0x80 || buffer [8 + i * 16] == 0x00) {
 
1563
                        BRASERO_MEDIA_LOG ("Track was recorded in TAO mode.");
 
1564
                        return FALSE;
 
1565
                }
 
1566
 
 
1567
                BRASERO_MEDIA_LOG ("Track was recorded in Packet mode.");
 
1568
                return FALSE;
 
1569
        }
 
1570
 
 
1571
        BRASERO_MEDIA_LOG ("No pregap. That track must have been recorded in SAO mode.");
 
1572
        return TRUE;
 
1573
}
 
1574
 
 
1575
static BraseroBurnResult
 
1576
brasero_medium_track_get_info (BraseroMedium *self,
 
1577
                               gboolean multisession,
 
1578
                               BraseroMediumTrack *track,
 
1579
                               int track_num,
 
1580
                               BraseroDeviceHandle *handle,
 
1581
                               BraseroScsiErrCode *code)
 
1582
{
 
1583
        BraseroScsiTrackInfo track_info;
 
1584
        BraseroMediumPrivate *priv;
 
1585
        BraseroScsiResult result;
 
1586
        int size;
 
1587
 
 
1588
        BRASERO_MEDIA_LOG ("Retrieving track information for %i", track_num);
 
1589
 
 
1590
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1591
 
 
1592
        /* at this point we know the type of the disc that's why we set the 
 
1593
         * size according to this type. That may help to avoid outrange address
 
1594
         * errors. */
 
1595
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DUAL_L|BRASERO_MEDIUM_WRITABLE))
 
1596
                size = 48;
 
1597
        else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_WRITABLE))
 
1598
                size = 40;
 
1599
        else
 
1600
                size = 36;
 
1601
 
 
1602
        result = brasero_mmc1_read_track_info (handle,
 
1603
                                               track_num,
 
1604
                                               &track_info,
 
1605
                                               &size,
 
1606
                                               code);
 
1607
 
 
1608
        if (result != BRASERO_SCSI_OK) {
 
1609
                BRASERO_MEDIA_LOG ("READ TRACK INFO failed");
 
1610
                return BRASERO_BURN_ERR;
 
1611
        }
 
1612
 
 
1613
        track->blocks_num = BRASERO_GET_32 (track_info.track_size);
 
1614
        track->session = BRASERO_SCSI_SESSION_NUM (track_info);
 
1615
 
 
1616
        if (track->blocks_num <= 300) {
 
1617
                /* Now here is a potential bug: we can write tracks (data or
 
1618
                 * not) shorter than 300 KiB /2 sec but they will be padded to
 
1619
                 * reach this floor value. It means that blocks_num is always
 
1620
                 * 300 blocks even if the data length on the track is actually
 
1621
                 * shorter.
 
1622
                 * So we read the volume descriptor. If it works, good otherwise
 
1623
                 * use the old value.
 
1624
                 * That's important for checksuming to have a perfect account of
 
1625
                 * the data size. */
 
1626
                BRASERO_MEDIA_LOG ("300 sectors size. Checking for real size");
 
1627
                brasero_medium_track_volume_size (self, track, handle);
 
1628
        }
 
1629
        /* NOTE: for multisession CDs only
 
1630
         * if the session was incremental (TAO/packet/...) by opposition to DAO
 
1631
         * and SAO, then 2 blocks (run-out) have been added at the end of user
 
1632
         * track for linking. That's why we have 2 additional sectors when the
 
1633
         * track has been recorded in TAO mode
 
1634
         * See MMC5
 
1635
         * 6.44.3.2 CD-R Fixed Packet, Variable Packet, Track-At-Once
 
1636
         * Now, strangely track_get_info always removes two blocks, whereas read
 
1637
         * raw toc adds them (always) and this, whatever the mode, the position.
 
1638
         * It means that when we detect a SAO session we have to add 2 blocks to
 
1639
         * all tracks in it. 
 
1640
         * See # for any information:
 
1641
         * if first track is recorded in SAO/DAO then the length will be two sec
 
1642
         * shorter. If not, if it was recorded in TAO, that's fine.
 
1643
         * The other way would be to use read raw toc but then that's the
 
1644
         * opposite that happens and that latter will return two more bytes for
 
1645
         * TAO recorded session.
 
1646
         * So there are 2 workarounds:
 
1647
         * - read the volume size (can be unreliable)
 
1648
         * - read the 2 last blocks and see if they are run-outs
 
1649
         * here we do solution 2 but only for CDRW, not blank, and for first
 
1650
         * session only since that's the only one that can be recorded in DAO. */
 
1651
        else if (track->session == 1
 
1652
             && (track->type & BRASERO_MEDIUM_TRACK_DATA)
 
1653
             &&  multisession
 
1654
             &&  (priv->info & BRASERO_MEDIUM_CD)
 
1655
             && !(priv->info & BRASERO_MEDIUM_ROM)) {
 
1656
                BRASERO_MEDIA_LOG ("Data track belongs to first session of multisession CD. "
 
1657
                                  "Checking for real size (%i sectors currently).",
 
1658
                                  track->blocks_num);
 
1659
 
 
1660
                /* we test the pregaps blocks for TDB: these are special blocks
 
1661
                 * filling the pregap of a track when it was recorded as TAO or
 
1662
                 * as Packet.
 
1663
                 * NOTE: in this case we need to skip 7 sectors before since if
 
1664
                 * it was recorded incrementally then there is also 4 runins,
 
1665
                 * 1 link sector and 2 runouts (at end of pregap). 
 
1666
                 * we also make sure that the two blocks we're adding are
 
1667
                 * actually readable. */
 
1668
                /* Test the last block, the before last and the one before before last */
 
1669
                result = brasero_mmc1_read_block (handle,
 
1670
                                                  FALSE,
 
1671
                                                  BRASERO_SCSI_BLOCK_TYPE_ANY,
 
1672
                                                  BRASERO_SCSI_BLOCK_HEADER_NONE,
 
1673
                                                  BRASERO_SCSI_BLOCK_NO_SUBCHANNEL,
 
1674
                                                  track->blocks_num + track->start,
 
1675
                                                  2,
 
1676
                                                  NULL,
 
1677
                                                  0,
 
1678
                                                  NULL);
 
1679
 
 
1680
                if (result == BRASERO_SCSI_OK) {
 
1681
                        BRASERO_MEDIA_LOG ("Following two sectors are readable.");
 
1682
 
 
1683
                        if (brasero_medium_track_written_SAO (handle, track_num, track->start)) {
 
1684
                                track->blocks_num += 2;
 
1685
                                BRASERO_MEDIA_LOG ("Correcting track size (now %i)", track->blocks_num);
 
1686
                        }
 
1687
                }
 
1688
                else
 
1689
                        BRASERO_MEDIA_LOG ("Detected runouts");
 
1690
        }
 
1691
 
 
1692
        /* NOTE: DVD+RW, DVD-RW (restricted overwrite) never reach this function */
 
1693
        BRASERO_MEDIA_LOG ("Track %i (session %i): type = %i start = %llu size = %llu",
 
1694
                          track_num,
 
1695
                          track->session,
 
1696
                          track->type,
 
1697
                          track->start,
 
1698
                          track->blocks_num);
 
1699
 
 
1700
        return BRASERO_BURN_OK;
 
1701
}
 
1702
 
 
1703
static BraseroBurnResult
 
1704
brasero_medium_track_set_leadout_DVDR_blank (BraseroMedium *self,
 
1705
                                             BraseroDeviceHandle *handle,
 
1706
                                             BraseroMediumTrack *leadout,
 
1707
                                             BraseroScsiErrCode *code)
 
1708
{
 
1709
        BraseroScsiFormatCapacitiesHdr *hdr = NULL;
 
1710
        BraseroScsiMaxCapacityDesc *current;
 
1711
        BraseroMediumPrivate *priv;
 
1712
        BraseroScsiResult result;
 
1713
        int size;
 
1714
 
 
1715
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1716
 
 
1717
        BRASERO_MEDIA_LOG ("Using fallback method for blank CDR to retrieve NWA and leadout information");
 
1718
 
 
1719
        /* NWA is easy for blank DVD-Rs, it's 0. So far, so good... */
 
1720
        priv->next_wr_add = 0;
 
1721
 
 
1722
        result = brasero_mmc2_read_format_capacities (handle,
 
1723
                                                      &hdr,
 
1724
                                                      &size,
 
1725
                                                      code);
 
1726
        if (result != BRASERO_SCSI_OK) {
 
1727
                BRASERO_MEDIA_LOG ("READ FORMAT CAPACITIES failed");
 
1728
                return BRASERO_BURN_ERR;
 
1729
        }
 
1730
 
 
1731
        /* See if the media is already formatted which means for -R media that 
 
1732
         * they are blank. */
 
1733
        current = hdr->max_caps;
 
1734
        if (current->type & BRASERO_SCSI_DESC_FORMATTED) {
 
1735
                BRASERO_MEDIA_LOG ("Unformatted medium");
 
1736
                g_free (hdr);
 
1737
                return BRASERO_BURN_ERR;
 
1738
        }
 
1739
                
 
1740
        BRASERO_MEDIA_LOG ("Unformatted medium");
 
1741
 
 
1742
        /* of course it starts at 0 since it's empty */
 
1743
        leadout->start = 0;
 
1744
        leadout->blocks_num = BRASERO_GET_32 (current->blocks_num);
 
1745
 
 
1746
        BRASERO_MEDIA_LOG ("Leadout (through READ FORMAT CAPACITIES): start = %llu size = %llu",
 
1747
                          leadout->start,
 
1748
                          leadout->blocks_num);
 
1749
 
 
1750
        g_free (hdr);
 
1751
        return BRASERO_BURN_OK;
 
1752
}
 
1753
 
 
1754
static BraseroBurnResult
 
1755
brasero_medium_track_set_leadout_CDR_blank (BraseroMedium *self,
 
1756
                                            BraseroDeviceHandle *handle,
 
1757
                                            BraseroMediumTrack *leadout,
 
1758
                                            BraseroScsiErrCode *code)
 
1759
{
 
1760
        BraseroScsiAtipData *atip = NULL;
 
1761
        BraseroMediumPrivate *priv;
 
1762
        BraseroScsiResult result;
 
1763
        int size = 0;
 
1764
 
 
1765
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1766
 
 
1767
        BRASERO_MEDIA_LOG ("Using fallback method for blank CDR to retrieve NWA and leadout information");
 
1768
 
 
1769
        /* NWA is easy for blank CDRs, it's 0. So far, so good... */
 
1770
        priv->next_wr_add = 0;
 
1771
 
 
1772
        result = brasero_mmc1_read_atip (handle, &atip, &size, code);
 
1773
        if (result != BRASERO_SCSI_OK) {
 
1774
                BRASERO_MEDIA_LOG ("READ ATIP failed");
 
1775
                return BRASERO_BURN_ERR;
 
1776
        }
 
1777
 
 
1778
        leadout->blocks_num = atip->desc->leadout_mn * 60 * 75 +
 
1779
                              atip->desc->leadout_sec * 75 +
 
1780
                              atip->desc->leadout_frame;
 
1781
 
 
1782
        /* of course it starts at 0 since it's empty */
 
1783
        leadout->start = 0;
 
1784
 
 
1785
        BRASERO_MEDIA_LOG ("Leadout (through READ ATIP): start = %llu size = %llu",
 
1786
                          leadout->start,
 
1787
                          leadout->blocks_num);
 
1788
 
 
1789
        g_free (atip);
 
1790
 
 
1791
        return BRASERO_BURN_OK;
 
1792
}
 
1793
 
 
1794
static BraseroBurnResult
 
1795
brasero_medium_set_write_mode_page (BraseroMedium *self,
 
1796
                                    BraseroDeviceHandle *handle,
 
1797
                                    BraseroScsiErrCode *code)
 
1798
{
 
1799
        BraseroScsiModeData *data = NULL;
 
1800
        BraseroScsiWritePage *wrt_page;
 
1801
        BraseroMediumPrivate *priv;
 
1802
        BraseroScsiResult result;
 
1803
        int size;
 
1804
 
 
1805
        BRASERO_MEDIA_LOG ("Setting write mode page");
 
1806
 
 
1807
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1808
 
 
1809
        /* NOTE: this works for CDR, DVDR+-, BDR-SRM */
 
1810
        /* make sure the current write mode is TAO. Otherwise the drive will
 
1811
         * return the first sector of the pregap instead of the first user
 
1812
         * accessible sector. */
 
1813
        result = brasero_spc1_mode_sense_get_page (handle,
 
1814
                                                   BRASERO_SPC_PAGE_WRITE,
 
1815
                                                   &data,
 
1816
                                                   &size,
 
1817
                                                   code);
 
1818
        if (result == BRASERO_SCSI_OK) {
 
1819
                wrt_page = (BraseroScsiWritePage *) &data->page;
 
1820
 
 
1821
                BRASERO_MEDIA_LOG ("Former write type %d", wrt_page->write_type);
 
1822
                BRASERO_MEDIA_LOG ("Former track mode %d", wrt_page->track_mode);
 
1823
                BRASERO_MEDIA_LOG ("Former data block type %d", wrt_page->data_block_type);
 
1824
 
 
1825
                /* "reset some stuff to be on the safe side" (words and ideas
 
1826
                 * taken from k3b:)). */
 
1827
                wrt_page->ps = 0;
 
1828
                wrt_page->BUFE = 0;
 
1829
                wrt_page->multisession = 0;
 
1830
                wrt_page->testwrite = 0;
 
1831
                wrt_page->LS_V = 0;
 
1832
                wrt_page->copy = 0;
 
1833
                wrt_page->FP = 0;
 
1834
                wrt_page->session_format = 0;
 
1835
                BRASERO_SET_16 (wrt_page->pause_len, 150);
 
1836
 
 
1837
                if (priv->info & BRASERO_MEDIUM_CD) {
 
1838
                        wrt_page->write_type = BRASERO_SCSI_WRITE_TAO;
 
1839
                        wrt_page->track_mode = 4;
 
1840
                }
 
1841
                else if (priv->info & BRASERO_MEDIUM_DVD) {
 
1842
                        wrt_page->write_type = BRASERO_SCSI_WRITE_PACKET_INC;
 
1843
                        wrt_page->track_mode = 5;
 
1844
                }
 
1845
 
 
1846
                wrt_page->data_block_type = 8;
 
1847
 
 
1848
                result = brasero_spc1_mode_select (handle, data, size, code);
 
1849
                g_free (data);
 
1850
 
 
1851
                if (result != BRASERO_SCSI_OK) {
 
1852
                        BRASERO_MEDIA_LOG ("MODE SELECT failed");
 
1853
 
 
1854
                        /* This isn't necessarily a problem! we better try */
 
1855
                        return BRASERO_BURN_ERR;
 
1856
                }
 
1857
        }
 
1858
        else {
 
1859
                BRASERO_MEDIA_LOG ("MODE SENSE failed");
 
1860
                /* This isn't necessarily a problem! we better try the rest */
 
1861
                return BRASERO_BURN_ERR;
 
1862
        }
 
1863
 
 
1864
        return BRASERO_BURN_OK;
 
1865
}
 
1866
 
 
1867
static BraseroBurnResult
 
1868
brasero_medium_track_set_leadout (BraseroMedium *self,
 
1869
                                  BraseroDeviceHandle *handle,
 
1870
                                  BraseroMediumTrack *leadout,
 
1871
                                  BraseroScsiErrCode *code)
 
1872
{
 
1873
        BraseroScsiTrackInfo track_info;
 
1874
        BraseroMediumPrivate *priv;
 
1875
        BraseroScsiResult result;
 
1876
        gint track_num;
 
1877
        int size;
 
1878
 
 
1879
        BRASERO_MEDIA_LOG ("Retrieving NWA and leadout information");
 
1880
 
 
1881
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1882
 
 
1883
        if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info)) {
 
1884
                BRASERO_MEDIA_LOG ("Overwritable medium  => skipping");
 
1885
                return BRASERO_BURN_OK;
 
1886
        }
 
1887
 
 
1888
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDR)) {
 
1889
                /* This is necessary to make sure nwa won't be the start of the
 
1890
                 * pregap if the current write mode is SAO with blank CDR.
 
1891
                 * Carry on even if it fails.
 
1892
                 * This can work with CD-R/W and DVD-R/W. + media don't use the
 
1893
                 * write mode page anyway. */
 
1894
                result = brasero_medium_set_write_mode_page (self, handle, code);
 
1895
                if (result == BRASERO_BURN_ERR
 
1896
                &&  BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDR|BRASERO_MEDIUM_BLANK))
 
1897
                        return brasero_medium_track_set_leadout_CDR_blank (self,
 
1898
                                                                           handle,
 
1899
                                                                           leadout,
 
1900
                                                                           code);
 
1901
        }
 
1902
 
 
1903
        /* At this point we know the type of the disc that's why we set the 
 
1904
         * size according to this type. That may help to avoid outrange address
 
1905
         * errors. */
 
1906
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DUAL_L|BRASERO_MEDIUM_WRITABLE))
 
1907
                size = 48;
 
1908
        else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_WRITABLE))
 
1909
                size = 40;
 
1910
        else
 
1911
                size = 36;
 
1912
 
 
1913
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDR)
 
1914
        ||  BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDRW)
 
1915
        /* The following includes DL */
 
1916
        ||  BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR_PLUS)) 
 
1917
                track_num = 0xFF;
 
1918
        else if (priv->first_open_track >= 0)
 
1919
                track_num = priv->first_open_track;
 
1920
        else {
 
1921
                BRASERO_MEDIA_LOG ("There aren't any open session set");
 
1922
                return BRASERO_BURN_ERR;
 
1923
        }
 
1924
 
 
1925
        result = brasero_mmc1_read_track_info (handle,
 
1926
                                               track_num,
 
1927
                                               &track_info,
 
1928
                                               &size,
 
1929
                                               code);
 
1930
        if (result != BRASERO_SCSI_OK) {
 
1931
                BRASERO_MEDIA_LOG ("READ TRACK INFO failed");
 
1932
 
 
1933
                /* This only for CD-R */
 
1934
                if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDR|BRASERO_MEDIUM_BLANK))
 
1935
                        return brasero_medium_track_set_leadout_CDR_blank (self,
 
1936
                                                                           handle,
 
1937
                                                                           leadout,
 
1938
                                                                           code);
 
1939
                else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BLANK))
 
1940
                        return brasero_medium_track_set_leadout_DVDR_blank (self,
 
1941
                                                                            handle,
 
1942
                                                                            leadout,
 
1943
                                                                            code);
 
1944
                         
 
1945
                return BRASERO_BURN_ERR;
 
1946
        }
 
1947
 
 
1948
        BRASERO_MEDIA_LOG ("Next Writable Address is %d", BRASERO_GET_32 (track_info.next_wrt_address));
 
1949
        if (track_info.next_wrt_address_valid)
 
1950
                priv->next_wr_add = BRASERO_GET_32 (track_info.next_wrt_address);
 
1951
        else
 
1952
                BRASERO_MEDIA_LOG ("Next Writable Address is not valid");
 
1953
 
 
1954
        /* Set free space */
 
1955
        BRASERO_MEDIA_LOG ("Free blocks %d", BRASERO_GET_32 (track_info.free_blocks));
 
1956
        leadout->blocks_num = BRASERO_GET_32 (track_info.free_blocks);
 
1957
 
 
1958
        if (!leadout->blocks_num) {
 
1959
                leadout->blocks_num = BRASERO_GET_32 (track_info.track_size);
 
1960
                BRASERO_MEDIA_LOG ("Using track size %d", leadout->blocks_num);
 
1961
        }
 
1962
 
 
1963
        if (!leadout->blocks_num
 
1964
        &&   BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BLANK))
 
1965
                return brasero_medium_track_set_leadout_DVDR_blank (self,
 
1966
                                                                    handle,
 
1967
                                                                    leadout,
 
1968
                                                                    code);
 
1969
 
 
1970
        BRASERO_MEDIA_LOG ("Leadout: start = %llu size = %llu",
 
1971
                          leadout->start,
 
1972
                          leadout->blocks_num);
 
1973
 
 
1974
        return BRASERO_BURN_OK;
 
1975
}
 
1976
 
 
1977
/**
 
1978
 * NOTE: for DVD-R multisession we lose 28688 blocks for each session
 
1979
 * so the capacity is the addition of all session sizes + 28688 for each
 
1980
 * For all multisession DVD-/+R and CDR-RW the remaining size is given 
 
1981
 * in the leadout. One exception though with DVD+/-RW.
 
1982
 */
 
1983
 
 
1984
static void
 
1985
brasero_medium_add_DVD_plus_RW_leadout (BraseroMedium *self)
 
1986
{
 
1987
        BraseroMediumTrack *leadout;
 
1988
        BraseroMediumPrivate *priv;
 
1989
        gint64 blocks_num;
 
1990
        gint32 start;
 
1991
 
 
1992
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
1993
 
 
1994
        /* determine the start */
 
1995
        if (priv->tracks) {
 
1996
                BraseroMediumTrack *track;
 
1997
 
 
1998
                track = priv->tracks->data;
 
1999
                start = track->start + track->blocks_num;
 
2000
                blocks_num = priv->block_num - ((track->blocks_num > 300) ? track->blocks_num : 300);
 
2001
        }
 
2002
        else {
 
2003
                start = 0;
 
2004
                blocks_num = priv->block_num;
 
2005
        }
 
2006
 
 
2007
        leadout = g_new0 (BraseroMediumTrack, 1);
 
2008
        priv->tracks = g_slist_append (priv->tracks, leadout);
 
2009
 
 
2010
        leadout->start = start;
 
2011
        leadout->blocks_num = blocks_num;
 
2012
        leadout->type = BRASERO_MEDIUM_TRACK_LEADOUT;
 
2013
 
 
2014
        /* we fabricate the leadout here. We don't really need one in 
 
2015
         * fact since it is always at the last sector whatever the
 
2016
         * amount of data written. So we need in fact to read the file
 
2017
         * system and get the last sector from it. Hopefully it won't be
 
2018
         * buggy */
 
2019
        priv->next_wr_add = 0;
 
2020
 
 
2021
        BRASERO_MEDIA_LOG ("Adding fabricated leadout start = %llu length = %llu",
 
2022
                          leadout->start,
 
2023
                          leadout->blocks_num);
 
2024
}
 
2025
 
 
2026
static BraseroBurnResult
 
2027
brasero_medium_get_sessions_info (BraseroMedium *self,
 
2028
                                  BraseroDeviceHandle *handle,
 
2029
                                  BraseroScsiErrCode *code)
 
2030
{
 
2031
        int num, i, size;
 
2032
        gboolean multisession;
 
2033
        BraseroScsiResult result;
 
2034
        BraseroScsiTocDesc *desc;
 
2035
        BraseroMediumPrivate *priv;
 
2036
        BraseroScsiFormattedTocData *toc = NULL;
 
2037
 
 
2038
        BRASERO_MEDIA_LOG ("Reading Toc");
 
2039
 
 
2040
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2041
        result = brasero_mmc1_read_toc_formatted (handle,
 
2042
                                                  0,
 
2043
                                                  &toc,
 
2044
                                                  &size,
 
2045
                                                  code);
 
2046
        if (result != BRASERO_SCSI_OK) {
 
2047
                BRASERO_MEDIA_LOG ("READ TOC failed");
 
2048
                return BRASERO_BURN_ERR;
 
2049
        }
 
2050
 
 
2051
        num = (size - sizeof (BraseroScsiFormattedTocData)) /
 
2052
               sizeof (BraseroScsiTocDesc);
 
2053
 
 
2054
        /* remove 1 for leadout */
 
2055
        multisession = !(priv->info & BRASERO_MEDIUM_BLANK) && num > 0;
 
2056
 
 
2057
        /* NOTE: in the case of DVD- there are always only 3 sessions if they
 
2058
         * are open: all first concatenated sessions, the last session, and the
 
2059
         * leadout. */
 
2060
        
 
2061
        BRASERO_MEDIA_LOG ("%i track(s) found", num);
 
2062
 
 
2063
        desc = toc->desc;
 
2064
        for (i = 0; i < num; i ++, desc ++) {
 
2065
                BraseroMediumTrack *track;
 
2066
 
 
2067
                if (desc->track_num == BRASERO_SCSI_TRACK_LEADOUT_START) {
 
2068
                        BRASERO_MEDIA_LOG ("Leadout reached %d",
 
2069
                                          BRASERO_GET_32 (desc->track_start));
 
2070
                        break;
 
2071
                }
 
2072
 
 
2073
                track = g_new0 (BraseroMediumTrack, 1);
 
2074
                priv->tracks = g_slist_prepend (priv->tracks, track);
 
2075
                track->start = BRASERO_GET_32 (desc->track_start);
 
2076
 
 
2077
                /* we shouldn't request info on a track if the disc is closed */
 
2078
                if (desc->control & BRASERO_SCSI_TRACK_COPY)
 
2079
                        track->type |= BRASERO_MEDIUM_TRACK_COPY;
 
2080
 
 
2081
                if (!(desc->control & BRASERO_SCSI_TRACK_DATA)) {
 
2082
                        track->type |= BRASERO_MEDIUM_TRACK_AUDIO;
 
2083
                        priv->info |= BRASERO_MEDIUM_HAS_AUDIO;
 
2084
 
 
2085
                        if (desc->control & BRASERO_SCSI_TRACK_PREEMP)
 
2086
                                track->type |= BRASERO_MEDIUM_TRACK_PREEMP;
 
2087
 
 
2088
                        if (desc->control & BRASERO_SCSI_TRACK_4_CHANNELS)
 
2089
                                track->type |= BRASERO_MEDIUM_TRACK_4_CHANNELS;
 
2090
                }
 
2091
                else {
 
2092
                        track->type |= BRASERO_MEDIUM_TRACK_DATA;
 
2093
                        priv->info |= BRASERO_MEDIUM_HAS_DATA;
 
2094
 
 
2095
                        if (desc->control & BRASERO_SCSI_TRACK_DATA_INCREMENTAL)
 
2096
                                track->type |= BRASERO_MEDIUM_TRACK_INCREMENTAL;
 
2097
                }
 
2098
 
 
2099
                if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info)) {
 
2100
                        BraseroBurnResult result;
 
2101
 
 
2102
                        /* A special case for these kinds of media (DVD+RW, ...)
 
2103
                         * which have only one track: the first. Since it's not
 
2104
                         * possible to know the amount of data that were really
 
2105
                         * written in this session, read the filesystem. */
 
2106
                        BRASERO_MEDIA_LOG ("DVD+RW (DL) or DVD-RW (restricted overwrite) checking volume size (start = %i)", track->start);
 
2107
                        track->session = 1;
 
2108
                        track->start = 0;
 
2109
                        result = brasero_medium_track_volume_size (self, 
 
2110
                                                                   track,
 
2111
                                                                   handle);
 
2112
                        if (result != BRASERO_BURN_OK) {
 
2113
                                priv->tracks = g_slist_remove (priv->tracks, track);
 
2114
                                g_free (track);
 
2115
 
 
2116
                                priv->info |= BRASERO_MEDIUM_BLANK;
 
2117
                                priv->info &= ~(BRASERO_MEDIUM_CLOSED|
 
2118
                                                BRASERO_MEDIUM_HAS_DATA);
 
2119
 
 
2120
                                BRASERO_MEDIA_LOG ("Empty first session.");
 
2121
                        }
 
2122
                        else {
 
2123
                                priv->next_wr_add = 0;
 
2124
                                BRASERO_MEDIA_LOG ("Track 1 (session %i): type = %i start = %llu size = %llu",
 
2125
                                                  track->session,
 
2126
                                                  track->type,
 
2127
                                                  track->start,
 
2128
                                                  track->blocks_num);
 
2129
                        }
 
2130
 
 
2131
                        /* NOTE: the next track should be the leadout */
 
2132
                        continue;
 
2133
                }
 
2134
 
 
2135
                if (priv->probe_cancelled) {
 
2136
                        g_free (toc);
 
2137
                        return BRASERO_BURN_CANCEL;
 
2138
                }
 
2139
 
 
2140
                brasero_medium_track_get_info (self,
 
2141
                                               multisession,
 
2142
                                               track,
 
2143
                                               g_slist_length (priv->tracks),
 
2144
                                               handle,
 
2145
                                               code);
 
2146
        }
 
2147
 
 
2148
        if (priv->probe_cancelled) {
 
2149
                g_free (toc);
 
2150
                return BRASERO_BURN_CANCEL;
 
2151
        }
 
2152
 
 
2153
        /* put the tracks in the right order */
 
2154
        priv->tracks = g_slist_reverse (priv->tracks);
 
2155
 
 
2156
        if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info))
 
2157
                brasero_medium_add_DVD_plus_RW_leadout (self);
 
2158
        else if (!(priv->info & BRASERO_MEDIUM_CLOSED)) {
 
2159
                BraseroMediumTrack *leadout;
 
2160
 
 
2161
                /* we shouldn't request info on leadout if the disc is closed
 
2162
                 * (except for DVD+/- (restricted) RW (see above) */
 
2163
                leadout = g_new0 (BraseroMediumTrack, 1);
 
2164
                leadout->start = BRASERO_GET_32 (desc->track_start);
 
2165
                leadout->type = BRASERO_MEDIUM_TRACK_LEADOUT;
 
2166
                priv->tracks = g_slist_append (priv->tracks, leadout);
 
2167
 
 
2168
                brasero_medium_track_set_leadout (self,
 
2169
                                                  handle,
 
2170
                                                  leadout,
 
2171
                                                  code);
 
2172
        }
 
2173
 
 
2174
        g_free (toc);
 
2175
 
 
2176
        return BRASERO_BURN_OK;
 
2177
}
 
2178
 
 
2179
static void
 
2180
brasero_medium_get_DVD_id (BraseroMedium *self,
 
2181
                           BraseroDeviceHandle *handle,
 
2182
                           BraseroScsiErrCode *code)
 
2183
{
 
2184
        gint size = 0;
 
2185
        BraseroScsiResult result;
 
2186
        BraseroMediumPrivate *priv;
 
2187
        BraseroScsiReadDiscStructureHdr *hdr = NULL;
 
2188
 
 
2189
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2190
 
 
2191
        /* This should be only possible for DVD-R(W) and not with all drives */
 
2192
        result = brasero_mmc2_read_generic_structure (handle,
 
2193
                                                      BRASERO_SCSI_FORMAT_LESS_MEDIA_ID_DVD,
 
2194
                                                      &hdr,
 
2195
                                                      &size,
 
2196
                                                      code);
 
2197
        if (result != BRASERO_SCSI_OK) {
 
2198
                BRASERO_MEDIA_LOG ("Retrieval of DVD id failed");
 
2199
                return;
 
2200
        }
 
2201
 
 
2202
        BRASERO_MEDIA_LOG ("DVD id %d", BRASERO_GET_16 (hdr->data + 2));
 
2203
        priv->id = g_strdup_printf ("%d", BRASERO_GET_16 (hdr->data + 2));
 
2204
        g_free (hdr);
 
2205
}
 
2206
 
 
2207
static BraseroBurnResult
 
2208
brasero_medium_set_blank (BraseroMedium *self,
 
2209
                          BraseroDeviceHandle *handle,
 
2210
                          gint first_open_track,
 
2211
                          BraseroScsiErrCode *code)
 
2212
{
 
2213
        BraseroMediumPrivate *priv;
 
2214
        BraseroMediumTrack *track;
 
2215
 
 
2216
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2217
 
 
2218
        BRASERO_MEDIA_LOG ("Empty media");
 
2219
 
 
2220
        priv->info |= BRASERO_MEDIUM_BLANK;
 
2221
        priv->block_size = 2048;
 
2222
 
 
2223
        priv->first_open_track = first_open_track;
 
2224
        BRASERO_MEDIA_LOG ("First open track %d", priv->first_open_track);
 
2225
 
 
2226
        if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info))
 
2227
                brasero_medium_add_DVD_plus_RW_leadout (self);
 
2228
        else {
 
2229
                track = g_new0 (BraseroMediumTrack, 1);
 
2230
                track->start = 0;
 
2231
                track->type = BRASERO_MEDIUM_TRACK_LEADOUT;
 
2232
                priv->tracks = g_slist_prepend (priv->tracks, track);
 
2233
                        
 
2234
                brasero_medium_track_set_leadout (self,
 
2235
                                                  handle,
 
2236
                                                  track,
 
2237
                                                  code);
 
2238
        }
 
2239
 
 
2240
        return BRASERO_BURN_OK;
 
2241
}
 
2242
 
 
2243
static BraseroBurnResult
 
2244
brasero_medium_get_contents (BraseroMedium *self,
 
2245
                             BraseroDeviceHandle *handle,
 
2246
                             BraseroScsiErrCode *code)
 
2247
{
 
2248
        int size;
 
2249
        BraseroBurnResult res;
 
2250
        BraseroScsiResult result;
 
2251
        BraseroMediumPrivate *priv;
 
2252
        BraseroScsiDiscInfoStd *info = NULL;
 
2253
 
 
2254
        BRASERO_MEDIA_LOG ("Retrieving media status");
 
2255
 
 
2256
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2257
 
 
2258
        result = brasero_mmc1_read_disc_information_std (handle,
 
2259
                                                         &info,
 
2260
                                                         &size,
 
2261
                                                         code);
 
2262
        if (result != BRASERO_SCSI_OK) {
 
2263
                BRASERO_MEDIA_LOG ("READ DISC INFORMATION failed");
 
2264
                return BRASERO_BURN_ERR;
 
2265
        }
 
2266
 
 
2267
        if (info->disc_id_valid) {
 
2268
                /* Try to get the disc identification if possible (CDs only) */
 
2269
                BRASERO_MEDIA_LOG ("Disc id %i", BRASERO_GET_32 (info->disc_id));
 
2270
                priv->id = g_strdup_printf ("%d", BRASERO_GET_32 (info->disc_id));
 
2271
        }
 
2272
        else if (priv->info & BRASERO_MEDIUM_DVD)
 
2273
                brasero_medium_get_DVD_id (self, handle, code);
 
2274
 
 
2275
        if (info->erasable)
 
2276
                priv->info |= BRASERO_MEDIUM_REWRITABLE;
 
2277
 
 
2278
        priv->first_open_track = -1;
 
2279
 
 
2280
        if (info->status == BRASERO_SCSI_DISC_EMPTY) {
 
2281
                res = brasero_medium_set_blank (self,
 
2282
                                                handle,
 
2283
                                                BRASERO_FIRST_TRACK_IN_LAST_SESSION (info),
 
2284
                                                code);
 
2285
        }
 
2286
        else if (info->status == BRASERO_SCSI_DISC_INCOMPLETE) {
 
2287
                if (!BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info)) {
 
2288
                        priv->info |= BRASERO_MEDIUM_APPENDABLE;
 
2289
                        BRASERO_MEDIA_LOG ("Appendable media");
 
2290
 
 
2291
                        priv->first_open_track = BRASERO_FIRST_TRACK_IN_LAST_SESSION (info);
 
2292
                        BRASERO_MEDIA_LOG ("First track in last open session %d", priv->first_open_track);
 
2293
 
 
2294
                        res = brasero_medium_get_sessions_info (self, handle, code);
 
2295
                }
 
2296
                else {
 
2297
                        /* if that type of media is in incomplete state that
 
2298
                         * means it has just been formatted. And therefore it's
 
2299
                         * blank. */
 
2300
                        res = brasero_medium_set_blank (self,
 
2301
                                                        handle,
 
2302
                                                        BRASERO_FIRST_TRACK_IN_LAST_SESSION (info),
 
2303
                                                        code);
 
2304
                }
 
2305
        }
 
2306
        else if (info->status == BRASERO_SCSI_DISC_FINALIZED) {
 
2307
                priv->info |= BRASERO_MEDIUM_CLOSED;
 
2308
                BRASERO_MEDIA_LOG ("Closed media");
 
2309
 
 
2310
                res = brasero_medium_get_sessions_info (self, handle, code);
 
2311
        }
 
2312
 
 
2313
        g_free (info);
 
2314
        return res;
 
2315
}
 
2316
 
 
2317
/**
 
2318
 * Some identification functions
 
2319
 */
 
2320
 
 
2321
static BraseroBurnResult
 
2322
brasero_medium_get_medium_type (BraseroMedium *self,
 
2323
                                BraseroDeviceHandle *handle,
 
2324
                                BraseroScsiErrCode *code)
 
2325
{
 
2326
        BraseroScsiProfile profile;
 
2327
        BraseroMediumPrivate *priv;
 
2328
        BraseroScsiResult result;
 
2329
 
 
2330
        BRASERO_MEDIA_LOG ("Retrieving media profile");
 
2331
 
 
2332
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2333
        result = brasero_mmc2_get_profile (handle, &profile, code);
 
2334
 
 
2335
        if (result != BRASERO_SCSI_OK) {
 
2336
                BraseroScsiAtipData *data = NULL;
 
2337
                int size = 0;
 
2338
 
 
2339
                BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
 
2340
 
 
2341
                /* This could be a MMC1 drive since this command was
 
2342
                 * introduced in MMC2 and is supported onward. So it
 
2343
                 * has to be a CD (R/RW). The rest of the information
 
2344
                 * will be provided by read_disc_information. */
 
2345
 
 
2346
                /* retrieve the speed */
 
2347
                result = brasero_medium_get_page_2A_write_speed_desc (self,
 
2348
                                                                      handle,
 
2349
                                                                      code);
 
2350
 
 
2351
                /* If this fails it means that this drive is probably older than
 
2352
                 * MMC1 spec or does not conform to it. */
 
2353
                if (result != BRASERO_BURN_OK)
 
2354
                        return BRASERO_BURN_ERR;
 
2355
 
 
2356
                /* The only thing here left to determine is if that's a WRITABLE
 
2357
                 * or a REWRITABLE. To determine that information, we need to
 
2358
                 * read TocPmaAtip. It if fails that's a ROM, if it succeeds.
 
2359
                 * No need to set error code since we consider that it's a ROM
 
2360
                 * if a failure happens. */
 
2361
                result = brasero_mmc1_read_atip (handle,
 
2362
                                                 &data,
 
2363
                                                 &size,
 
2364
                                                 NULL);
 
2365
                if (result != BRASERO_SCSI_OK) {
 
2366
                        /* CDROM */
 
2367
                        priv->info = BRASERO_MEDIUM_CDROM;
 
2368
                        priv->type = types [1];
 
2369
                }
 
2370
                else {
 
2371
                        /* check the size of the structure: it must be at least 8 bytes long */
 
2372
                        if (size < 8) {
 
2373
                                if (size)
 
2374
                                        g_free (data);
 
2375
 
 
2376
                                BRASERO_MEDIA_LOG ("READ ATIP failed (wrong size)");
 
2377
                                return BRASERO_BURN_ERR;
 
2378
                        }
 
2379
 
 
2380
                        if (data->desc->erasable) {
 
2381
                                /* CDRW */
 
2382
                                priv->info = BRASERO_MEDIUM_CDRW;
 
2383
                                priv->type = types [3];
 
2384
                        }
 
2385
                        else {
 
2386
                                /* CDR */
 
2387
                                priv->info = BRASERO_MEDIUM_CDR;
 
2388
                                priv->type = types [2];
 
2389
                        }
 
2390
 
 
2391
                        g_free (data);
 
2392
                }
 
2393
 
 
2394
                return result;
 
2395
        }
 
2396
 
 
2397
        switch (profile) {
 
2398
        case BRASERO_SCSI_PROF_CDROM:
 
2399
                priv->info = BRASERO_MEDIUM_CDROM;
 
2400
                priv->type = types [1];
 
2401
                break;
 
2402
 
 
2403
        case BRASERO_SCSI_PROF_CDR:
 
2404
                priv->info = BRASERO_MEDIUM_CDR;
 
2405
                priv->type = types [2];
 
2406
                break;
 
2407
 
 
2408
        case BRASERO_SCSI_PROF_CDRW:
 
2409
                priv->info = BRASERO_MEDIUM_CDRW;
 
2410
                priv->type = types [3];
 
2411
                break;
 
2412
 
 
2413
        case BRASERO_SCSI_PROF_DVD_ROM:
 
2414
                priv->info = BRASERO_MEDIUM_DVD_ROM;
 
2415
                priv->type = types [4];
 
2416
                break;
 
2417
 
 
2418
        case BRASERO_SCSI_PROF_DVD_R:
 
2419
                priv->info = BRASERO_MEDIUM_DVDR;
 
2420
                priv->type = types [5];
 
2421
                break;
 
2422
 
 
2423
        case BRASERO_SCSI_PROF_DVD_RW_RESTRICTED:
 
2424
                priv->info = BRASERO_MEDIUM_DVDRW_RESTRICTED;
 
2425
                priv->type = types [6];
 
2426
                break;
 
2427
 
 
2428
        case BRASERO_SCSI_PROF_DVD_RW_SEQUENTIAL:
 
2429
                priv->info = BRASERO_MEDIUM_DVDRW;
 
2430
                priv->type = types [6];
 
2431
                break;
 
2432
 
 
2433
        case BRASERO_SCSI_PROF_DVD_R_PLUS:
 
2434
                priv->info = BRASERO_MEDIUM_DVDR_PLUS;
 
2435
                priv->type = types [7];
 
2436
                break;
 
2437
 
 
2438
        case BRASERO_SCSI_PROF_DVD_RW_PLUS:
 
2439
                priv->info = BRASERO_MEDIUM_DVDRW_PLUS;
 
2440
                priv->type = types [8];
 
2441
                break;
 
2442
 
 
2443
        case BRASERO_SCSI_PROF_DVD_R_PLUS_DL:
 
2444
                priv->info = BRASERO_MEDIUM_DVDR_PLUS_DL;
 
2445
                priv->type = types [9];
 
2446
                break;
 
2447
 
 
2448
        case BRASERO_SCSI_PROF_DVD_RW_PLUS_DL:
 
2449
                priv->info = BRASERO_MEDIUM_DVDRW_PLUS_DL;
 
2450
                priv->type = types [10];
 
2451
                break;
 
2452
 
 
2453
        case BRASERO_SCSI_PROF_DVD_R_DL_SEQUENTIAL:
 
2454
                priv->info = BRASERO_MEDIUM_DVDR_DL;
 
2455
                priv->type = types [11];
 
2456
                break;
 
2457
 
 
2458
        case BRASERO_SCSI_PROF_DVD_R_DL_JUMP:
 
2459
                priv->info = BRASERO_MEDIUM_DVDR_JUMP_DL;
 
2460
                priv->type = types [11];
 
2461
                break;
 
2462
 
 
2463
        case BRASERO_SCSI_PROF_BD_ROM:
 
2464
                priv->info = BRASERO_MEDIUM_BD_ROM;
 
2465
                priv->type = types [13];
 
2466
                break;
 
2467
 
 
2468
        case BRASERO_SCSI_PROF_BR_R_SEQUENTIAL:
 
2469
                /* check if that's a POW later */
 
2470
                priv->info = BRASERO_MEDIUM_BDR_SRM;
 
2471
                priv->type = types [14];
 
2472
                break;
 
2473
 
 
2474
        case BRASERO_SCSI_PROF_BR_R_RANDOM:
 
2475
                priv->info = BRASERO_MEDIUM_BDR_RANDOM;
 
2476
                priv->type = types [14];
 
2477
                break;
 
2478
 
 
2479
        case BRASERO_SCSI_PROF_BD_RW:
 
2480
                priv->info = BRASERO_MEDIUM_BDRE;
 
2481
                priv->type = types [15];
 
2482
                break;
 
2483
 
 
2484
        case BRASERO_SCSI_PROF_DVD_RAM:
 
2485
                priv->info = BRASERO_MEDIUM_DVD_RAM;
 
2486
                priv->type = types [12];
 
2487
                break;
 
2488
 
 
2489
        /* WARNING: these types are recognized, no more */
 
2490
        case BRASERO_SCSI_PROF_NON_REMOVABLE:
 
2491
        case BRASERO_SCSI_PROF_REMOVABLE:
 
2492
        case BRASERO_SCSI_PROF_MO_ERASABLE:
 
2493
        case BRASERO_SCSI_PROF_MO_WRITE_ONCE:
 
2494
        case BRASERO_SCSI_PROF_MO_ADVANCED_STORAGE:
 
2495
        case BRASERO_SCSI_PROF_DDCD_ROM:
 
2496
        case BRASERO_SCSI_PROF_DDCD_R:
 
2497
        case BRASERO_SCSI_PROF_DDCD_RW:
 
2498
        case BRASERO_SCSI_PROF_HD_DVD_ROM:
 
2499
        case BRASERO_SCSI_PROF_HD_DVD_R:
 
2500
        case BRASERO_SCSI_PROF_HD_DVD_RAM:
 
2501
                priv->info = BRASERO_MEDIUM_UNSUPPORTED;
 
2502
                return BRASERO_BURN_NOT_SUPPORTED;
 
2503
        }
 
2504
 
 
2505
        /* Get a more precise idea of what sequential BD-R type we have here */
 
2506
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDR_SRM)) {
 
2507
                BraseroScsiGetConfigHdr *hdr = NULL;
 
2508
                int size = 0;
 
2509
 
 
2510
                /* check for POW type */
 
2511
                result = brasero_mmc2_get_configuration_feature (handle,
 
2512
                                                                 BRASERO_SCSI_FEAT_BDR_POW,
 
2513
                                                                 &hdr,
 
2514
                                                                 &size,
 
2515
                                                                 code);
 
2516
                if (result == BRASERO_SCSI_OK) {
 
2517
                        if (hdr->desc->current) {
 
2518
                                BRASERO_MEDIA_LOG ("POW formatted medium detected");
 
2519
                                priv->info |= BRASERO_MEDIUM_POW;
 
2520
                        }
 
2521
 
 
2522
                        g_free (hdr);                   
 
2523
                }
 
2524
                else {
 
2525
                        BraseroScsiFormatCapacitiesHdr *hdr = NULL;
 
2526
 
 
2527
                        /* NOTE: the disc status as far as format is concerned
 
2528
                         * is done later for all rewritable media. */
 
2529
                        /* check for unformatted media (if it's POW or RANDOM
 
2530
                         * there is no need of course) */
 
2531
                        result = brasero_mmc2_read_format_capacities (handle,
 
2532
                                                                      &hdr,
 
2533
                                                                      &size,
 
2534
                                                                      NULL);
 
2535
                        if (result == BRASERO_SCSI_OK) {
 
2536
                                BraseroScsiMaxCapacityDesc *current;
 
2537
 
 
2538
                                current = hdr->max_caps;
 
2539
                                if (!(current->type & BRASERO_SCSI_DESC_FORMATTED)) {
 
2540
                                        BRASERO_MEDIA_LOG ("Unformatted BD-R");
 
2541
                                        priv->info |= BRASERO_MEDIUM_UNFORMATTED;
 
2542
                                }
 
2543
 
 
2544
                                g_free (hdr);
 
2545
                        }
 
2546
                }               
 
2547
        }
 
2548
 
 
2549
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BD)) {
 
2550
                /* FIXME: check for dual layer BD */
 
2551
        }
 
2552
 
 
2553
        return BRASERO_BURN_OK;
 
2554
}
 
2555
 
 
2556
static BraseroBurnResult
 
2557
brasero_medium_get_css_feature (BraseroMedium *self,
 
2558
                                BraseroDeviceHandle *handle,
 
2559
                                BraseroScsiErrCode *code)
 
2560
{
 
2561
        BraseroScsiGetConfigHdr *hdr = NULL;
 
2562
        BraseroMediumPrivate *priv;
 
2563
        BraseroScsiResult result;
 
2564
        int size;
 
2565
 
 
2566
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2567
 
 
2568
        BRASERO_MEDIA_LOG ("Testing for Css encrypted media");
 
2569
        result = brasero_mmc2_get_configuration_feature (handle,
 
2570
                                                         BRASERO_SCSI_FEAT_DVD_CSS,
 
2571
                                                         &hdr,
 
2572
                                                         &size,
 
2573
                                                         code);
 
2574
        if (result != BRASERO_SCSI_OK) {
 
2575
                BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
 
2576
                return BRASERO_BURN_ERR;
 
2577
        }
 
2578
 
 
2579
        if (hdr->desc->add_len < sizeof (BraseroScsiDVDCssDesc)) {
 
2580
                g_free (hdr);
 
2581
                return BRASERO_BURN_OK;
 
2582
        }
 
2583
 
 
2584
        /* here we just need to see if this feature is current or not */
 
2585
        if (hdr->desc->current) {
 
2586
                priv->info |= BRASERO_MEDIUM_PROTECTED;
 
2587
                BRASERO_MEDIA_LOG ("media is Css protected");
 
2588
        }
 
2589
 
 
2590
        g_free (hdr);
 
2591
        return BRASERO_BURN_OK;
 
2592
}
 
2593
 
 
2594
static gboolean
 
2595
brasero_medium_get_CD_TEXT (BraseroMedium *medium,
 
2596
                            int type,
 
2597
                            int track_num,
 
2598
                            guint charset_CD_TEXT,
 
2599
                            gboolean double_byte,
 
2600
                            const char *string)
 
2601
{
 
2602
        char *utf8_string;
 
2603
        BraseroMediumPrivate *priv;
 
2604
        const gchar *charset = NULL;
 
2605
 
 
2606
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
2607
 
 
2608
        /* For the moment we're only interested in medium title but that could
 
2609
         * be extented to all tracks information. */
 
2610
        switch (type) {
 
2611
        case BRASERO_SCSI_CD_TEXT_ALBUM_TITLE:
 
2612
                if (track_num)
 
2613
                        return FALSE;
 
2614
 
 
2615
                break;
 
2616
 
 
2617
        case BRASERO_SCSI_CD_TEXT_PERFORMER_NAME:
 
2618
        case BRASERO_SCSI_CD_TEXT_SONGWRITER_NAME:
 
2619
        case BRASERO_SCSI_CD_TEXT_COMPOSER_NAME:
 
2620
        case BRASERO_SCSI_CD_TEXT_ARRANGER_NAME:
 
2621
        case BRASERO_SCSI_CD_TEXT_ARTIST_NAME:
 
2622
        case BRASERO_SCSI_CD_TEXT_DISC_ID_INFO:
 
2623
        case BRASERO_SCSI_CD_TEXT_GENRE_ID_INFO:
 
2624
        case BRASERO_SCSI_CD_TEXT_UPC_EAN_ISRC:
 
2625
        default:
 
2626
                return FALSE;
 
2627
        }
 
2628
 
 
2629
        g_get_charset (&charset);
 
2630
 
 
2631
        /* It's ASCII so convert to locale */
 
2632
        switch (charset_CD_TEXT) {
 
2633
        case BRASERO_CD_TEXT_8859_1:
 
2634
                utf8_string = g_convert_with_fallback (string,
 
2635
                                                       -1,
 
2636
                                                       charset,
 
2637
                                                       "ISO-8859-1",
 
2638
                                                       "_",
 
2639
                                                       NULL,
 
2640
                                                       NULL,
 
2641
                                                       NULL);
 
2642
                break;
 
2643
        case BRASERO_CD_TEXT_KANJI:
 
2644
                utf8_string = g_convert_with_fallback (string,
 
2645
                                                       -1,
 
2646
                                                       charset,
 
2647
                                                       "EUC-JP",
 
2648
                                                       "_",
 
2649
                                                       NULL,
 
2650
                                                       NULL,
 
2651
                                                       NULL);
 
2652
                break;
 
2653
        case BRASERO_CD_TEXT_KOREAN:
 
2654
                utf8_string = g_convert_with_fallback (string,
 
2655
                                                       -1,
 
2656
                                                       charset,
 
2657
                                                       "EUC-KR",
 
2658
                                                       "_",
 
2659
                                                       NULL,
 
2660
                                                       NULL,
 
2661
                                                       NULL);
 
2662
                break;
 
2663
        case BRASERO_CD_TEXT_CHINESE:
 
2664
                utf8_string = g_convert_with_fallback (string,
 
2665
                                                       -1,
 
2666
                                                       charset,
 
2667
                                                       "GB2312",
 
2668
                                                       "_",
 
2669
                                                       NULL,
 
2670
                                                       NULL,
 
2671
                                                       NULL);
 
2672
                break;
 
2673
        default:
 
2674
        case BRASERO_CD_TEXT_ASCII:
 
2675
                utf8_string = g_convert_with_fallback (string,
 
2676
                                                       -1,
 
2677
                                                       charset,
 
2678
                                                       "ASCII",
 
2679
                                                       "_",
 
2680
                                                       NULL,
 
2681
                                                       NULL,
 
2682
                                                       NULL);
 
2683
        }
 
2684
 
 
2685
 
 
2686
        if (priv->CD_TEXT_title)
 
2687
                g_free (priv->CD_TEXT_title);
 
2688
 
 
2689
        if (!utf8_string) {
 
2690
                BRASERO_MEDIA_LOG ("Charset convertion failed");
 
2691
                priv->CD_TEXT_title = g_strdup (string);
 
2692
        }
 
2693
        else
 
2694
                priv->CD_TEXT_title = utf8_string;
 
2695
 
 
2696
        BRASERO_MEDIA_LOG ("CD-TEXT title %s", priv->CD_TEXT_title);
 
2697
        return TRUE;
 
2698
}
 
2699
 
 
2700
static int
 
2701
_next_CD_TEXT_pack (BraseroScsiCDTextData *cd_text,
 
2702
                    int current,
 
2703
                    int max)
 
2704
{
 
2705
        current ++;
 
2706
        if (current >= max)
 
2707
                return -1;
 
2708
 
 
2709
        /* Skip all packs we're not interested or are not valid */
 
2710
        while (cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_ALBUM_TITLE &&
 
2711
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_PERFORMER_NAME &&
 
2712
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_SONGWRITER_NAME &&
 
2713
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_COMPOSER_NAME &&
 
2714
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_ARRANGER_NAME &&
 
2715
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_ARTIST_NAME &&
 
2716
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_DISC_ID_INFO &&
 
2717
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_GENRE_ID_INFO &&
 
2718
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_UPC_EAN_ISRC &&
 
2719
               cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_BLOCK_SIZE) {
 
2720
                current ++;
 
2721
                if (current > max)
 
2722
                        return -1;
 
2723
        }
 
2724
 
 
2725
        return current;
 
2726
}
 
2727
 
 
2728
static gboolean
 
2729
brasero_medium_read_CD_TEXT_block_info (BraseroScsiCDTextData *cd_text,
 
2730
                                        int current,
 
2731
                                        int max,
 
2732
                                        gchar *buffer)
 
2733
{
 
2734
        while ((current = _next_CD_TEXT_pack (cd_text, current, max)) != -1) {
 
2735
                off_t offset = 0;
 
2736
 
 
2737
                if (cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_BLOCK_SIZE)
 
2738
                        continue;
 
2739
 
 
2740
                do {
 
2741
                        memcpy (buffer + offset,
 
2742
                                cd_text->pack [current].text,
 
2743
                                sizeof (cd_text->pack [current].text));
 
2744
 
 
2745
                        offset += sizeof (cd_text->pack [current].text);
 
2746
                        current = _next_CD_TEXT_pack (cd_text, current, max);
 
2747
                } while (current != -1 && cd_text->pack [current].type == BRASERO_SCSI_CD_TEXT_BLOCK_SIZE);
 
2748
 
 
2749
                return TRUE;
 
2750
        }
 
2751
 
 
2752
        return FALSE;
 
2753
}
 
2754
 
 
2755
static void
 
2756
brasero_medium_read_CD_TEXT (BraseroMedium *self,
 
2757
                             BraseroDeviceHandle *handle,
 
2758
                             BraseroScsiErrCode *code)
 
2759
{
 
2760
        int off;
 
2761
        gint charset;
 
2762
        int track_num;
 
2763
        int num, size, i;
 
2764
        char buffer [256]; /* mmc specs advise no more than 160 */
 
2765
        gboolean find_block_info;
 
2766
        BraseroMediumPrivate *priv;
 
2767
        BraseroScsiCDTextData *cd_text;
 
2768
 
 
2769
        BRASERO_MEDIA_LOG ("Getting CD-TEXT");
 
2770
        if (brasero_mmc3_read_cd_text (handle, &cd_text, &size, code) != BRASERO_SCSI_OK) {
 
2771
                BRASERO_MEDIA_LOG ("GET CD-TEXT failed");
 
2772
                return;
 
2773
        }
 
2774
 
 
2775
        /* Get the number of CD-Text Data Packs */
 
2776
        num = (BRASERO_GET_16 (cd_text->hdr->len) -
 
2777
              (sizeof (BraseroScsiTocPmaAtipHdr) - sizeof (cd_text->hdr->len)))  /
 
2778
               sizeof (BraseroScsiCDTextPackData);
 
2779
 
 
2780
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2781
 
 
2782
        off = 0;
 
2783
        track_num = 0;
 
2784
        charset = BRASERO_CD_TEXT_ASCII;
 
2785
 
 
2786
        i = -1;
 
2787
        find_block_info = TRUE;
 
2788
        while ((i = _next_CD_TEXT_pack (cd_text, i, num)) != -1) {
 
2789
                int j;
 
2790
                gboolean is_double_byte;
 
2791
 
 
2792
                /* skip these until the start of another language block or the end */
 
2793
                if (cd_text->pack [i].type == BRASERO_SCSI_CD_TEXT_BLOCK_SIZE) {
 
2794
                        find_block_info = TRUE;
 
2795
                        continue;
 
2796
                }
 
2797
 
 
2798
                if (find_block_info) {
 
2799
                        find_block_info = FALSE;
 
2800
 
 
2801
                        /* This pack is important since it holds the charset. */
 
2802
                        /* NOTE: it's always the last in a block (max 255
 
2803
                         * CD-TEXT pack data). So find it first. */
 
2804
                        if (brasero_medium_read_CD_TEXT_block_info (cd_text, i, num, buffer)) {
 
2805
                                BraseroScsiCDTextPackCharset *pack;
 
2806
 
 
2807
                                pack = (BraseroScsiCDTextPackCharset *) buffer;
 
2808
                                charset = pack->charset;
 
2809
 
 
2810
                                BRASERO_MEDIA_LOG ("Found language pack. Charset = %d. Start %d. End %d",
 
2811
                                                  charset, pack->first_track, pack->last_track);
 
2812
                        }
 
2813
                }
 
2814
 
 
2815
                track_num = cd_text->pack [i].track_num;
 
2816
                is_double_byte = cd_text->pack [i].double_byte;
 
2817
 
 
2818
                for (j = 0; j < sizeof (cd_text->pack [i].text); j++) {
 
2819
                        if (!off
 
2820
                        &&   cd_text->pack [i].text [j] == '\t'
 
2821
                        && (!is_double_byte 
 
2822
                        || (j+1 < sizeof (cd_text->pack [i].text) && cd_text->pack [i].text [j + 1] == '\t'))) {
 
2823
                                /* Specs say that tab character means that's the
 
2824
                                 * same string as before. So if buffer is not
 
2825
                                 * empty send the same string. */
 
2826
                                if (buffer [0] != '\0')
 
2827
                                        brasero_medium_get_CD_TEXT (self,
 
2828
                                                                    cd_text->pack [i].type,
 
2829
                                                                    track_num,
 
2830
                                                                    charset,
 
2831
                                                                    cd_text->pack [i].double_byte,
 
2832
                                                                    buffer);
 
2833
                                track_num ++;
 
2834
                                continue;
 
2835
                        }
 
2836
 
 
2837
                        buffer [off] = cd_text->pack [i].text [j];
 
2838
                        off++;
 
2839
 
 
2840
                        if (cd_text->pack [i].text [j] == '\0'
 
2841
                        && (!is_double_byte 
 
2842
                        || (j+1 < sizeof (cd_text->pack [i].text) && cd_text->pack [i].text [j + 1] == '\0'))) {
 
2843
                                /* Make sure we actually wrote something to the
 
2844
                                 * buffer and that it's not empty. */
 
2845
                                if (buffer [0] != '\0')
 
2846
                                        brasero_medium_get_CD_TEXT (self,
 
2847
                                                                    cd_text->pack [i].type,
 
2848
                                                                    track_num,
 
2849
                                                                    charset,
 
2850
                                                                    cd_text->pack [i].double_byte,
 
2851
                                                                    buffer);
 
2852
 
 
2853
                                /* End of encapsulated Text Pack. Skip to the next. */
 
2854
                                track_num ++;
 
2855
                                off = 0;
 
2856
                        }
 
2857
                }
 
2858
        }
 
2859
 
 
2860
        g_free (cd_text);
 
2861
}
 
2862
 
 
2863
static void
 
2864
brasero_medium_init_real (BraseroMedium *object,
 
2865
                          BraseroDeviceHandle *handle)
 
2866
{
 
2867
        guint i;
 
2868
        gchar *name;
 
2869
        BraseroBurnResult result;
 
2870
        BraseroMediumPrivate *priv;
 
2871
        BraseroScsiErrCode code = 0;
 
2872
        gchar buffer [256] = { 0, };
 
2873
 
 
2874
        priv = BRASERO_MEDIUM_PRIVATE (object);
 
2875
 
 
2876
        name = brasero_drive_get_display_name (priv->drive);
 
2877
        BRASERO_MEDIA_LOG ("Initializing information for medium in %s", name);
 
2878
        g_free (name);
 
2879
 
 
2880
        if (priv->probe_cancelled)
 
2881
                return;
 
2882
 
 
2883
        result = brasero_medium_get_medium_type (object, handle, &code);
 
2884
        if (result != BRASERO_BURN_OK)
 
2885
                return;
 
2886
 
 
2887
        if (priv->probe_cancelled)
 
2888
                return;
 
2889
 
 
2890
        result = brasero_medium_get_speed (object, handle, &code);
 
2891
        if (result != BRASERO_BURN_OK)
 
2892
                return;
 
2893
 
 
2894
        if (priv->probe_cancelled)
 
2895
                return;
 
2896
 
 
2897
        brasero_medium_get_capacity_by_type (object, handle, &code);
 
2898
        if (priv->probe_cancelled)
 
2899
                return;
 
2900
 
 
2901
        result = brasero_medium_get_contents (object, handle, &code);
 
2902
        if (result != BRASERO_BURN_OK)
 
2903
                return;
 
2904
 
 
2905
        if (priv->probe_cancelled)
 
2906
                return;
 
2907
 
 
2908
        /* assume that css feature is only for DVD-ROM which might be wrong but
 
2909
         * some drives wrongly reports that css is enabled for blank DVD+R/W */
 
2910
        if (BRASERO_MEDIUM_IS (priv->info, (BRASERO_MEDIUM_DVD|BRASERO_MEDIUM_ROM)))
 
2911
                brasero_medium_get_css_feature (object, handle, &code);
 
2912
 
 
2913
        if (priv->probe_cancelled)
 
2914
                return;
 
2915
 
 
2916
        brasero_medium_init_caps (object, handle, &code);
 
2917
        if (priv->probe_cancelled)
 
2918
                return;
 
2919
 
 
2920
        /* read CD-TEXT title */
 
2921
        if (priv->info & BRASERO_MEDIUM_HAS_AUDIO)
 
2922
                brasero_medium_read_CD_TEXT (object, handle, &code);
 
2923
 
 
2924
        if (priv->probe_cancelled)
 
2925
                return;
 
2926
 
 
2927
        brasero_media_to_string (priv->info, buffer);
 
2928
        BRASERO_MEDIA_LOG ("media is %s", buffer);
 
2929
 
 
2930
        if (!priv->wr_speeds)
 
2931
                return;
 
2932
 
 
2933
        /* sort write speeds */
 
2934
        for (i = 0; priv->wr_speeds [i] != 0; i ++) {
 
2935
                guint j;
 
2936
 
 
2937
                for (j = 0; priv->wr_speeds [j] != 0; j ++) {
 
2938
                        if (priv->wr_speeds [i] > priv->wr_speeds [j]) {
 
2939
                                gint64 tmp;
 
2940
 
 
2941
                                tmp = priv->wr_speeds [i];
 
2942
                                priv->wr_speeds [i] = priv->wr_speeds [j];
 
2943
                                priv->wr_speeds [j] = tmp;
 
2944
                        }
 
2945
                }
 
2946
        }
 
2947
}
 
2948
 
 
2949
static gboolean
 
2950
brasero_medium_probed (gpointer data)
 
2951
{
 
2952
        BraseroMediumPrivate *priv;
 
2953
 
 
2954
        priv = BRASERO_MEDIUM_PRIVATE (data);
 
2955
 
 
2956
        /* This signal must be emitted in the main thread */
 
2957
        GDK_THREADS_ENTER ();
 
2958
        g_signal_emit (data,
 
2959
                       medium_signals [PROBED],
 
2960
                       0);
 
2961
        GDK_THREADS_LEAVE ();
 
2962
 
 
2963
        priv->probe_id = 0;
 
2964
        return FALSE;
 
2965
}
 
2966
 
 
2967
static gpointer
 
2968
brasero_medium_probe_thread (gpointer self)
 
2969
{
 
2970
        gint counter = 0;
 
2971
        const gchar *path;
 
2972
        BraseroScsiErrCode code;
 
2973
        BraseroMediumPrivate *priv;
 
2974
        BraseroDeviceHandle *handle;
 
2975
 
 
2976
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
2977
        path = brasero_drive_get_device (priv->drive);
 
2978
 
 
2979
        priv->info = BRASERO_MEDIUM_BUSY;
 
2980
 
 
2981
        /* the drive might be busy (a burning is going on) so we don't block
 
2982
         * but we re-try to open it every second */
 
2983
        BRASERO_MEDIA_LOG ("Trying to open device %s", path);
 
2984
 
 
2985
        handle = brasero_device_handle_open (path, FALSE, &code);
 
2986
        while (!handle && counter <= BRASERO_MEDIUM_OPEN_ATTEMPTS) {
 
2987
                sleep (1);
 
2988
 
 
2989
                if (priv->probe_cancelled) {
 
2990
                        priv->probe = NULL;
 
2991
                        return NULL;
 
2992
                }
 
2993
 
 
2994
                counter ++;
 
2995
                handle = brasero_device_handle_open (path, FALSE, &code);
 
2996
        }
 
2997
 
 
2998
        if (priv->probe_cancelled) {
 
2999
                priv->probe = NULL;
 
3000
                return NULL;
 
3001
        }
 
3002
 
 
3003
        if (handle) {
 
3004
                BRASERO_MEDIA_LOG ("Open () succeeded");
 
3005
 
 
3006
                /* NOTE: if we wanted to know the status we'd need to read the 
 
3007
                 * error code variable which is currently NULL */
 
3008
                while (brasero_spc1_test_unit_ready (handle, NULL) != BRASERO_SCSI_OK) {
 
3009
                        sleep (1);
 
3010
 
 
3011
                        if (priv->probe_cancelled) {
 
3012
                                priv->probe = NULL;
 
3013
                                brasero_device_handle_close (handle);
 
3014
                                BRASERO_MEDIA_LOG ("Device probing cancelled");
 
3015
                                return NULL;
 
3016
                        }
 
3017
                }
 
3018
 
 
3019
                BRASERO_MEDIA_LOG ("Device ready");
 
3020
 
 
3021
                brasero_medium_init_real (BRASERO_MEDIUM (self), handle);
 
3022
                brasero_device_handle_close (handle);
 
3023
        }
 
3024
        else
 
3025
                BRASERO_MEDIA_LOG ("Open () failed: medium busy");
 
3026
 
 
3027
        priv->probe_id = g_idle_add (brasero_medium_probed, self);
 
3028
        priv->probe = NULL;
 
3029
        return NULL;
 
3030
}
 
3031
 
 
3032
static void
 
3033
brasero_medium_probe (BraseroMedium *self)
 
3034
{
 
3035
        BraseroMediumPrivate *priv;
 
3036
 
 
3037
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
3038
 
 
3039
        /* NOTE: why a thread? Because in case of a damaged medium, brasero can
 
3040
         * block on some functions until timeout and if we do this in the main
 
3041
         * thread then our whole UI blocks. This medium won't be exported by the
 
3042
         * BraseroDrive that exported until it returns PROBED signal.
 
3043
         * One (good) side effect is that it also improves start time. */
 
3044
        priv->probe = g_thread_create (brasero_medium_probe_thread,
 
3045
                                       self,
 
3046
                                       TRUE,
 
3047
                                       NULL);
 
3048
}
 
3049
 
 
3050
static void
 
3051
brasero_medium_init_file (BraseroMedium *self)
 
3052
{
 
3053
        BraseroMediumPrivate *priv;
 
3054
 
 
3055
        priv = BRASERO_MEDIUM_PRIVATE (self);
 
3056
 
 
3057
        priv->info = BRASERO_MEDIUM_FILE;
 
3058
        priv->type = types [0];
 
3059
}
 
3060
 
 
3061
static void
 
3062
brasero_medium_init (BraseroMedium *object)
 
3063
{
 
3064
        BraseroMediumPrivate *priv;
 
3065
 
 
3066
        priv = BRASERO_MEDIUM_PRIVATE (object);
 
3067
        priv->next_wr_add = -1;
 
3068
 
 
3069
        /* we can't do anything here since properties haven't been set yet */
 
3070
}
 
3071
 
 
3072
static void
 
3073
brasero_medium_finalize (GObject *object)
 
3074
{
 
3075
        BraseroMediumPrivate *priv;
 
3076
 
 
3077
        priv = BRASERO_MEDIUM_PRIVATE (object);
 
3078
 
 
3079
        if (priv->probe) {
 
3080
                priv->probe_cancelled = TRUE;
 
3081
                g_thread_join (priv->probe);
 
3082
                priv->probe = 0;
 
3083
        }
 
3084
 
 
3085
        if (priv->probe_id) {
 
3086
                g_source_remove (priv->probe_id);
 
3087
                priv->probe_id = 0;
 
3088
        }
 
3089
 
 
3090
        if (priv->id) {
 
3091
                g_free (priv->id);
 
3092
                priv->id = NULL;
 
3093
        }
 
3094
 
 
3095
        if (priv->CD_TEXT_title) {
 
3096
                g_free (priv->CD_TEXT_title);
 
3097
                priv->CD_TEXT_title = NULL;
 
3098
        }
 
3099
 
 
3100
        g_free (priv->rd_speeds);
 
3101
        priv->rd_speeds = NULL;
 
3102
 
 
3103
        g_free (priv->wr_speeds);
 
3104
        priv->wr_speeds = NULL;
 
3105
 
 
3106
        g_slist_foreach (priv->tracks, (GFunc) g_free, NULL);
 
3107
        g_slist_free (priv->tracks);
 
3108
        priv->tracks = NULL;
 
3109
 
 
3110
        priv->drive = NULL;
 
3111
 
 
3112
        G_OBJECT_CLASS (parent_class)->finalize (object);
 
3113
}
 
3114
 
 
3115
static void
 
3116
brasero_medium_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 
3117
{
 
3118
        BraseroMediumPrivate *priv;
 
3119
 
 
3120
        g_return_if_fail (BRASERO_IS_MEDIUM (object));
 
3121
 
 
3122
        priv = BRASERO_MEDIUM_PRIVATE (object);
 
3123
 
 
3124
        switch (prop_id)
 
3125
        {
 
3126
        case PROP_DRIVE:
 
3127
                /* we don't ref the drive here as it would create a circular
 
3128
                 * dependency where the drive would hold a reference on the 
 
3129
                 * medium and the medium on the drive */
 
3130
                priv->drive = g_value_get_object (value);
 
3131
 
 
3132
                if (brasero_drive_is_fake (priv->drive)) {
 
3133
                        brasero_medium_init_file (BRASERO_MEDIUM (object));
 
3134
                        break;
 
3135
                }
 
3136
 
 
3137
                brasero_medium_probe (BRASERO_MEDIUM (object));
 
3138
                break;
 
3139
        default:
 
3140
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3141
                break;
 
3142
        }
 
3143
}
 
3144
 
 
3145
static void
 
3146
brasero_medium_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 
3147
{
 
3148
        BraseroMediumPrivate *priv;
 
3149
 
 
3150
        g_return_if_fail (BRASERO_IS_MEDIUM (object));
 
3151
 
 
3152
        priv = BRASERO_MEDIUM_PRIVATE (object);
 
3153
 
 
3154
        switch (prop_id)
 
3155
        {
 
3156
        case PROP_DRIVE:
 
3157
                g_value_set_object (value, priv->drive);
 
3158
                break;
 
3159
        default:
 
3160
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3161
                break;
 
3162
        }
 
3163
}
 
3164
 
 
3165
static void
 
3166
brasero_medium_class_init (BraseroMediumClass *klass)
 
3167
{
 
3168
        GObjectClass* object_class = G_OBJECT_CLASS (klass);
 
3169
        parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
 
3170
 
 
3171
        g_type_class_add_private (klass, sizeof (BraseroMediumPrivate));
 
3172
 
 
3173
        object_class->finalize = brasero_medium_finalize;
 
3174
        object_class->set_property = brasero_medium_set_property;
 
3175
        object_class->get_property = brasero_medium_get_property;
 
3176
 
 
3177
        /**
 
3178
        * BraseroMedium::probed:
 
3179
        * @medium: the object which received the signal
 
3180
        *
 
3181
        * This signal gets emitted when the medium inside the drive has been
 
3182
        * fully probed. This is mostly for internal use.
 
3183
        *
 
3184
        */
 
3185
        medium_signals[PROBED] =
 
3186
                g_signal_new ("probed",
 
3187
                              G_OBJECT_CLASS_TYPE (klass),
 
3188
                              G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
 
3189
                              0,
 
3190
                              NULL, NULL,
 
3191
                              g_cclosure_marshal_VOID__VOID,
 
3192
                              G_TYPE_NONE, 0,
 
3193
                              G_TYPE_NONE);
 
3194
 
 
3195
        g_object_class_install_property (object_class,
 
3196
                                         PROP_DRIVE,
 
3197
                                         g_param_spec_object ("drive",
 
3198
                                                              "Drive",
 
3199
                                                              "Drive in which medium is inserted",
 
3200
                                                              BRASERO_TYPE_DRIVE,
 
3201
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
3202
}
 
3203
 
 
3204
/**
 
3205
 * brasero_medium_can_be_written:
 
3206
 * @medium: #BraseroMedium
 
3207
 *
 
3208
 * Gets whether the medium can be written. It also checks that the medium can
 
3209
 * write the medium.
 
3210
 *
 
3211
 * Return value: a #gboolean. TRUE if the medium can be rewritten, FALSE otherwise.
 
3212
 *
 
3213
 **/
 
3214
gboolean
 
3215
brasero_medium_can_be_written (BraseroMedium *medium)
 
3216
{
 
3217
        BraseroMediumPrivate *priv;
 
3218
        BraseroDriveCaps caps;
 
3219
 
 
3220
        g_return_val_if_fail (medium != NULL, FALSE);
 
3221
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
3222
 
 
3223
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
3224
 
 
3225
        if (!(priv->info & BRASERO_MEDIUM_REWRITABLE)
 
3226
        &&   (priv->info & BRASERO_MEDIUM_CLOSED))
 
3227
                return FALSE;
 
3228
 
 
3229
        if (priv->info & BRASERO_MEDIUM_FILE)
 
3230
                return FALSE;
 
3231
 
 
3232
        caps = brasero_drive_get_caps (priv->drive);
 
3233
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDR))
 
3234
                return (caps & BRASERO_DRIVE_CAPS_CDR) != 0;
 
3235
 
 
3236
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR))
 
3237
                return (caps & BRASERO_DRIVE_CAPS_DVDR) != 0;
 
3238
 
 
3239
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR_PLUS))
 
3240
                return (caps & BRASERO_DRIVE_CAPS_DVDR_PLUS) != 0;
 
3241
 
 
3242
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDRW))
 
3243
                return (caps & BRASERO_DRIVE_CAPS_CDRW) != 0;
 
3244
 
 
3245
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW))
 
3246
                return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
 
3247
 
 
3248
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
 
3249
                return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
 
3250
 
 
3251
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS))
 
3252
                return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS) != 0;
 
3253
 
 
3254
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR_PLUS_DL))
 
3255
                return (caps & BRASERO_DRIVE_CAPS_DVDR_PLUS_DL) != 0;
 
3256
 
 
3257
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS_DL))
 
3258
                return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL) != 0;
 
3259
 
 
3260
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVD_RAM))
 
3261
                return (caps & BRASERO_DRIVE_CAPS_DVDRAM) != 0;
 
3262
 
 
3263
        /* All types of BD-R */
 
3264
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BD|BRASERO_MEDIUM_WRITABLE))
 
3265
                return (caps & BRASERO_DRIVE_CAPS_BDR) != 0;
 
3266
 
 
3267
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE))
 
3268
                return (caps & BRASERO_DRIVE_CAPS_BDRW) != 0;
 
3269
 
 
3270
        return FALSE;
 
3271
}
 
3272
 
 
3273
/**
 
3274
 * brasero_medium_can_be_rewritten:
 
3275
 * @medium: #BraseroMedium
 
3276
 *
 
3277
 * Gets whether the medium can be rewritten. Note: it also checks that the drive
 
3278
 * can rewrite the medium type.
 
3279
 *
 
3280
 * Return value: a #gboolean. TRUE if the medium can be rewritten, FALSE otherwise.
 
3281
 *
 
3282
 **/
 
3283
gboolean
 
3284
brasero_medium_can_be_rewritten (BraseroMedium *medium)
 
3285
{
 
3286
        BraseroMediumPrivate *priv;
 
3287
        BraseroDriveCaps caps;
 
3288
 
 
3289
        g_return_val_if_fail (medium != NULL, FALSE);
 
3290
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
 
3291
 
 
3292
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
3293
 
 
3294
        if (!(priv->info & BRASERO_MEDIUM_REWRITABLE)
 
3295
        ||   (priv->info & BRASERO_MEDIUM_FILE))
 
3296
                return FALSE;
 
3297
 
 
3298
        caps = brasero_drive_get_caps (priv->drive);
 
3299
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDRW))
 
3300
                return (caps & BRASERO_DRIVE_CAPS_CDRW) != 0;
 
3301
 
 
3302
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW))
 
3303
                return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
 
3304
 
 
3305
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
 
3306
                return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
 
3307
 
 
3308
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS))
 
3309
                return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS) != 0;
 
3310
 
 
3311
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS_DL))
 
3312
                return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL) != 0;
 
3313
 
 
3314
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVD_RAM))
 
3315
                return (caps & BRASERO_DRIVE_CAPS_DVDRAM) != 0;
 
3316
 
 
3317
        if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE))
 
3318
                return (caps & BRASERO_DRIVE_CAPS_BDRW) != 0;
 
3319
 
 
3320
        return FALSE;
 
3321
}
 
3322
 
 
3323
/**
 
3324
 * brasero_medium_get_drive:
 
3325
 * @medium: #BraseroMedium
 
3326
 *
 
3327
 * Gets the #BraseroDrive in which the medium is inserted.
 
3328
 *
 
3329
 * Return value: a #BraseroDrive. No need to unref after use.
 
3330
 *
 
3331
 **/
 
3332
BraseroDrive *
 
3333
brasero_medium_get_drive (BraseroMedium *medium)
 
3334
{
 
3335
        BraseroMediumPrivate *priv;
 
3336
 
 
3337
        if (!medium)
 
3338
                return NULL;
 
3339
 
 
3340
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
 
3341
 
 
3342
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
3343
        return priv->drive;
 
3344
}
 
3345
 
 
3346
/**
 
3347
 * brasero_medium_get_CD_TEXT_title:
 
3348
 * @medium: #BraseroMedium
 
3349
 *
 
3350
 * Gets the CD-TEXT title for @Medium.
 
3351
 *
 
3352
 * Return value: a #gchar *.
 
3353
 *
 
3354
 **/
 
3355
const gchar *
 
3356
brasero_medium_get_CD_TEXT_title (BraseroMedium *medium)
 
3357
{
 
3358
        BraseroMediumPrivate *priv;
 
3359
 
 
3360
        g_return_val_if_fail (medium != NULL, NULL);
 
3361
        g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
 
3362
 
 
3363
        priv = BRASERO_MEDIUM_PRIVATE (medium);
 
3364
        return priv->CD_TEXT_title;
 
3365
 
 
3366
}
 
3367
 
 
3368
GType
 
3369
brasero_medium_get_type (void)
 
3370
{
 
3371
        static GType our_type = 0;
 
3372
 
 
3373
        if (our_type == 0)
 
3374
        {
 
3375
                static const GTypeInfo our_info =
 
3376
                {
 
3377
                        sizeof (BraseroMediumClass), /* class_size */
 
3378
                        (GBaseInitFunc) NULL, /* base_init */
 
3379
                        (GBaseFinalizeFunc) NULL, /* base_finalize */
 
3380
                        (GClassInitFunc) brasero_medium_class_init, /* class_init */
 
3381
                        (GClassFinalizeFunc) NULL, /* class_finalize */
 
3382
                        NULL /* class_data */,
 
3383
                        sizeof (BraseroMedium), /* instance_size */
 
3384
                        0, /* n_preallocs */
 
3385
                        (GInstanceInitFunc) brasero_medium_init, /* instance_init */
 
3386
                        NULL /* value_table */
 
3387
                };
 
3388
 
 
3389
                our_type = g_type_register_static (G_TYPE_OBJECT, "BraseroMedium",
 
3390
                                                   &our_info, 0);
 
3391
        }
 
3392
 
 
3393
        return our_type;
 
3394
}