1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
6
* Libbrasero-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.
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.
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.
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.
35
#include <sys/types.h>
42
#include <glib/gi18n-lib.h>
45
#include "burn-basics.h"
47
#include "brasero-media-private.h"
49
#include "brasero-medium.h"
50
#include "brasero-drive.h"
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"
66
const gchar *types [] = { N_("File"),
75
N_("DVD+R dual layer"),
76
N_("DVD+RW dual layer"),
77
N_("DVD-R dual layer"),
80
N_("Writable Blu-ray disc"),
81
N_("Rewritable Blu-ray disc"),
85
BRASERO_MEDIUM_CAP_INVALID = 0,
86
BRASERO_MEDIUM_CAP_TRUE = 1,
87
BRASERO_MEDIUM_CAP_FALSE = 2
88
} BraseroMediumCapState;
90
typedef struct _BraseroMediumPrivate BraseroMediumPrivate;
91
struct _BraseroMediumPrivate
111
guint first_open_track;
117
gchar *CD_TEXT_title;
119
/* Do we really need both? */
124
guint probe_cancelled:1;
127
#define BRASERO_MEDIUM_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM, BraseroMediumPrivate))
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
136
#define BUSY_RETRY_TIME 1000
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;
149
typedef struct _BraseroMediumTrack BraseroMediumTrack;
151
struct _BraseroMediumTrack {
153
BraseroMediumTrackType type;
168
static gulong medium_signals [LAST_SIGNAL] = {0, };
170
#define BRASERO_MEDIUM_OPEN_ATTEMPTS 5
172
static GObjectClass* parent_class = NULL;
175
* This one is not supposed to be public API. It's declared in burn-caps.c
179
brasero_medium_supported_flags (BraseroMedium *self,
180
BraseroBurnFlag flags)
182
BraseroMediumPrivate *priv;
184
priv = BRASERO_MEDIUM_PRIVATE (self);
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;
195
else if (flags & BRASERO_BURN_FLAG_DAO) {
196
if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
197
flags &= ~BRASERO_BURN_FLAG_DUMMY;
199
else if (priv->dummy_tao != BRASERO_MEDIUM_CAP_TRUE)
200
flags &= ~BRASERO_BURN_FLAG_DUMMY;
203
flags &= ~BRASERO_BURN_FLAG_BURNPROOF;
209
* This one is not supposed to be public API. It's declared in burn-caps.c
213
brasero_medium_support_flags (BraseroMedium *self,
214
BraseroBurnFlag flags)
216
BraseroMediumPrivate *priv;
218
priv = BRASERO_MEDIUM_PRIVATE (self);
220
if (flags & BRASERO_BURN_FLAG_DUMMY) {
221
/* This is always FALSE */
222
if (priv->info & BRASERO_MEDIUM_PLUS)
225
if (priv->info & BRASERO_MEDIUM_DVD) {
226
if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
229
else if (flags & BRASERO_BURN_FLAG_DAO) {
230
if (priv->dummy_sao != BRASERO_MEDIUM_CAP_TRUE)
233
else if (priv->dummy_tao != BRASERO_MEDIUM_CAP_TRUE)
237
if (flags & BRASERO_BURN_FLAG_BURNPROOF) {
246
* brasero_medium_get_tooltip:
247
* @medium: #BraseroMedium
249
* Returns a tooltip to be displayed in the UI.
250
* It is of the form {content type} {disc type} in {drive name}.
252
* Return value: a #gchar *.
256
brasero_medium_get_tooltip (BraseroMedium *medium)
258
BraseroMediumPrivate *priv;
265
g_return_val_if_fail (medium != NULL, NULL);
266
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
268
priv = BRASERO_MEDIUM_PRIVATE (medium);
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"));
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);
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"),
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"),
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"),
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"),
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"),
323
* brasero_medium_get_type_string:
324
* @medium: #BraseroMedium
326
* Returns the medium type as a string to be displayed in a UI.
328
* Return value: a #gchar *.
332
brasero_medium_get_type_string (BraseroMedium *medium)
334
BraseroMediumPrivate *priv;
336
g_return_val_if_fail (medium != NULL, NULL);
337
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
339
priv = BRASERO_MEDIUM_PRIVATE (medium);
344
* brasero_medium_get_status:
345
* @medium: #BraseroMedium
347
* Gets the medium type and state.
349
* Return value: a #BraseroMedia.
353
brasero_medium_get_status (BraseroMedium *medium)
355
BraseroMediumPrivate *priv;
358
return BRASERO_MEDIUM_NONE;
360
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), BRASERO_MEDIUM_NONE);
362
priv = BRASERO_MEDIUM_PRIVATE (medium);
367
* brasero_medium_get_last_data_track_address:
368
* @medium: #BraseroMedium
369
* @byte: a #gint64 * or NULL
370
* @sector: a #gint64 * or NULL
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.
378
brasero_medium_get_last_data_track_address (BraseroMedium *medium,
383
BraseroMediumPrivate *priv;
384
BraseroMediumTrack *track = NULL;
386
g_return_val_if_fail (medium != NULL, FALSE);
387
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
389
priv = BRASERO_MEDIUM_PRIVATE (medium);
391
for (iter = priv->tracks; iter; iter = iter->next) {
392
BraseroMediumTrack *current;
394
current = iter->data;
395
if (current->type & BRASERO_MEDIUM_TRACK_DATA)
408
*byte = track->start * priv->block_size;
411
*sector = track->start;
417
* brasero_medium_get_last_data_track_space:
418
* @medium: #BraseroMedium
419
* @size: a #gint64 * or NULL
420
* @blocks: a #gint64 * or NULL
422
* Stores in either @size (in bytes) or in @blocks (in blocks) the space used by
423
* the last track on the medium.
427
brasero_medium_get_last_data_track_space (BraseroMedium *medium,
432
BraseroMediumPrivate *priv;
433
BraseroMediumTrack *track = NULL;
435
g_return_val_if_fail (medium != NULL, FALSE);
436
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
438
priv = BRASERO_MEDIUM_PRIVATE (medium);
440
for (iter = priv->tracks; iter; iter = iter->next) {
441
BraseroMediumTrack *current;
443
current = iter->data;
444
if (current->type & BRASERO_MEDIUM_TRACK_DATA)
457
*size = track->blocks_num * priv->block_size;
459
*blocks = track->blocks_num;
465
* brasero_medium_get_track_num:
466
* @medium: #BraseroMedium
468
* Gets the number of tracks on the medium.
470
* Return value: a #guint.
474
brasero_medium_get_track_num (BraseroMedium *medium)
478
BraseroMediumPrivate *priv;
480
g_return_val_if_fail (medium != NULL, 0);
481
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
483
priv = BRASERO_MEDIUM_PRIVATE (medium);
484
for (iter = priv->tracks; iter; iter = iter->next) {
485
BraseroMediumTrack *current;
487
current = iter->data;
488
if (current->type & BRASERO_MEDIUM_TRACK_LEADOUT)
497
static BraseroMediumTrack *
498
brasero_medium_get_track (BraseroMedium *medium,
503
BraseroMediumPrivate *priv;
505
priv = BRASERO_MEDIUM_PRIVATE (medium);
507
for (iter = priv->tracks; iter; iter = iter->next) {
508
BraseroMediumTrack *current;
510
current = iter->data;
511
if (current->type == BRASERO_MEDIUM_TRACK_LEADOUT)
524
* brasero_medium_get_track_space:
525
* @medium: a #BraseroMedium
527
* @size: a #gint64 * or NULL
528
* @blocks: a #gint64 * or NULL
530
* Stores in either @size (in bytes) or in @blocks (in blocks) the space used
531
* by session @num on the disc.
533
* Return value: a #gboolean. Returns TRUE if information could be retrieved;
534
* FALSE otherwise (usually when track @num doesn't exist).
538
brasero_medium_get_track_space (BraseroMedium *medium,
543
BraseroMediumPrivate *priv;
544
BraseroMediumTrack *track;
546
g_return_val_if_fail (medium != NULL, FALSE);
547
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
549
priv = BRASERO_MEDIUM_PRIVATE (medium);
551
track = brasero_medium_get_track (medium, num);
561
*size = track->blocks_num * priv->block_size;
563
*blocks = track->blocks_num;
569
* brasero_medium_get_track_address:
570
* @medium: a #BraseroMedium
572
* @byte: a #gint64 * or NULL
573
* @sector: a #gint64 * or NULL
575
* Stores in either @byte (in bytes) or in @sector (in blocks) the address at
576
* which the session identified by @num starts.
578
* Return value: a #gboolean. Returns TRUE if information could be retrieved;
579
* FALSE otherwise (usually when track @num doesn't exist).
583
brasero_medium_get_track_address (BraseroMedium *medium,
588
BraseroMediumPrivate *priv;
589
BraseroMediumTrack *track;
591
g_return_val_if_fail (medium != NULL, FALSE);
592
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
594
priv = BRASERO_MEDIUM_PRIVATE (medium);
596
track = brasero_medium_get_track (medium, num);
606
*byte = track->start * priv->block_size;
608
*sector = track->start;
614
* brasero_medium_get_next_writable_address:
615
* @medium: #BraseroMedium
617
* Gets the address (block number) that can be used to write a new session on @medium
619
* Return value: a #gint64.
623
brasero_medium_get_next_writable_address (BraseroMedium *medium)
625
BraseroMediumPrivate *priv;
627
g_return_val_if_fail (medium != NULL, 0);
628
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
630
priv = BRASERO_MEDIUM_PRIVATE (medium);
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;
638
/* These are always writable so give the next address after the
643
first = priv->tracks->data;
645
/* round to the nearest 16th block */
646
return (((first->start + first->blocks_num) + 15) / 16) * 16;
649
return priv->next_wr_add;
653
* brasero_medium_get_max_write_speed:
654
* @medium: #BraseroMedium
656
* Gets the maximum speed that can be used to write to @medium.
657
* Note: the speed are in B/sec.
659
* Return value: a #gint64.
663
brasero_medium_get_max_write_speed (BraseroMedium *medium)
665
BraseroMediumPrivate *priv;
667
g_return_val_if_fail (medium != NULL, 0);
668
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), 0);
670
priv = BRASERO_MEDIUM_PRIVATE (medium);
671
return priv->max_wrt * 1000;
675
* brasero_medium_get_write_speeds:
676
* @medium: #BraseroMedium
678
* Gets an array holding all possible speeds to write to @medium.
679
* Note: the speed are in B/sec.
681
* Return value: a #gint64 *.
685
brasero_medium_get_write_speeds (BraseroMedium *medium)
687
BraseroMediumPrivate *priv;
692
g_return_val_if_fail (medium != NULL, NULL);
693
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
695
priv = BRASERO_MEDIUM_PRIVATE (medium);
697
if (!priv->wr_speeds)
700
while (priv->wr_speeds [max] != 0) max ++;
702
speeds = g_new0 (guint64, max + 1);
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;
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).
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)
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.
736
* brasero_medium_get_data_size:
737
* @medium: #BraseroMedium
738
* @size: a #gint64 * or NULL
739
* @blocks: a #gint64 * or NULL
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.
746
brasero_medium_get_data_size (BraseroMedium *medium,
751
BraseroMediumPrivate *priv;
752
BraseroMediumTrack *track = NULL;
754
g_return_if_fail (medium != NULL);
755
g_return_if_fail (BRASERO_IS_MEDIUM (medium));
757
priv = BRASERO_MEDIUM_PRIVATE (medium);
760
/* that's probably because it wasn't possible to retrieve info */
770
for (iter = priv->tracks; iter; iter = iter->next) {
771
BraseroMediumTrack *tmp;
774
if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT)
781
*size = track ? (track->start + track->blocks_num) * priv->block_size: 0;
784
*blocks = track ? track->start + track->blocks_num: 0;
788
* brasero_medium_get_free_space:
789
* @medium: #BraseroMedium
790
* @size: a #gint64 * or NULL
791
* @blocks: a #gint64 * or NULL
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.
798
brasero_medium_get_free_space (BraseroMedium *medium,
803
BraseroMediumPrivate *priv;
804
BraseroMediumTrack *track = NULL;
806
g_return_if_fail (medium != NULL);
807
g_return_if_fail (BRASERO_IS_MEDIUM (medium));
809
priv = BRASERO_MEDIUM_PRIVATE (medium);
812
/* that's probably because it wasn't possible to retrieve info.
813
* maybe it also happens with unformatted DVD+RW */
815
if (priv->info & BRASERO_MEDIUM_CLOSED) {
824
*size = priv->block_num * priv->block_size;
827
*blocks = priv->block_num;
833
for (iter = priv->tracks; iter; iter = iter->next) {
834
BraseroMediumTrack *tmp;
837
if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT) {
845
/* No leadout was found so the disc is probably closed:
846
* no free space left. */
849
else if (track->blocks_num <= 0)
850
*size = (priv->block_num - track->start) * priv->block_size;
852
*size = track->blocks_num * priv->block_size;
857
/* No leadout was found so the disc is probably closed:
858
* no free space left. */
861
else if (track->blocks_num <= 0)
862
*blocks = priv->block_num - track->blocks_num;
864
*blocks = track->blocks_num;
869
* brasero_medium_get_capacity:
870
* @medium: #BraseroMedium
871
* @size: a #gint64 * or NULL
872
* @blocks: a #gint64 * or NULL
874
* Stores in either @size (in bytes) or @blocks (the number of blocks) the total
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.
881
brasero_medium_get_capacity (BraseroMedium *medium,
885
BraseroMediumPrivate *priv;
887
g_return_if_fail (medium != NULL);
888
g_return_if_fail (BRASERO_IS_MEDIUM (medium));
890
priv = BRASERO_MEDIUM_PRIVATE (medium);
892
if (priv->info & BRASERO_MEDIUM_REWRITABLE) {
894
*size = priv->block_num * priv->block_size;
897
*blocks = priv->block_num;
899
else if (priv->info & BRASERO_MEDIUM_CLOSED)
900
brasero_medium_get_data_size (medium, size, blocks);
902
brasero_medium_get_free_space (medium, size, blocks);
906
* Test presence of simulate burning
909
static BraseroBurnResult
910
brasero_medium_test_simulate_CD_SAO (BraseroMedium *self,
911
BraseroDeviceHandle *handle,
912
BraseroScsiErrCode *code)
914
BraseroScsiGetConfigHdr *hdr = NULL;
915
BraseroScsiCDTAODesc *tao_desc;
916
BraseroScsiFeatureDesc *desc;
917
BraseroMediumPrivate *priv;
918
BraseroScsiResult result;
921
priv = BRASERO_MEDIUM_PRIVATE (self);
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,
930
if (result != BRASERO_SCSI_OK) {
931
BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
932
return BRASERO_BURN_ERR;
937
BRASERO_MEDIA_LOG ("Feature is not current");
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;
943
return BRASERO_BURN_OK;
946
static BraseroBurnResult
947
brasero_medium_test_simulate_CD_TAO (BraseroMedium *self,
948
BraseroDeviceHandle *handle,
949
BraseroScsiErrCode *code)
951
BraseroScsiGetConfigHdr *hdr = NULL;
952
BraseroScsiCDSAODesc *sao_desc;
953
BraseroScsiFeatureDesc *desc;
954
BraseroMediumPrivate *priv;
955
BraseroScsiResult result;
958
priv = BRASERO_MEDIUM_PRIVATE (self);
960
BRASERO_MEDIA_LOG ("Checking simulate (CD SAO)");
961
result = brasero_mmc2_get_configuration_feature (handle,
962
BRASERO_SCSI_FEAT_WRT_SAO_RAW,
966
if (result != BRASERO_SCSI_OK) {
967
BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
968
return BRASERO_BURN_ERR;
973
BRASERO_MEDIA_LOG ("Feature is not current");
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;
979
return BRASERO_BURN_OK;
982
static BraseroBurnResult
983
brasero_medium_test_simulate_DVDRW (BraseroMedium *self,
984
BraseroDeviceHandle *handle,
985
BraseroScsiErrCode *code)
987
BraseroScsiDVDRWlessWrtDesc *less_wrt_desc;
988
BraseroScsiGetConfigHdr *hdr = NULL;
989
BraseroScsiFeatureDesc *desc;
990
BraseroMediumPrivate *priv;
991
BraseroScsiResult result;
994
priv = BRASERO_MEDIUM_PRIVATE (self);
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,
1003
if (result != BRASERO_SCSI_OK) {
1004
BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
1005
return BRASERO_BURN_ERR;
1010
BRASERO_MEDIA_LOG ("Feature is not current");
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;
1017
return BRASERO_BURN_OK;
1021
* This is a last resort when the initialization has failed.
1025
brasero_medium_test_simulate_2A (BraseroMedium *self,
1026
BraseroDeviceHandle *handle,
1027
BraseroScsiErrCode *code)
1029
BraseroScsiStatusPage *page_2A = NULL;
1030
BraseroScsiModeData *data = NULL;
1031
BraseroMediumPrivate *priv;
1032
BraseroScsiResult result;
1035
priv = BRASERO_MEDIUM_PRIVATE (self);
1037
result = brasero_spc1_mode_sense_get_page (handle,
1038
BRASERO_SPC_PAGE_STATUS,
1042
if (result != BRASERO_SCSI_OK) {
1043
BRASERO_MEDIA_LOG ("MODE SENSE failed");
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
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;
1060
brasero_medium_init_caps (BraseroMedium *self,
1061
BraseroDeviceHandle *handle,
1062
BraseroScsiErrCode *code)
1064
BraseroMediumPrivate *priv;
1065
BraseroScsiResult res;
1067
priv = BRASERO_MEDIUM_PRIVATE (self);
1069
/* These special media don't support/need burnfree and simulation */
1070
if (priv->info & (BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_BD))
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);
1080
res = brasero_medium_test_simulate_DVDRW (self, handle, code);
1082
BRASERO_MEDIA_LOG ("Tested simulation %d %d, burnfree %d",
1087
if (res == BRASERO_SCSI_OK)
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);
1094
BRASERO_MEDIA_LOG ("Re-tested simulation %d %d, burnfree %d",
1101
* Function to retrieve the capacity of a media
1104
static BraseroBurnResult
1105
brasero_medium_get_capacity_CD_RW (BraseroMedium *self,
1106
BraseroDeviceHandle *handle,
1107
BraseroScsiErrCode *code)
1109
BraseroScsiAtipData *atip_data = NULL;
1110
BraseroMediumPrivate *priv;
1111
BraseroScsiResult result;
1114
priv = BRASERO_MEDIUM_PRIVATE (self);
1116
BRASERO_MEDIA_LOG ("Retrieving capacity from atip");
1118
result = brasero_mmc1_read_atip (handle,
1123
if (result != BRASERO_SCSI_OK) {
1124
BRASERO_MEDIA_LOG ("READ ATIP failed (scsi error)");
1125
return BRASERO_BURN_ERR;
1128
/* check the size of the structure: it must be at least 16 bytes long */
1133
BRASERO_MEDIA_LOG ("READ ATIP failed (wrong size)");
1134
return BRASERO_BURN_ERR;
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);
1142
BRASERO_MEDIA_LOG ("Format capacity %lli %lli",
1146
return BRASERO_BURN_OK;
1149
static BraseroBurnResult
1150
brasero_medium_get_capacity_DVD_RW (BraseroMedium *self,
1151
BraseroDeviceHandle *handle,
1152
BraseroScsiErrCode *code)
1154
BraseroScsiFormatCapacitiesHdr *hdr = NULL;
1155
BraseroScsiFormattableCapacityDesc *desc;
1156
BraseroScsiMaxCapacityDesc *current;
1157
BraseroMediumPrivate *priv;
1158
BraseroScsiResult result;
1162
BRASERO_MEDIA_LOG ("Retrieving format capacity");
1164
priv = BRASERO_MEDIUM_PRIVATE (self);
1165
result = brasero_mmc2_read_format_capacities (handle,
1169
if (result != BRASERO_SCSI_OK) {
1170
BRASERO_MEDIA_LOG ("READ FORMAT CAPACITIES failed");
1171
return BRASERO_BURN_ERR;
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
1179
* NOTE: that could work also for BD-R SRM+POW and BD-R RRM */
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;
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;
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;
1202
sizeof (BraseroScsiMaxCapacityDesc)) /
1203
sizeof (BraseroScsiFormattableCapacityDesc);
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);
1213
/* that can happen */
1214
if (!priv->block_size)
1215
priv->block_size = 2048;
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);
1230
else if (desc->format_type == BRASERO_SCSI_MAX_PACKET_SIZE_FORMAT) {
1231
priv->block_num = BRASERO_GET_32 (desc->blocks_num);
1238
BRASERO_MEDIA_LOG ("Format capacity %lli %lli",
1243
return BRASERO_BURN_OK;
1246
static BraseroBurnResult
1247
brasero_medium_get_capacity_by_type (BraseroMedium *self,
1248
BraseroDeviceHandle *handle,
1249
BraseroScsiErrCode *code)
1251
BraseroMediumPrivate *priv;
1253
priv = BRASERO_MEDIUM_PRIVATE (self);
1255
/* For DVDs/BDs that's always that block size */
1256
priv->block_size = 2048;
1258
if (!(priv->info & BRASERO_MEDIUM_REWRITABLE))
1259
return BRASERO_BURN_OK;
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);
1266
return BRASERO_BURN_OK;
1270
* Functions to retrieve the speed
1273
static BraseroBurnResult
1274
brasero_medium_get_speed_mmc3 (BraseroMedium *self,
1275
BraseroDeviceHandle *handle,
1276
BraseroScsiErrCode *code)
1280
gint max_rd, max_wrt;
1281
BraseroScsiResult result;
1282
BraseroMediumPrivate *priv;
1283
BraseroScsiWrtSpdDesc *desc;
1284
BraseroScsiGetPerfData *wrt_perf = NULL;
1286
BRASERO_MEDIA_LOG ("Retrieving speed (Get Performance)");
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,
1296
if (result != BRASERO_SCSI_OK) {
1297
BRASERO_MEDIA_LOG ("GET PERFORMANCE failed");
1298
return BRASERO_BURN_ERR;
1301
BRASERO_MEDIA_LOG ("Successfully retrieved a header: size %d, address %p", size, wrt_perf);
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);
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");
1316
/* Calculate the number of descriptors */
1317
num_desc = (size - sizeof (BraseroScsiGetPerfHdr)) / sizeof (BraseroScsiWrtSpdDesc);
1318
BRASERO_MEDIA_LOG ("Got %d descriptor(s)", num_desc);
1323
priv->rd_speeds = g_new0 (guint, num_desc + 1);
1324
priv->wr_speeds = g_new0 (guint, num_desc + 1);
1329
desc = (BraseroScsiWrtSpdDesc*) &wrt_perf->data;
1331
for (i = 0; i < num_desc; i ++) {
1332
BRASERO_MEDIA_LOG ("Descriptor n° %d, address = %p", i, (desc + i));
1334
priv->rd_speeds [i] = BRASERO_GET_32 (desc [i].rd_speed);
1335
priv->wr_speeds [i] = BRASERO_GET_32 (desc [i].wr_speed);
1337
BRASERO_MEDIA_LOG ("RD = %u / WRT = %u",
1338
priv->rd_speeds [i],
1339
priv->wr_speeds [i]);
1341
max_rd = MAX (max_rd, priv->rd_speeds [i]);
1342
max_wrt = MAX (max_wrt, priv->wr_speeds [i]);
1345
priv->max_rd = max_rd;
1346
priv->max_wrt = max_wrt;
1348
BRASERO_MEDIA_LOG ("Maximum Speed (mmc3) %i", max_wrt);
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 */
1358
return BRASERO_BURN_ERR;
1360
return BRASERO_BURN_OK;
1363
static BraseroBurnResult
1364
brasero_medium_get_page_2A_write_speed_desc (BraseroMedium *self,
1365
BraseroDeviceHandle *handle,
1366
BraseroScsiErrCode *code)
1368
BraseroScsiStatusPage *page_2A = NULL;
1369
BraseroScsiStatusWrSpdDesc *desc;
1370
BraseroScsiModeData *data = NULL;
1371
BraseroMediumPrivate *priv;
1372
BraseroScsiResult result;
1378
BRASERO_MEDIA_LOG ("Retrieving speed (2A speeds)");
1380
priv = BRASERO_MEDIUM_PRIVATE (self);
1381
result = brasero_spc1_mode_sense_get_page (handle,
1382
BRASERO_SPC_PAGE_STATUS,
1386
if (result != BRASERO_SCSI_OK) {
1387
BRASERO_MEDIA_LOG ("MODE SENSE failed");
1388
return BRASERO_BURN_ERR;
1391
page_2A = (BraseroScsiStatusPage *) &data->page;
1393
/* Reminder: size = sizeof (BraseroScsiStatusPage) + sizeof (BraseroScsiModeHdr) */
1394
size = MIN (size, sizeof (data->hdr.len) + BRASERO_GET_16 (data->hdr.len));
1396
if (size < (G_STRUCT_OFFSET (BraseroScsiStatusPage, copy_mngt_rev) + sizeof (BraseroScsiModeHdr))) {
1398
BRASERO_MEDIA_LOG ("wrong page size");
1399
return BRASERO_BURN_ERR;
1402
priv->max_rd = BRASERO_GET_16 (page_2A->rd_max_speed);
1403
priv->max_wrt = BRASERO_GET_16 (page_2A->wr_max_speed);
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);
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);
1419
return BRASERO_BURN_OK;
1422
desc_num = BRASERO_GET_16 (page_2A->wr_speed_desc_num);
1424
sizeof (BraseroScsiStatusPage) -
1425
sizeof (BraseroScsiModeHdr);
1426
max_num /= sizeof (BraseroScsiWrtSpdDesc);
1431
if (desc_num > max_num)
1434
priv->wr_speeds = g_new0 (gint, desc_num + 1);
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]);
1443
priv->max_wrt = max_wrt;
1445
BRASERO_MEDIA_LOG ("Maximum Speed (Page 2A) %i", priv->max_wrt);
1448
return BRASERO_BURN_OK;
1451
static BraseroBurnResult
1452
brasero_medium_get_speed (BraseroMedium *self,
1453
BraseroDeviceHandle *handle,
1454
BraseroScsiErrCode *code)
1456
BraseroScsiResult result;
1458
BRASERO_MEDIA_LOG ("Retrieving media available speeds");
1460
result = brasero_medium_get_speed_mmc3 (self, handle, code);
1461
if (result == BRASERO_BURN_OK)
1465
result = brasero_medium_get_page_2A_write_speed_desc (self, handle, code);
1470
* Functions to get information about disc contents
1473
static BraseroBurnResult
1474
brasero_medium_track_volume_size (BraseroMedium *self,
1475
BraseroMediumTrack *track,
1476
BraseroDeviceHandle *handle)
1478
BraseroMediumPrivate *priv;
1479
BraseroBurnResult res;
1480
GError *error = NULL;
1485
return BRASERO_BURN_ERR;
1487
priv = BRASERO_MEDIUM_PRIVATE (self);
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
1498
vol = brasero_volume_source_open_device_handle (handle, NULL);
1499
res = brasero_volume_get_size (vol,
1503
brasero_volume_source_close (vol);
1506
BRASERO_MEDIA_LOG ("Failed to retrieve the volume size: %s",
1507
error && error->message ?
1508
error->message:"unknown error");
1511
g_error_free (error);
1513
return BRASERO_BURN_ERR;
1516
track->blocks_num = nb_blocks;
1517
return BRASERO_BURN_OK;
1521
brasero_medium_track_written_SAO (BraseroDeviceHandle *handle,
1525
unsigned char buffer [2048];
1526
BraseroScsiResult result;
1528
BRASERO_MEDIA_LOG ("Checking for TDBs in track pregap.");
1530
/* The two following sectors are readable */
1531
result = brasero_mmc1_read_block (handle,
1533
BRASERO_SCSI_BLOCK_TYPE_ANY,
1534
BRASERO_SCSI_BLOCK_HEADER_NONE,
1535
BRASERO_SCSI_BLOCK_NO_SUBCHANNEL,
1542
if (result == BRASERO_SCSI_OK) {
1545
if (buffer [0] != 'T' || buffer [1] != 'D' || buffer [2] != 'I') {
1546
BRASERO_MEDIA_LOG ("Track was probably recorded in SAO mode - no TDB.");
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)
1558
BRASERO_MEDIA_LOG ("No appropriate TDU for track");
1562
if (buffer [8 + i * 16] == 0x80 || buffer [8 + i * 16] == 0x00) {
1563
BRASERO_MEDIA_LOG ("Track was recorded in TAO mode.");
1567
BRASERO_MEDIA_LOG ("Track was recorded in Packet mode.");
1571
BRASERO_MEDIA_LOG ("No pregap. That track must have been recorded in SAO mode.");
1575
static BraseroBurnResult
1576
brasero_medium_track_get_info (BraseroMedium *self,
1577
gboolean multisession,
1578
BraseroMediumTrack *track,
1580
BraseroDeviceHandle *handle,
1581
BraseroScsiErrCode *code)
1583
BraseroScsiTrackInfo track_info;
1584
BraseroMediumPrivate *priv;
1585
BraseroScsiResult result;
1588
BRASERO_MEDIA_LOG ("Retrieving track information for %i", track_num);
1590
priv = BRASERO_MEDIUM_PRIVATE (self);
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
1595
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DUAL_L|BRASERO_MEDIUM_WRITABLE))
1597
else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_WRITABLE))
1602
result = brasero_mmc1_read_track_info (handle,
1608
if (result != BRASERO_SCSI_OK) {
1609
BRASERO_MEDIA_LOG ("READ TRACK INFO failed");
1610
return BRASERO_BURN_ERR;
1613
track->blocks_num = BRASERO_GET_32 (track_info.track_size);
1614
track->session = BRASERO_SCSI_SESSION_NUM (track_info);
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
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
1626
BRASERO_MEDIA_LOG ("300 sectors size. Checking for real size");
1627
brasero_medium_track_volume_size (self, track, handle);
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
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
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)
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).",
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
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,
1671
BRASERO_SCSI_BLOCK_TYPE_ANY,
1672
BRASERO_SCSI_BLOCK_HEADER_NONE,
1673
BRASERO_SCSI_BLOCK_NO_SUBCHANNEL,
1674
track->blocks_num + track->start,
1680
if (result == BRASERO_SCSI_OK) {
1681
BRASERO_MEDIA_LOG ("Following two sectors are readable.");
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);
1689
BRASERO_MEDIA_LOG ("Detected runouts");
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",
1700
return BRASERO_BURN_OK;
1703
static BraseroBurnResult
1704
brasero_medium_track_set_leadout_DVDR_blank (BraseroMedium *self,
1705
BraseroDeviceHandle *handle,
1706
BraseroMediumTrack *leadout,
1707
BraseroScsiErrCode *code)
1709
BraseroScsiFormatCapacitiesHdr *hdr = NULL;
1710
BraseroScsiMaxCapacityDesc *current;
1711
BraseroMediumPrivate *priv;
1712
BraseroScsiResult result;
1715
priv = BRASERO_MEDIUM_PRIVATE (self);
1717
BRASERO_MEDIA_LOG ("Using fallback method for blank CDR to retrieve NWA and leadout information");
1719
/* NWA is easy for blank DVD-Rs, it's 0. So far, so good... */
1720
priv->next_wr_add = 0;
1722
result = brasero_mmc2_read_format_capacities (handle,
1726
if (result != BRASERO_SCSI_OK) {
1727
BRASERO_MEDIA_LOG ("READ FORMAT CAPACITIES failed");
1728
return BRASERO_BURN_ERR;
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");
1737
return BRASERO_BURN_ERR;
1740
BRASERO_MEDIA_LOG ("Unformatted medium");
1742
/* of course it starts at 0 since it's empty */
1744
leadout->blocks_num = BRASERO_GET_32 (current->blocks_num);
1746
BRASERO_MEDIA_LOG ("Leadout (through READ FORMAT CAPACITIES): start = %llu size = %llu",
1748
leadout->blocks_num);
1751
return BRASERO_BURN_OK;
1754
static BraseroBurnResult
1755
brasero_medium_track_set_leadout_CDR_blank (BraseroMedium *self,
1756
BraseroDeviceHandle *handle,
1757
BraseroMediumTrack *leadout,
1758
BraseroScsiErrCode *code)
1760
BraseroScsiAtipData *atip = NULL;
1761
BraseroMediumPrivate *priv;
1762
BraseroScsiResult result;
1765
priv = BRASERO_MEDIUM_PRIVATE (self);
1767
BRASERO_MEDIA_LOG ("Using fallback method for blank CDR to retrieve NWA and leadout information");
1769
/* NWA is easy for blank CDRs, it's 0. So far, so good... */
1770
priv->next_wr_add = 0;
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;
1778
leadout->blocks_num = atip->desc->leadout_mn * 60 * 75 +
1779
atip->desc->leadout_sec * 75 +
1780
atip->desc->leadout_frame;
1782
/* of course it starts at 0 since it's empty */
1785
BRASERO_MEDIA_LOG ("Leadout (through READ ATIP): start = %llu size = %llu",
1787
leadout->blocks_num);
1791
return BRASERO_BURN_OK;
1794
static BraseroBurnResult
1795
brasero_medium_set_write_mode_page (BraseroMedium *self,
1796
BraseroDeviceHandle *handle,
1797
BraseroScsiErrCode *code)
1799
BraseroScsiModeData *data = NULL;
1800
BraseroScsiWritePage *wrt_page;
1801
BraseroMediumPrivate *priv;
1802
BraseroScsiResult result;
1805
BRASERO_MEDIA_LOG ("Setting write mode page");
1807
priv = BRASERO_MEDIUM_PRIVATE (self);
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,
1818
if (result == BRASERO_SCSI_OK) {
1819
wrt_page = (BraseroScsiWritePage *) &data->page;
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);
1825
/* "reset some stuff to be on the safe side" (words and ideas
1826
* taken from k3b:)). */
1829
wrt_page->multisession = 0;
1830
wrt_page->testwrite = 0;
1834
wrt_page->session_format = 0;
1835
BRASERO_SET_16 (wrt_page->pause_len, 150);
1837
if (priv->info & BRASERO_MEDIUM_CD) {
1838
wrt_page->write_type = BRASERO_SCSI_WRITE_TAO;
1839
wrt_page->track_mode = 4;
1841
else if (priv->info & BRASERO_MEDIUM_DVD) {
1842
wrt_page->write_type = BRASERO_SCSI_WRITE_PACKET_INC;
1843
wrt_page->track_mode = 5;
1846
wrt_page->data_block_type = 8;
1848
result = brasero_spc1_mode_select (handle, data, size, code);
1851
if (result != BRASERO_SCSI_OK) {
1852
BRASERO_MEDIA_LOG ("MODE SELECT failed");
1854
/* This isn't necessarily a problem! we better try */
1855
return BRASERO_BURN_ERR;
1859
BRASERO_MEDIA_LOG ("MODE SENSE failed");
1860
/* This isn't necessarily a problem! we better try the rest */
1861
return BRASERO_BURN_ERR;
1864
return BRASERO_BURN_OK;
1867
static BraseroBurnResult
1868
brasero_medium_track_set_leadout (BraseroMedium *self,
1869
BraseroDeviceHandle *handle,
1870
BraseroMediumTrack *leadout,
1871
BraseroScsiErrCode *code)
1873
BraseroScsiTrackInfo track_info;
1874
BraseroMediumPrivate *priv;
1875
BraseroScsiResult result;
1879
BRASERO_MEDIA_LOG ("Retrieving NWA and leadout information");
1881
priv = BRASERO_MEDIUM_PRIVATE (self);
1883
if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info)) {
1884
BRASERO_MEDIA_LOG ("Overwritable medium => skipping");
1885
return BRASERO_BURN_OK;
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,
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
1906
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DUAL_L|BRASERO_MEDIUM_WRITABLE))
1908
else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_WRITABLE))
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))
1918
else if (priv->first_open_track >= 0)
1919
track_num = priv->first_open_track;
1921
BRASERO_MEDIA_LOG ("There aren't any open session set");
1922
return BRASERO_BURN_ERR;
1925
result = brasero_mmc1_read_track_info (handle,
1930
if (result != BRASERO_SCSI_OK) {
1931
BRASERO_MEDIA_LOG ("READ TRACK INFO failed");
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,
1939
else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BLANK))
1940
return brasero_medium_track_set_leadout_DVDR_blank (self,
1945
return BRASERO_BURN_ERR;
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);
1952
BRASERO_MEDIA_LOG ("Next Writable Address is not valid");
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);
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);
1963
if (!leadout->blocks_num
1964
&& BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BLANK))
1965
return brasero_medium_track_set_leadout_DVDR_blank (self,
1970
BRASERO_MEDIA_LOG ("Leadout: start = %llu size = %llu",
1972
leadout->blocks_num);
1974
return BRASERO_BURN_OK;
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.
1985
brasero_medium_add_DVD_plus_RW_leadout (BraseroMedium *self)
1987
BraseroMediumTrack *leadout;
1988
BraseroMediumPrivate *priv;
1992
priv = BRASERO_MEDIUM_PRIVATE (self);
1994
/* determine the start */
1996
BraseroMediumTrack *track;
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);
2004
blocks_num = priv->block_num;
2007
leadout = g_new0 (BraseroMediumTrack, 1);
2008
priv->tracks = g_slist_append (priv->tracks, leadout);
2010
leadout->start = start;
2011
leadout->blocks_num = blocks_num;
2012
leadout->type = BRASERO_MEDIUM_TRACK_LEADOUT;
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
2019
priv->next_wr_add = 0;
2021
BRASERO_MEDIA_LOG ("Adding fabricated leadout start = %llu length = %llu",
2023
leadout->blocks_num);
2026
static BraseroBurnResult
2027
brasero_medium_get_sessions_info (BraseroMedium *self,
2028
BraseroDeviceHandle *handle,
2029
BraseroScsiErrCode *code)
2032
gboolean multisession;
2033
BraseroScsiResult result;
2034
BraseroScsiTocDesc *desc;
2035
BraseroMediumPrivate *priv;
2036
BraseroScsiFormattedTocData *toc = NULL;
2038
BRASERO_MEDIA_LOG ("Reading Toc");
2040
priv = BRASERO_MEDIUM_PRIVATE (self);
2041
result = brasero_mmc1_read_toc_formatted (handle,
2046
if (result != BRASERO_SCSI_OK) {
2047
BRASERO_MEDIA_LOG ("READ TOC failed");
2048
return BRASERO_BURN_ERR;
2051
num = (size - sizeof (BraseroScsiFormattedTocData)) /
2052
sizeof (BraseroScsiTocDesc);
2054
/* remove 1 for leadout */
2055
multisession = !(priv->info & BRASERO_MEDIUM_BLANK) && num > 0;
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
2061
BRASERO_MEDIA_LOG ("%i track(s) found", num);
2064
for (i = 0; i < num; i ++, desc ++) {
2065
BraseroMediumTrack *track;
2067
if (desc->track_num == BRASERO_SCSI_TRACK_LEADOUT_START) {
2068
BRASERO_MEDIA_LOG ("Leadout reached %d",
2069
BRASERO_GET_32 (desc->track_start));
2073
track = g_new0 (BraseroMediumTrack, 1);
2074
priv->tracks = g_slist_prepend (priv->tracks, track);
2075
track->start = BRASERO_GET_32 (desc->track_start);
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;
2081
if (!(desc->control & BRASERO_SCSI_TRACK_DATA)) {
2082
track->type |= BRASERO_MEDIUM_TRACK_AUDIO;
2083
priv->info |= BRASERO_MEDIUM_HAS_AUDIO;
2085
if (desc->control & BRASERO_SCSI_TRACK_PREEMP)
2086
track->type |= BRASERO_MEDIUM_TRACK_PREEMP;
2088
if (desc->control & BRASERO_SCSI_TRACK_4_CHANNELS)
2089
track->type |= BRASERO_MEDIUM_TRACK_4_CHANNELS;
2092
track->type |= BRASERO_MEDIUM_TRACK_DATA;
2093
priv->info |= BRASERO_MEDIUM_HAS_DATA;
2095
if (desc->control & BRASERO_SCSI_TRACK_DATA_INCREMENTAL)
2096
track->type |= BRASERO_MEDIUM_TRACK_INCREMENTAL;
2099
if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info)) {
2100
BraseroBurnResult result;
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);
2109
result = brasero_medium_track_volume_size (self,
2112
if (result != BRASERO_BURN_OK) {
2113
priv->tracks = g_slist_remove (priv->tracks, track);
2116
priv->info |= BRASERO_MEDIUM_BLANK;
2117
priv->info &= ~(BRASERO_MEDIUM_CLOSED|
2118
BRASERO_MEDIUM_HAS_DATA);
2120
BRASERO_MEDIA_LOG ("Empty first session.");
2123
priv->next_wr_add = 0;
2124
BRASERO_MEDIA_LOG ("Track 1 (session %i): type = %i start = %llu size = %llu",
2131
/* NOTE: the next track should be the leadout */
2135
if (priv->probe_cancelled) {
2137
return BRASERO_BURN_CANCEL;
2140
brasero_medium_track_get_info (self,
2143
g_slist_length (priv->tracks),
2148
if (priv->probe_cancelled) {
2150
return BRASERO_BURN_CANCEL;
2153
/* put the tracks in the right order */
2154
priv->tracks = g_slist_reverse (priv->tracks);
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;
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);
2168
brasero_medium_track_set_leadout (self,
2176
return BRASERO_BURN_OK;
2180
brasero_medium_get_DVD_id (BraseroMedium *self,
2181
BraseroDeviceHandle *handle,
2182
BraseroScsiErrCode *code)
2185
BraseroScsiResult result;
2186
BraseroMediumPrivate *priv;
2187
BraseroScsiReadDiscStructureHdr *hdr = NULL;
2189
priv = BRASERO_MEDIUM_PRIVATE (self);
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,
2197
if (result != BRASERO_SCSI_OK) {
2198
BRASERO_MEDIA_LOG ("Retrieval of DVD id failed");
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));
2207
static BraseroBurnResult
2208
brasero_medium_set_blank (BraseroMedium *self,
2209
BraseroDeviceHandle *handle,
2210
gint first_open_track,
2211
BraseroScsiErrCode *code)
2213
BraseroMediumPrivate *priv;
2214
BraseroMediumTrack *track;
2216
priv = BRASERO_MEDIUM_PRIVATE (self);
2218
BRASERO_MEDIA_LOG ("Empty media");
2220
priv->info |= BRASERO_MEDIUM_BLANK;
2221
priv->block_size = 2048;
2223
priv->first_open_track = first_open_track;
2224
BRASERO_MEDIA_LOG ("First open track %d", priv->first_open_track);
2226
if (BRASERO_MEDIUM_RANDOM_WRITABLE (priv->info))
2227
brasero_medium_add_DVD_plus_RW_leadout (self);
2229
track = g_new0 (BraseroMediumTrack, 1);
2231
track->type = BRASERO_MEDIUM_TRACK_LEADOUT;
2232
priv->tracks = g_slist_prepend (priv->tracks, track);
2234
brasero_medium_track_set_leadout (self,
2240
return BRASERO_BURN_OK;
2243
static BraseroBurnResult
2244
brasero_medium_get_contents (BraseroMedium *self,
2245
BraseroDeviceHandle *handle,
2246
BraseroScsiErrCode *code)
2249
BraseroBurnResult res;
2250
BraseroScsiResult result;
2251
BraseroMediumPrivate *priv;
2252
BraseroScsiDiscInfoStd *info = NULL;
2254
BRASERO_MEDIA_LOG ("Retrieving media status");
2256
priv = BRASERO_MEDIUM_PRIVATE (self);
2258
result = brasero_mmc1_read_disc_information_std (handle,
2262
if (result != BRASERO_SCSI_OK) {
2263
BRASERO_MEDIA_LOG ("READ DISC INFORMATION failed");
2264
return BRASERO_BURN_ERR;
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));
2272
else if (priv->info & BRASERO_MEDIUM_DVD)
2273
brasero_medium_get_DVD_id (self, handle, code);
2276
priv->info |= BRASERO_MEDIUM_REWRITABLE;
2278
priv->first_open_track = -1;
2280
if (info->status == BRASERO_SCSI_DISC_EMPTY) {
2281
res = brasero_medium_set_blank (self,
2283
BRASERO_FIRST_TRACK_IN_LAST_SESSION (info),
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");
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);
2294
res = brasero_medium_get_sessions_info (self, handle, code);
2297
/* if that type of media is in incomplete state that
2298
* means it has just been formatted. And therefore it's
2300
res = brasero_medium_set_blank (self,
2302
BRASERO_FIRST_TRACK_IN_LAST_SESSION (info),
2306
else if (info->status == BRASERO_SCSI_DISC_FINALIZED) {
2307
priv->info |= BRASERO_MEDIUM_CLOSED;
2308
BRASERO_MEDIA_LOG ("Closed media");
2310
res = brasero_medium_get_sessions_info (self, handle, code);
2318
* Some identification functions
2321
static BraseroBurnResult
2322
brasero_medium_get_medium_type (BraseroMedium *self,
2323
BraseroDeviceHandle *handle,
2324
BraseroScsiErrCode *code)
2326
BraseroScsiProfile profile;
2327
BraseroMediumPrivate *priv;
2328
BraseroScsiResult result;
2330
BRASERO_MEDIA_LOG ("Retrieving media profile");
2332
priv = BRASERO_MEDIUM_PRIVATE (self);
2333
result = brasero_mmc2_get_profile (handle, &profile, code);
2335
if (result != BRASERO_SCSI_OK) {
2336
BraseroScsiAtipData *data = NULL;
2339
BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
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. */
2346
/* retrieve the speed */
2347
result = brasero_medium_get_page_2A_write_speed_desc (self,
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;
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,
2365
if (result != BRASERO_SCSI_OK) {
2367
priv->info = BRASERO_MEDIUM_CDROM;
2368
priv->type = types [1];
2371
/* check the size of the structure: it must be at least 8 bytes long */
2376
BRASERO_MEDIA_LOG ("READ ATIP failed (wrong size)");
2377
return BRASERO_BURN_ERR;
2380
if (data->desc->erasable) {
2382
priv->info = BRASERO_MEDIUM_CDRW;
2383
priv->type = types [3];
2387
priv->info = BRASERO_MEDIUM_CDR;
2388
priv->type = types [2];
2398
case BRASERO_SCSI_PROF_CDROM:
2399
priv->info = BRASERO_MEDIUM_CDROM;
2400
priv->type = types [1];
2403
case BRASERO_SCSI_PROF_CDR:
2404
priv->info = BRASERO_MEDIUM_CDR;
2405
priv->type = types [2];
2408
case BRASERO_SCSI_PROF_CDRW:
2409
priv->info = BRASERO_MEDIUM_CDRW;
2410
priv->type = types [3];
2413
case BRASERO_SCSI_PROF_DVD_ROM:
2414
priv->info = BRASERO_MEDIUM_DVD_ROM;
2415
priv->type = types [4];
2418
case BRASERO_SCSI_PROF_DVD_R:
2419
priv->info = BRASERO_MEDIUM_DVDR;
2420
priv->type = types [5];
2423
case BRASERO_SCSI_PROF_DVD_RW_RESTRICTED:
2424
priv->info = BRASERO_MEDIUM_DVDRW_RESTRICTED;
2425
priv->type = types [6];
2428
case BRASERO_SCSI_PROF_DVD_RW_SEQUENTIAL:
2429
priv->info = BRASERO_MEDIUM_DVDRW;
2430
priv->type = types [6];
2433
case BRASERO_SCSI_PROF_DVD_R_PLUS:
2434
priv->info = BRASERO_MEDIUM_DVDR_PLUS;
2435
priv->type = types [7];
2438
case BRASERO_SCSI_PROF_DVD_RW_PLUS:
2439
priv->info = BRASERO_MEDIUM_DVDRW_PLUS;
2440
priv->type = types [8];
2443
case BRASERO_SCSI_PROF_DVD_R_PLUS_DL:
2444
priv->info = BRASERO_MEDIUM_DVDR_PLUS_DL;
2445
priv->type = types [9];
2448
case BRASERO_SCSI_PROF_DVD_RW_PLUS_DL:
2449
priv->info = BRASERO_MEDIUM_DVDRW_PLUS_DL;
2450
priv->type = types [10];
2453
case BRASERO_SCSI_PROF_DVD_R_DL_SEQUENTIAL:
2454
priv->info = BRASERO_MEDIUM_DVDR_DL;
2455
priv->type = types [11];
2458
case BRASERO_SCSI_PROF_DVD_R_DL_JUMP:
2459
priv->info = BRASERO_MEDIUM_DVDR_JUMP_DL;
2460
priv->type = types [11];
2463
case BRASERO_SCSI_PROF_BD_ROM:
2464
priv->info = BRASERO_MEDIUM_BD_ROM;
2465
priv->type = types [13];
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];
2474
case BRASERO_SCSI_PROF_BR_R_RANDOM:
2475
priv->info = BRASERO_MEDIUM_BDR_RANDOM;
2476
priv->type = types [14];
2479
case BRASERO_SCSI_PROF_BD_RW:
2480
priv->info = BRASERO_MEDIUM_BDRE;
2481
priv->type = types [15];
2484
case BRASERO_SCSI_PROF_DVD_RAM:
2485
priv->info = BRASERO_MEDIUM_DVD_RAM;
2486
priv->type = types [12];
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;
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;
2510
/* check for POW type */
2511
result = brasero_mmc2_get_configuration_feature (handle,
2512
BRASERO_SCSI_FEAT_BDR_POW,
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;
2525
BraseroScsiFormatCapacitiesHdr *hdr = NULL;
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,
2535
if (result == BRASERO_SCSI_OK) {
2536
BraseroScsiMaxCapacityDesc *current;
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;
2549
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BD)) {
2550
/* FIXME: check for dual layer BD */
2553
return BRASERO_BURN_OK;
2556
static BraseroBurnResult
2557
brasero_medium_get_css_feature (BraseroMedium *self,
2558
BraseroDeviceHandle *handle,
2559
BraseroScsiErrCode *code)
2561
BraseroScsiGetConfigHdr *hdr = NULL;
2562
BraseroMediumPrivate *priv;
2563
BraseroScsiResult result;
2566
priv = BRASERO_MEDIUM_PRIVATE (self);
2568
BRASERO_MEDIA_LOG ("Testing for Css encrypted media");
2569
result = brasero_mmc2_get_configuration_feature (handle,
2570
BRASERO_SCSI_FEAT_DVD_CSS,
2574
if (result != BRASERO_SCSI_OK) {
2575
BRASERO_MEDIA_LOG ("GET CONFIGURATION failed");
2576
return BRASERO_BURN_ERR;
2579
if (hdr->desc->add_len < sizeof (BraseroScsiDVDCssDesc)) {
2581
return BRASERO_BURN_OK;
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");
2591
return BRASERO_BURN_OK;
2595
brasero_medium_get_CD_TEXT (BraseroMedium *medium,
2598
guint charset_CD_TEXT,
2599
gboolean double_byte,
2603
BraseroMediumPrivate *priv;
2604
const gchar *charset = NULL;
2606
priv = BRASERO_MEDIUM_PRIVATE (medium);
2608
/* For the moment we're only interested in medium title but that could
2609
* be extented to all tracks information. */
2611
case BRASERO_SCSI_CD_TEXT_ALBUM_TITLE:
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:
2629
g_get_charset (&charset);
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,
2643
case BRASERO_CD_TEXT_KANJI:
2644
utf8_string = g_convert_with_fallback (string,
2653
case BRASERO_CD_TEXT_KOREAN:
2654
utf8_string = g_convert_with_fallback (string,
2663
case BRASERO_CD_TEXT_CHINESE:
2664
utf8_string = g_convert_with_fallback (string,
2674
case BRASERO_CD_TEXT_ASCII:
2675
utf8_string = g_convert_with_fallback (string,
2686
if (priv->CD_TEXT_title)
2687
g_free (priv->CD_TEXT_title);
2690
BRASERO_MEDIA_LOG ("Charset convertion failed");
2691
priv->CD_TEXT_title = g_strdup (string);
2694
priv->CD_TEXT_title = utf8_string;
2696
BRASERO_MEDIA_LOG ("CD-TEXT title %s", priv->CD_TEXT_title);
2701
_next_CD_TEXT_pack (BraseroScsiCDTextData *cd_text,
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) {
2729
brasero_medium_read_CD_TEXT_block_info (BraseroScsiCDTextData *cd_text,
2734
while ((current = _next_CD_TEXT_pack (cd_text, current, max)) != -1) {
2737
if (cd_text->pack [current].type != BRASERO_SCSI_CD_TEXT_BLOCK_SIZE)
2741
memcpy (buffer + offset,
2742
cd_text->pack [current].text,
2743
sizeof (cd_text->pack [current].text));
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);
2756
brasero_medium_read_CD_TEXT (BraseroMedium *self,
2757
BraseroDeviceHandle *handle,
2758
BraseroScsiErrCode *code)
2764
char buffer [256]; /* mmc specs advise no more than 160 */
2765
gboolean find_block_info;
2766
BraseroMediumPrivate *priv;
2767
BraseroScsiCDTextData *cd_text;
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");
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);
2780
priv = BRASERO_MEDIUM_PRIVATE (self);
2784
charset = BRASERO_CD_TEXT_ASCII;
2787
find_block_info = TRUE;
2788
while ((i = _next_CD_TEXT_pack (cd_text, i, num)) != -1) {
2790
gboolean is_double_byte;
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;
2798
if (find_block_info) {
2799
find_block_info = FALSE;
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;
2807
pack = (BraseroScsiCDTextPackCharset *) buffer;
2808
charset = pack->charset;
2810
BRASERO_MEDIA_LOG ("Found language pack. Charset = %d. Start %d. End %d",
2811
charset, pack->first_track, pack->last_track);
2815
track_num = cd_text->pack [i].track_num;
2816
is_double_byte = cd_text->pack [i].double_byte;
2818
for (j = 0; j < sizeof (cd_text->pack [i].text); j++) {
2820
&& cd_text->pack [i].text [j] == '\t'
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,
2831
cd_text->pack [i].double_byte,
2837
buffer [off] = cd_text->pack [i].text [j];
2840
if (cd_text->pack [i].text [j] == '\0'
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,
2850
cd_text->pack [i].double_byte,
2853
/* End of encapsulated Text Pack. Skip to the next. */
2864
brasero_medium_init_real (BraseroMedium *object,
2865
BraseroDeviceHandle *handle)
2869
BraseroBurnResult result;
2870
BraseroMediumPrivate *priv;
2871
BraseroScsiErrCode code = 0;
2872
gchar buffer [256] = { 0, };
2874
priv = BRASERO_MEDIUM_PRIVATE (object);
2876
name = brasero_drive_get_display_name (priv->drive);
2877
BRASERO_MEDIA_LOG ("Initializing information for medium in %s", name);
2880
if (priv->probe_cancelled)
2883
result = brasero_medium_get_medium_type (object, handle, &code);
2884
if (result != BRASERO_BURN_OK)
2887
if (priv->probe_cancelled)
2890
result = brasero_medium_get_speed (object, handle, &code);
2891
if (result != BRASERO_BURN_OK)
2894
if (priv->probe_cancelled)
2897
brasero_medium_get_capacity_by_type (object, handle, &code);
2898
if (priv->probe_cancelled)
2901
result = brasero_medium_get_contents (object, handle, &code);
2902
if (result != BRASERO_BURN_OK)
2905
if (priv->probe_cancelled)
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);
2913
if (priv->probe_cancelled)
2916
brasero_medium_init_caps (object, handle, &code);
2917
if (priv->probe_cancelled)
2920
/* read CD-TEXT title */
2921
if (priv->info & BRASERO_MEDIUM_HAS_AUDIO)
2922
brasero_medium_read_CD_TEXT (object, handle, &code);
2924
if (priv->probe_cancelled)
2927
brasero_media_to_string (priv->info, buffer);
2928
BRASERO_MEDIA_LOG ("media is %s", buffer);
2930
if (!priv->wr_speeds)
2933
/* sort write speeds */
2934
for (i = 0; priv->wr_speeds [i] != 0; i ++) {
2937
for (j = 0; priv->wr_speeds [j] != 0; j ++) {
2938
if (priv->wr_speeds [i] > priv->wr_speeds [j]) {
2941
tmp = priv->wr_speeds [i];
2942
priv->wr_speeds [i] = priv->wr_speeds [j];
2943
priv->wr_speeds [j] = tmp;
2950
brasero_medium_probed (gpointer data)
2952
BraseroMediumPrivate *priv;
2954
priv = BRASERO_MEDIUM_PRIVATE (data);
2956
/* This signal must be emitted in the main thread */
2957
GDK_THREADS_ENTER ();
2958
g_signal_emit (data,
2959
medium_signals [PROBED],
2961
GDK_THREADS_LEAVE ();
2968
brasero_medium_probe_thread (gpointer self)
2972
BraseroScsiErrCode code;
2973
BraseroMediumPrivate *priv;
2974
BraseroDeviceHandle *handle;
2976
priv = BRASERO_MEDIUM_PRIVATE (self);
2977
path = brasero_drive_get_device (priv->drive);
2979
priv->info = BRASERO_MEDIUM_BUSY;
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);
2985
handle = brasero_device_handle_open (path, FALSE, &code);
2986
while (!handle && counter <= BRASERO_MEDIUM_OPEN_ATTEMPTS) {
2989
if (priv->probe_cancelled) {
2995
handle = brasero_device_handle_open (path, FALSE, &code);
2998
if (priv->probe_cancelled) {
3004
BRASERO_MEDIA_LOG ("Open () succeeded");
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) {
3011
if (priv->probe_cancelled) {
3013
brasero_device_handle_close (handle);
3014
BRASERO_MEDIA_LOG ("Device probing cancelled");
3019
BRASERO_MEDIA_LOG ("Device ready");
3021
brasero_medium_init_real (BRASERO_MEDIUM (self), handle);
3022
brasero_device_handle_close (handle);
3025
BRASERO_MEDIA_LOG ("Open () failed: medium busy");
3027
priv->probe_id = g_idle_add (brasero_medium_probed, self);
3033
brasero_medium_probe (BraseroMedium *self)
3035
BraseroMediumPrivate *priv;
3037
priv = BRASERO_MEDIUM_PRIVATE (self);
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,
3051
brasero_medium_init_file (BraseroMedium *self)
3053
BraseroMediumPrivate *priv;
3055
priv = BRASERO_MEDIUM_PRIVATE (self);
3057
priv->info = BRASERO_MEDIUM_FILE;
3058
priv->type = types [0];
3062
brasero_medium_init (BraseroMedium *object)
3064
BraseroMediumPrivate *priv;
3066
priv = BRASERO_MEDIUM_PRIVATE (object);
3067
priv->next_wr_add = -1;
3069
/* we can't do anything here since properties haven't been set yet */
3073
brasero_medium_finalize (GObject *object)
3075
BraseroMediumPrivate *priv;
3077
priv = BRASERO_MEDIUM_PRIVATE (object);
3080
priv->probe_cancelled = TRUE;
3081
g_thread_join (priv->probe);
3085
if (priv->probe_id) {
3086
g_source_remove (priv->probe_id);
3095
if (priv->CD_TEXT_title) {
3096
g_free (priv->CD_TEXT_title);
3097
priv->CD_TEXT_title = NULL;
3100
g_free (priv->rd_speeds);
3101
priv->rd_speeds = NULL;
3103
g_free (priv->wr_speeds);
3104
priv->wr_speeds = NULL;
3106
g_slist_foreach (priv->tracks, (GFunc) g_free, NULL);
3107
g_slist_free (priv->tracks);
3108
priv->tracks = NULL;
3112
G_OBJECT_CLASS (parent_class)->finalize (object);
3116
brasero_medium_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3118
BraseroMediumPrivate *priv;
3120
g_return_if_fail (BRASERO_IS_MEDIUM (object));
3122
priv = BRASERO_MEDIUM_PRIVATE (object);
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);
3132
if (brasero_drive_is_fake (priv->drive)) {
3133
brasero_medium_init_file (BRASERO_MEDIUM (object));
3137
brasero_medium_probe (BRASERO_MEDIUM (object));
3140
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3146
brasero_medium_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3148
BraseroMediumPrivate *priv;
3150
g_return_if_fail (BRASERO_IS_MEDIUM (object));
3152
priv = BRASERO_MEDIUM_PRIVATE (object);
3157
g_value_set_object (value, priv->drive);
3160
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3166
brasero_medium_class_init (BraseroMediumClass *klass)
3168
GObjectClass* object_class = G_OBJECT_CLASS (klass);
3169
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
3171
g_type_class_add_private (klass, sizeof (BraseroMediumPrivate));
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;
3178
* BraseroMedium::probed:
3179
* @medium: the object which received the signal
3181
* This signal gets emitted when the medium inside the drive has been
3182
* fully probed. This is mostly for internal use.
3185
medium_signals[PROBED] =
3186
g_signal_new ("probed",
3187
G_OBJECT_CLASS_TYPE (klass),
3188
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE,
3191
g_cclosure_marshal_VOID__VOID,
3195
g_object_class_install_property (object_class,
3197
g_param_spec_object ("drive",
3199
"Drive in which medium is inserted",
3201
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
3205
* brasero_medium_can_be_written:
3206
* @medium: #BraseroMedium
3208
* Gets whether the medium can be written. It also checks that the medium can
3211
* Return value: a #gboolean. TRUE if the medium can be rewritten, FALSE otherwise.
3215
brasero_medium_can_be_written (BraseroMedium *medium)
3217
BraseroMediumPrivate *priv;
3218
BraseroDriveCaps caps;
3220
g_return_val_if_fail (medium != NULL, FALSE);
3221
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
3223
priv = BRASERO_MEDIUM_PRIVATE (medium);
3225
if (!(priv->info & BRASERO_MEDIUM_REWRITABLE)
3226
&& (priv->info & BRASERO_MEDIUM_CLOSED))
3229
if (priv->info & BRASERO_MEDIUM_FILE)
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;
3236
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR))
3237
return (caps & BRASERO_DRIVE_CAPS_DVDR) != 0;
3239
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR_PLUS))
3240
return (caps & BRASERO_DRIVE_CAPS_DVDR_PLUS) != 0;
3242
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_CDRW))
3243
return (caps & BRASERO_DRIVE_CAPS_CDRW) != 0;
3245
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW))
3246
return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
3248
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
3249
return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
3251
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS))
3252
return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS) != 0;
3254
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDR_PLUS_DL))
3255
return (caps & BRASERO_DRIVE_CAPS_DVDR_PLUS_DL) != 0;
3257
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS_DL))
3258
return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL) != 0;
3260
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVD_RAM))
3261
return (caps & BRASERO_DRIVE_CAPS_DVDRAM) != 0;
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;
3267
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE))
3268
return (caps & BRASERO_DRIVE_CAPS_BDRW) != 0;
3274
* brasero_medium_can_be_rewritten:
3275
* @medium: #BraseroMedium
3277
* Gets whether the medium can be rewritten. Note: it also checks that the drive
3278
* can rewrite the medium type.
3280
* Return value: a #gboolean. TRUE if the medium can be rewritten, FALSE otherwise.
3284
brasero_medium_can_be_rewritten (BraseroMedium *medium)
3286
BraseroMediumPrivate *priv;
3287
BraseroDriveCaps caps;
3289
g_return_val_if_fail (medium != NULL, FALSE);
3290
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), FALSE);
3292
priv = BRASERO_MEDIUM_PRIVATE (medium);
3294
if (!(priv->info & BRASERO_MEDIUM_REWRITABLE)
3295
|| (priv->info & BRASERO_MEDIUM_FILE))
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;
3302
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW))
3303
return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
3305
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
3306
return (caps & BRASERO_DRIVE_CAPS_DVDRW) != 0;
3308
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS))
3309
return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS) != 0;
3311
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS_DL))
3312
return (caps & BRASERO_DRIVE_CAPS_DVDRW_PLUS_DL) != 0;
3314
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVD_RAM))
3315
return (caps & BRASERO_DRIVE_CAPS_DVDRAM) != 0;
3317
if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_BDRE))
3318
return (caps & BRASERO_DRIVE_CAPS_BDRW) != 0;
3324
* brasero_medium_get_drive:
3325
* @medium: #BraseroMedium
3327
* Gets the #BraseroDrive in which the medium is inserted.
3329
* Return value: a #BraseroDrive. No need to unref after use.
3333
brasero_medium_get_drive (BraseroMedium *medium)
3335
BraseroMediumPrivate *priv;
3340
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
3342
priv = BRASERO_MEDIUM_PRIVATE (medium);
3347
* brasero_medium_get_CD_TEXT_title:
3348
* @medium: #BraseroMedium
3350
* Gets the CD-TEXT title for @Medium.
3352
* Return value: a #gchar *.
3356
brasero_medium_get_CD_TEXT_title (BraseroMedium *medium)
3358
BraseroMediumPrivate *priv;
3360
g_return_val_if_fail (medium != NULL, NULL);
3361
g_return_val_if_fail (BRASERO_IS_MEDIUM (medium), NULL);
3363
priv = BRASERO_MEDIUM_PRIVATE (medium);
3364
return priv->CD_TEXT_title;
3369
brasero_medium_get_type (void)
3371
static GType our_type = 0;
3375
static const GTypeInfo our_info =
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 */
3389
our_type = g_type_register_static (G_TYPE_OBJECT, "BraseroMedium",