2073 lines
52 KiB
C
2073 lines
52 KiB
C
--- src/burn-medium.c.orig 2008-01-27 10:25:14.000000000 -0500
|
|
+++ src/burn-medium.c 2008-02-06 01:55:21.000000000 -0500
|
|
@@ -1,2070 +0,0 @@
|
|
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
-/*
|
|
- * brasero
|
|
- * Copyright (C) Philippe Rouquier 2007 <bonfire-app@wanadoo.fr>
|
|
- *
|
|
- * brasero is free software.
|
|
- *
|
|
- * You may redistribute it and/or modify it under the terms of the
|
|
- * GNU General Public License, as published by the Free Software
|
|
- * Foundation; either version 2 of the License, or (at your option)
|
|
- * any later version.
|
|
- *
|
|
- * brasero is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
- * See the GNU General Public License for more details.
|
|
- *
|
|
- * You should have received a copy of the GNU General Public License
|
|
- * along with brasero. If not, write to:
|
|
- * The Free Software Foundation, Inc.,
|
|
- * 51 Franklin Street, Fifth Floor
|
|
- * Boston, MA 02110-1301, USA.
|
|
- */
|
|
-
|
|
-#ifdef HAVE_CONFIG_H
|
|
-# include <config.h>
|
|
-#endif
|
|
-
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <fcntl.h>
|
|
-#include <errno.h>
|
|
-
|
|
-#include <glib.h>
|
|
-#include <glib/gi18n-lib.h>
|
|
-
|
|
-#include <nautilus-burn-drive.h>
|
|
-
|
|
-#include "burn-basics.h"
|
|
-#include "burn-debug.h"
|
|
-#include "burn-medium.h"
|
|
-#include "scsi-mmc1.h"
|
|
-#include "scsi-mmc2.h"
|
|
-#include "scsi-mmc3.h"
|
|
-#include "scsi-spc1.h"
|
|
-#include "scsi-utils.h"
|
|
-#include "scsi-mode-pages.h"
|
|
-#include "scsi-status-page.h"
|
|
-#include "scsi-q-subchannel.h"
|
|
-#include "scsi-dvd-structures.h"
|
|
-#include "burn-volume.h"
|
|
-#include "brasero-ncb.h"
|
|
-
|
|
-const gchar *icons [] = { "gnome-dev-removable",
|
|
- "gnome-dev-cdrom",
|
|
- "gnome-dev-disc-cdr",
|
|
- "gnome-dev-disc-cdrw",
|
|
- "gnome-dev-disc-dvdrom",
|
|
- "gnome-dev-disc-dvdr",
|
|
- "gnome-dev-disc-dvdrw",
|
|
- "gnome-dev-disc-dvdr-plus",
|
|
- "gnome-dev-disc-dvdram",
|
|
- NULL };
|
|
-const gchar *types [] = { N_("file"),
|
|
- N_("CDROM"),
|
|
- N_("CD-R"),
|
|
- N_("CD-RW"),
|
|
- N_("DVDROM"),
|
|
- N_("DVD-R"),
|
|
- N_("DVD-RW"),
|
|
- N_("DVD+R"),
|
|
- N_("DVD+RW"),
|
|
- N_("DVD+R dual layer"),
|
|
- N_("DVD+RW dual layer"),
|
|
- N_("DVD-R dual layer"),
|
|
- N_("DVD-RAM"),
|
|
- N_("Blu-ray disc"),
|
|
- N_("Writable Blu-ray disc"),
|
|
- N_("Rewritable Blu-ray disc"),
|
|
- NULL };
|
|
-
|
|
-
|
|
-typedef struct _BraseroMediumPrivate BraseroMediumPrivate;
|
|
-struct _BraseroMediumPrivate
|
|
-{
|
|
- gint retry_id;
|
|
-
|
|
- GSList * tracks;
|
|
-
|
|
- const gchar *type;
|
|
- const gchar *icon;
|
|
-
|
|
- gint max_rd;
|
|
- gint max_wrt;
|
|
-
|
|
- gint *rd_speeds;
|
|
- gint *wr_speeds;
|
|
-
|
|
- gint64 block_num;
|
|
- gint64 block_size;
|
|
-
|
|
- guint64 next_wr_add;
|
|
- BraseroMedia info;
|
|
- NautilusBurnDrive * drive;
|
|
-};
|
|
-
|
|
-#define BRASERO_MEDIUM_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_MEDIUM, BraseroMediumPrivate))
|
|
-
|
|
-/**
|
|
- * Try to open the drive exclusively but don't block; if drive can't be opened
|
|
- * exclusively then retry every second until we're shut or the drive state
|
|
- * changes to not busy.
|
|
- * No exclusive at the moment since when the medium is mounted we can't use excl
|
|
- */
|
|
-
|
|
-#define OPEN_FLAGS O_RDONLY /*|O_EXCL */|O_NONBLOCK
|
|
-#define BUSY_RETRY_TIME 1000
|
|
-
|
|
-enum
|
|
-{
|
|
- PROP_0,
|
|
- PROP_DRIVE
|
|
-};
|
|
-
|
|
-static GObjectClass* parent_class = NULL;
|
|
-
|
|
-const gchar *
|
|
-brasero_medium_get_type_string (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return priv->type;
|
|
-}
|
|
-
|
|
-const gchar *
|
|
-brasero_medium_get_icon (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return priv->icon;
|
|
-}
|
|
-
|
|
-BraseroMedia
|
|
-brasero_medium_get_status (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return priv->info;
|
|
-}
|
|
-
|
|
-GSList *
|
|
-brasero_medium_get_tracks (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return g_slist_copy (priv->tracks);
|
|
-}
|
|
-
|
|
-gboolean
|
|
-brasero_medium_get_last_data_track_address (BraseroMedium *medium,
|
|
- gint64 *byte,
|
|
- gint64 *sector)
|
|
-{
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track = NULL;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *current;
|
|
-
|
|
- current = iter->data;
|
|
- if (current->type & BRASERO_MEDIUM_TRACK_DATA)
|
|
- track = current;
|
|
- }
|
|
-
|
|
- if (!track) {
|
|
- if (byte)
|
|
- *byte = -1;
|
|
- if (sector)
|
|
- *sector = -1;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (byte)
|
|
- *byte = track->start * priv->block_size;
|
|
-
|
|
- if (sector)
|
|
- *sector = track->start;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-gboolean
|
|
-brasero_medium_get_last_data_track_space (BraseroMedium *medium,
|
|
- gint64 *size,
|
|
- gint64 *blocks)
|
|
-{
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track = NULL;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *current;
|
|
-
|
|
- current = iter->data;
|
|
- if (current->type & BRASERO_MEDIUM_TRACK_DATA)
|
|
- track = current;
|
|
- }
|
|
-
|
|
- if (!track) {
|
|
- if (size)
|
|
- *size = -1;
|
|
- if (blocks)
|
|
- *blocks = -1;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (size)
|
|
- *size = track->blocks_num * priv->block_size;
|
|
- if (blocks)
|
|
- *blocks = track->blocks_num;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-guint
|
|
-brasero_medium_get_track_num (BraseroMedium *medium)
|
|
-{
|
|
- guint retval = 0;
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *current;
|
|
-
|
|
- current = iter->data;
|
|
- if (current->type & BRASERO_MEDIUM_TRACK_LEADOUT)
|
|
- break;
|
|
-
|
|
- retval ++;
|
|
- }
|
|
-
|
|
- return retval;
|
|
-}
|
|
-
|
|
-static BraseroMediumTrack *
|
|
-brasero_medium_get_track (BraseroMedium *medium,
|
|
- guint num)
|
|
-{
|
|
- guint i = 1;
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *current;
|
|
-
|
|
- current = iter->data;
|
|
- if (current->type == BRASERO_MEDIUM_TRACK_LEADOUT)
|
|
- break;
|
|
-
|
|
- if (i == num)
|
|
- return current;
|
|
-
|
|
- i++;
|
|
- }
|
|
-
|
|
- return NULL;
|
|
-}
|
|
-
|
|
-gboolean
|
|
-brasero_medium_get_track_space (BraseroMedium *medium,
|
|
- guint num,
|
|
- gint64 *size,
|
|
- gint64 *blocks)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- track = brasero_medium_get_track (medium, num);
|
|
- if (!track) {
|
|
- if (size)
|
|
- *size = -1;
|
|
- if (blocks)
|
|
- *blocks = -1;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (size)
|
|
- *size = track->blocks_num * priv->block_size;
|
|
- if (blocks)
|
|
- *blocks = track->blocks_num;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-gboolean
|
|
-brasero_medium_get_track_address (BraseroMedium *medium,
|
|
- guint num,
|
|
- gint64 *byte,
|
|
- gint64 *sector)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- track = brasero_medium_get_track (medium, num);
|
|
- if (!track) {
|
|
- if (byte)
|
|
- *byte = -1;
|
|
- if (sector)
|
|
- *sector = -1;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (byte)
|
|
- *byte = track->start * priv->block_size;
|
|
- if (sector)
|
|
- *sector = track->start;
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-gint64
|
|
-brasero_medium_get_next_writable_address (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return priv->next_wr_add;
|
|
-}
|
|
-
|
|
-gint64
|
|
-brasero_medium_get_max_write_speed (BraseroMedium *medium)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
- return priv->max_wrt * 1024;
|
|
-}
|
|
-
|
|
-/**
|
|
- * NOTEs about the following functions:
|
|
- * for all closed media (including ROM types) capacity == size of data and
|
|
- * should be the size of all data on the disc, free space is 0
|
|
- * for all blank -R types capacity == free space and size of data == 0
|
|
- * for all multisession -R types capacity == free space since having the real
|
|
- * capacity of the media would be useless as we can only use this type of media
|
|
- * to append more data
|
|
- * for all -RW types capacity = free space + size of data. Here they can be
|
|
- * appended (use free space) or rewritten (whole capacity).
|
|
- *
|
|
- * Usually:
|
|
- * the free space is the size of the leadout track
|
|
- * the size of data is the sum of track sizes (excluding leadout)
|
|
- * the capacity depends on the media:
|
|
- * for closed discs == sum of track sizes
|
|
- * for multisession discs == free space (leadout size)
|
|
- * for blank discs == (free space) leadout size
|
|
- * for rewritable/blank == use SCSI functions to get capacity (see below)
|
|
- *
|
|
- * In fact we should really need the size of data in DVD+/-RW cases since the
|
|
- * session is always equal to the size of the disc.
|
|
- */
|
|
-
|
|
-void
|
|
-brasero_medium_get_data_size (BraseroMedium *medium,
|
|
- gint64 *size,
|
|
- gint64 *blocks)
|
|
-{
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track = NULL;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- if (!priv->tracks) {
|
|
- /* that's probably because it wasn't possible to retrieve info */
|
|
- if (size)
|
|
- *size = 0;
|
|
-
|
|
- if (blocks)
|
|
- *blocks = 0;
|
|
-
|
|
- return;
|
|
- }
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *tmp;
|
|
-
|
|
- tmp = iter->data;
|
|
- if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT)
|
|
- break;
|
|
-
|
|
- track = iter->data;
|
|
- }
|
|
-
|
|
- if (size)
|
|
- *size = track ? (track->start + track->blocks_num) * priv->block_size: 0;
|
|
-
|
|
- if (blocks)
|
|
- *blocks = track ? track->start + track->blocks_num: 0;
|
|
-}
|
|
-
|
|
-void
|
|
-brasero_medium_get_free_space (BraseroMedium *medium,
|
|
- gint64 *size,
|
|
- gint64 *blocks)
|
|
-{
|
|
- GSList *iter;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroMediumTrack *track = NULL;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- if (!priv->tracks) {
|
|
- /* that's probably because it wasn't possible to retrieve info.
|
|
- * maybe it also happens with unformatted DVD+RW */
|
|
-
|
|
- if (priv->info & BRASERO_MEDIUM_CLOSED) {
|
|
- if (size)
|
|
- *size = 0;
|
|
-
|
|
- if (blocks)
|
|
- *blocks = 0;
|
|
- }
|
|
- else {
|
|
- if (size)
|
|
- *size = priv->block_num * priv->block_size;
|
|
-
|
|
- if (blocks)
|
|
- *blocks = priv->block_num;
|
|
- }
|
|
-
|
|
- return;
|
|
- }
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *tmp;
|
|
-
|
|
- tmp = iter->data;
|
|
- if (tmp->type == BRASERO_MEDIUM_TRACK_LEADOUT) {
|
|
- track = iter->data;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (size) {
|
|
- if (!track) {
|
|
- /* No leadout was found so the disc is probably closed:
|
|
- * no free space left. */
|
|
- *size = 0;
|
|
- }
|
|
- else if (track->blocks_num <= 0)
|
|
- *size = (priv->block_num - track->start) * priv->block_size;
|
|
- else
|
|
- *size = track->blocks_num * priv->block_size;
|
|
- }
|
|
-
|
|
- if (blocks) {
|
|
- if (!track) {
|
|
- /* No leadout was found so the disc is probably closed:
|
|
- * no free space left. */
|
|
- *blocks = 0;
|
|
- }
|
|
- else if (track->blocks_num <= 0)
|
|
- *blocks = priv->block_num - track->blocks_num;
|
|
- else
|
|
- *blocks = track->blocks_num;
|
|
- }
|
|
-}
|
|
-
|
|
-void
|
|
-brasero_medium_get_capacity (BraseroMedium *medium,
|
|
- gint64 *size,
|
|
- gint64 *blocks)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (medium);
|
|
-
|
|
- if (priv->info & BRASERO_MEDIUM_REWRITABLE) {
|
|
- if (size)
|
|
- *size = priv->block_num * priv->block_size;
|
|
-
|
|
- if (blocks)
|
|
- *blocks = priv->block_num;
|
|
- }
|
|
- else if (priv->info & BRASERO_MEDIUM_CLOSED)
|
|
- brasero_medium_get_data_size (medium, size, blocks);
|
|
- else
|
|
- brasero_medium_get_free_space (medium, size, blocks);
|
|
-}
|
|
-
|
|
-/**
|
|
- * Function to retrieve the capacity of a media
|
|
- */
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_capacity_CD_RW (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiAtipData *atip_data = NULL;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- int size = 0;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving capacity from atip");
|
|
-
|
|
- result = brasero_mmc1_read_atip (fd,
|
|
- &atip_data,
|
|
- &size,
|
|
- NULL);
|
|
-
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BRASERO_BURN_LOG ("READ ATIP failed (scsi error)");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- /* check the size of the structure: it must be at least 16 bytes long */
|
|
- if (size < 16) {
|
|
- if (size)
|
|
- g_free (atip_data);
|
|
-
|
|
- BRASERO_BURN_LOG ("READ ATIP failed (wrong size)");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- priv->block_num = BRASERO_MSF_TO_LBA (atip_data->desc->leadout_mn,
|
|
- atip_data->desc->leadout_sec,
|
|
- atip_data->desc->leadout_frame);
|
|
- g_free (atip_data);
|
|
-
|
|
- BRASERO_BURN_LOG ("Format capacity %lli %lli",
|
|
- priv->block_num,
|
|
- priv->block_size);
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_capacity_DVD_RW (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiFormatCapacitiesHdr *hdr = NULL;
|
|
- BraseroScsiMaxCapacityDesc *current;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- gint size;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving format capacity");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- result = brasero_mmc2_read_format_capacities (fd,
|
|
- &hdr,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (hdr);
|
|
-
|
|
- BRASERO_BURN_LOG ("READ FORMAT CAPACITIES failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- current = hdr->max_caps;
|
|
-
|
|
- /* see if the media is already formatted */
|
|
- if (current->type != BRASERO_SCSI_DESC_FORMATTED) {
|
|
- int i, max;
|
|
- BraseroScsiFormattableCapacityDesc *desc;
|
|
-
|
|
- max = (hdr->len -
|
|
- sizeof (BraseroScsiMaxCapacityDesc)) /
|
|
- sizeof (BraseroScsiFormattableCapacityDesc);
|
|
-
|
|
- desc = hdr->desc;
|
|
- for (i = 0; i < max; i ++, desc ++) {
|
|
- /* search for the correct descriptor */
|
|
- if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)) {
|
|
- if (desc->format_type == BRASERO_SCSI_DVDRW_PLUS) {
|
|
- priv->block_num = BRASERO_GET_32 (desc->blocks_num);
|
|
- priv->block_size = BRASERO_GET_24 (desc->type_param);
|
|
-
|
|
- /* that can happen */
|
|
- if (!priv->block_size)
|
|
- priv->block_size = 2048;
|
|
- break;
|
|
- }
|
|
- }
|
|
- else if (desc->format_type == BRASERO_SCSI_BLOCK_SIZE_DEFAULT_AND_DB) {
|
|
- priv->block_num = BRASERO_GET_32 (desc->blocks_num);
|
|
- priv->block_size = BRASERO_GET_24 (desc->type_param);
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
- else {
|
|
- priv->block_num = BRASERO_GET_32 (current->blocks_num);
|
|
- priv->block_size = BRASERO_GET_24 (current->block_size);
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Format capacity %lli %lli",
|
|
- priv->block_num,
|
|
- priv->block_size);
|
|
-
|
|
- g_free (hdr);
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_capacity_by_type (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- priv->block_size = 2048;
|
|
-
|
|
- if (!(priv->info & BRASERO_MEDIUM_REWRITABLE))
|
|
- return BRASERO_BURN_OK;
|
|
-
|
|
- if (priv->info & BRASERO_MEDIUM_CD)
|
|
- brasero_medium_get_capacity_CD_RW (self, fd, code);
|
|
- else
|
|
- brasero_medium_get_capacity_DVD_RW (self, fd, code);
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Functions to retrieve the speed
|
|
- */
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_speed_mmc3 (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- int size;
|
|
- int num_desc, i;
|
|
- gint max_rd, max_wrt;
|
|
- BraseroScsiResult result;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiWrtSpdDesc *desc;
|
|
- BraseroScsiGetPerfData *wrt_perf = NULL;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving speed (Get Performance)");
|
|
-
|
|
- /* NOTE: this only work if there is RT streaming feature with
|
|
- * wspd bit set to 1. At least an MMC3 drive. */
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- result = brasero_mmc3_get_performance_wrt_spd_desc (fd,
|
|
- &wrt_perf,
|
|
- &size,
|
|
- code);
|
|
-
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (wrt_perf);
|
|
-
|
|
- BRASERO_BURN_LOG ("GET PERFORMANCE failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- num_desc = (size - sizeof (BraseroScsiGetPerfHdr)) /
|
|
- sizeof (BraseroScsiWrtSpdDesc);
|
|
-
|
|
- if (num_desc <= 0)
|
|
- goto end;
|
|
-
|
|
- priv->rd_speeds = g_new0 (gint, num_desc + 1);
|
|
- priv->wr_speeds = g_new0 (gint, num_desc + 1);
|
|
-
|
|
- max_rd = 0;
|
|
- max_wrt = 0;
|
|
-
|
|
- desc = (BraseroScsiWrtSpdDesc*) &wrt_perf->data;
|
|
- for (i = 0; i < num_desc; i ++, desc ++) {
|
|
- priv->rd_speeds [i] = BRASERO_GET_32 (desc->rd_speed);
|
|
- priv->wr_speeds [i] = BRASERO_GET_32 (desc->wr_speed);
|
|
-
|
|
- max_rd = MAX (max_rd, priv->rd_speeds [i]);
|
|
- max_wrt = MAX (max_wrt, priv->wr_speeds [i]);
|
|
- }
|
|
-
|
|
- priv->max_rd = max_rd;
|
|
- priv->max_wrt = max_wrt;
|
|
-
|
|
-end:
|
|
-
|
|
- g_free (wrt_perf);
|
|
-
|
|
- /* strangely there are so drives (I know one case) which support this
|
|
- * function but don't report any speed. So if our top speed is 0 then
|
|
- * use the other way to get the speed. It was a Teac */
|
|
- if (!priv->max_wrt)
|
|
- return BRASERO_BURN_ERR;
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_page_2A_write_speed_desc (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiStatusPage *page_2A = NULL;
|
|
- BraseroScsiStatusWrSpdDesc *desc;
|
|
- BraseroScsiModeData *data = NULL;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- gint desc_num, i;
|
|
- gint max_wrt = 0;
|
|
- gint max_num;
|
|
- int size = 0;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving speed (2A speeds)");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- result = brasero_spc1_mode_sense_get_page (fd,
|
|
- BRASERO_SPC_PAGE_STATUS,
|
|
- &data,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (data);
|
|
-
|
|
- BRASERO_BURN_LOG ("MODE SENSE failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- page_2A = (BraseroScsiStatusPage *) &data->page;
|
|
-
|
|
- /* FIXME: the following is not necessarily true */
|
|
- if (size < sizeof (BraseroScsiStatusPage)) {
|
|
- g_free (data);
|
|
-
|
|
- BRASERO_BURN_LOG ("wrong size in page");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- desc_num = BRASERO_GET_16 (page_2A->wr_speed_desc_num);
|
|
- max_num = size -
|
|
- sizeof (BraseroScsiStatusPage) -
|
|
- sizeof (BraseroScsiModeHdr);
|
|
- max_num /= sizeof (BraseroScsiWrtSpdDesc);
|
|
-
|
|
- if (max_num < 0)
|
|
- max_num = 0;
|
|
-
|
|
- if (desc_num > max_num)
|
|
- desc_num = max_num;
|
|
-
|
|
- priv->wr_speeds = g_new0 (gint, desc_num + 1);
|
|
- desc = page_2A->wr_spd_desc;
|
|
- for (i = 0; i < desc_num; i ++, desc ++) {
|
|
- priv->wr_speeds [i] = BRASERO_GET_16 (desc->speed);
|
|
- max_wrt = MAX (max_wrt, priv->wr_speeds [i]);
|
|
- }
|
|
-
|
|
- if (!max_wrt)
|
|
- priv->max_wrt = BRASERO_GET_16 (page_2A->wr_max_speed);
|
|
- else
|
|
- priv->max_wrt = max_wrt;
|
|
-
|
|
- priv->max_rd = BRASERO_GET_16 (page_2A->rd_max_speed);
|
|
- g_free (data);
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_page_2A_max_speed (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiStatusPage *page_2A = NULL;
|
|
- BraseroScsiModeData *data = NULL;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- int size = 0;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving speed (2A max)");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- result = brasero_spc1_mode_sense_get_page (fd,
|
|
- BRASERO_SPC_PAGE_STATUS,
|
|
- &data,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (data);
|
|
-
|
|
- BRASERO_BURN_LOG ("MODE SENSE failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- page_2A = (BraseroScsiStatusPage *) &data->page;
|
|
-
|
|
- if (size < 0x14) {
|
|
- g_free (data);
|
|
-
|
|
- BRASERO_BURN_LOG ("wrong page size");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- priv->max_rd = BRASERO_GET_16 (page_2A->rd_max_speed);
|
|
- priv->max_wrt = BRASERO_GET_16 (page_2A->wr_max_speed);
|
|
-
|
|
- g_free (data);
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_medium_type (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiGetConfigHdr *hdr = NULL;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- int size;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving media profile");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- result = brasero_mmc2_get_configuration_feature (fd,
|
|
- BRASERO_SCSI_FEAT_REAL_TIME_STREAM,
|
|
- &hdr,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BraseroScsiAtipData *data = NULL;
|
|
- int size = 0;
|
|
-
|
|
- BRASERO_BURN_LOG ("GET CONFIGURATION failed");
|
|
-
|
|
- /* This could be a MMC1 drive since this command was
|
|
- * introduced in MMC2 and is supported onward. So it
|
|
- * has to be a CD (R/RW). The rest of the information
|
|
- * will be provided by read_disc_information. */
|
|
-
|
|
- /* The only thing here left to determine is if that's a WRITABLE
|
|
- * or a REWRITABLE. To determine that information, we need to
|
|
- * read TocPmaAtip. It if fails that's a ROM, if it succeeds.
|
|
- * No need to set error code since we consider that it's a ROM
|
|
- * if a failure happens. */
|
|
- result = brasero_mmc1_read_atip (fd,
|
|
- &data,
|
|
- &size,
|
|
- NULL);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- /* CDROM */
|
|
- priv->info = BRASERO_MEDIUM_CDROM;
|
|
- priv->type = types [1];
|
|
- priv->icon = icons [1];
|
|
- }
|
|
- else {
|
|
- /* check the size of the structure: it must be at least 8 bytes long */
|
|
- if (size < 8) {
|
|
- if (size)
|
|
- g_free (data);
|
|
-
|
|
- BRASERO_BURN_LOG ("READ ATIP failed (wrong size)");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- if (data->desc->erasable) {
|
|
- /* CDRW */
|
|
- priv->info = BRASERO_MEDIUM_CDRW;
|
|
- priv->type = types [3];
|
|
- priv->icon = icons [3];
|
|
- }
|
|
- else {
|
|
- /* CDR */
|
|
- priv->info = BRASERO_MEDIUM_CDR;
|
|
- priv->type = types [2];
|
|
- priv->icon = icons [2];
|
|
- }
|
|
-
|
|
- g_free (data);
|
|
- }
|
|
-
|
|
- /* retrieve the speed */
|
|
- result = brasero_medium_get_page_2A_max_speed (self,
|
|
- fd,
|
|
- code);
|
|
- return result;
|
|
- }
|
|
-
|
|
- switch (BRASERO_GET_16 (hdr->current_profile)) {
|
|
- case BRASERO_SCSI_PROF_CDROM:
|
|
- priv->info = BRASERO_MEDIUM_CDROM;
|
|
- priv->type = types [1];
|
|
- priv->icon = icons [1];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_CDR:
|
|
- priv->info = BRASERO_MEDIUM_CDR;
|
|
- priv->type = types [2];
|
|
- priv->icon = icons [2];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_CDRW:
|
|
- priv->info = BRASERO_MEDIUM_CDRW;
|
|
- priv->type = types [3];
|
|
- priv->icon = icons [3];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_ROM:
|
|
- priv->info = BRASERO_MEDIUM_DVD_ROM;
|
|
- priv->type = types [4];
|
|
- priv->icon = icons [4];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_R:
|
|
- priv->info = BRASERO_MEDIUM_DVDR;
|
|
- priv->type = types [5];
|
|
- priv->icon = icons [5];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_RW_RESTRICTED:
|
|
- priv->info = BRASERO_MEDIUM_DVDRW_RESTRICTED;
|
|
- priv->type = types [6];
|
|
- priv->icon = icons [6];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_RW_SEQUENTIAL:
|
|
- priv->info = BRASERO_MEDIUM_DVDRW;
|
|
- priv->type = types [6];
|
|
- priv->icon = icons [6];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_R_PLUS:
|
|
- priv->info = BRASERO_MEDIUM_DVDR_PLUS;
|
|
- priv->type = types [7];
|
|
- priv->icon = icons [7];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_RW_PLUS:
|
|
- priv->info = BRASERO_MEDIUM_DVDRW_PLUS;
|
|
- priv->type = types [8];
|
|
- priv->icon = icons [7];
|
|
- break;
|
|
-
|
|
- /* WARNING: these types are recognized, no more */
|
|
- case BRASERO_SCSI_PROF_DVD_R_PLUS_DL:
|
|
- priv->info = BRASERO_MEDIUM_DVDR_PLUS_DL;
|
|
- priv->type = types [9];
|
|
- priv->icon = icons [7];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_RW_PLUS_DL:
|
|
- priv->info = BRASERO_MEDIUM_DVDRW_PLUS_DL;
|
|
- priv->type = types [10];
|
|
- priv->icon = icons [7];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_R_DL_SEQUENTIAL:
|
|
- priv->info = BRASERO_MEDIUM_DVDR_DL;
|
|
- priv->type = types [11];
|
|
- priv->icon = icons [5];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_R_DL_JUMP:
|
|
- priv->info = BRASERO_MEDIUM_DVDR_JUMP_DL;
|
|
- priv->type = types [11];
|
|
- priv->icon = icons [5];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_DVD_RAM:
|
|
- priv->info = BRASERO_MEDIUM_DVD_RAM;
|
|
- priv->type = types [12];
|
|
- priv->icon = icons [8];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_BD_ROM:
|
|
- priv->info = BRASERO_MEDIUM_BD_ROM;
|
|
- priv->type = types [13];
|
|
- priv->icon = icons [4];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_BR_R_SEQUENTIAL:
|
|
- priv->info = BRASERO_MEDIUM_BDR;
|
|
- priv->type = types [14];
|
|
- priv->icon = icons [5];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_BR_R_RANDOM:
|
|
- priv->info = BRASERO_MEDIUM_BDR_RANDOM;
|
|
- priv->type = types [14];
|
|
- priv->icon = icons [5];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_BD_RW:
|
|
- priv->info = BRASERO_MEDIUM_BDRW;
|
|
- priv->type = types [15];
|
|
- priv->icon = icons [6];
|
|
- break;
|
|
-
|
|
- case BRASERO_SCSI_PROF_NON_REMOVABLE:
|
|
- case BRASERO_SCSI_PROF_REMOVABLE:
|
|
- case BRASERO_SCSI_PROF_MO_ERASABLE:
|
|
- case BRASERO_SCSI_PROF_MO_WRITE_ONCE:
|
|
- case BRASERO_SCSI_PROF_MO_ADVANCED_STORAGE:
|
|
- case BRASERO_SCSI_PROF_DDCD_ROM:
|
|
- case BRASERO_SCSI_PROF_DDCD_R:
|
|
- case BRASERO_SCSI_PROF_DDCD_RW:
|
|
- case BRASERO_SCSI_PROF_HD_DVD_ROM:
|
|
- case BRASERO_SCSI_PROF_HD_DVD_R:
|
|
- case BRASERO_SCSI_PROF_HD_DVD_RAM:
|
|
- priv->info = BRASERO_MEDIUM_UNSUPPORTED;
|
|
- priv->icon = icons [0];
|
|
- g_free (hdr);
|
|
- return BRASERO_BURN_NOT_SUPPORTED;
|
|
- }
|
|
-
|
|
- /* try all SCSI functions to get write/read speeds in order */
|
|
- if (hdr->desc->add_len >= sizeof (BraseroScsiRTStreamDesc)) {
|
|
- BraseroScsiRTStreamDesc *stream;
|
|
-
|
|
- /* means it's at least an MMC3 drive */
|
|
- stream = (BraseroScsiRTStreamDesc *) hdr->desc->data;
|
|
- if (stream->wrt_spd) {
|
|
- result = brasero_medium_get_speed_mmc3 (self, fd, code);
|
|
- if (result == BRASERO_BURN_OK)
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (stream->mp2a) {
|
|
- result = brasero_medium_get_page_2A_write_speed_desc (self, fd, code);
|
|
- if (result == BRASERO_BURN_OK)
|
|
- goto end;
|
|
- }
|
|
- }
|
|
-
|
|
- /* fallback for speeds */
|
|
- result = brasero_medium_get_page_2A_max_speed (self, fd, code);
|
|
-
|
|
-end:
|
|
-
|
|
- g_free (hdr);
|
|
-
|
|
- if (result != BRASERO_BURN_OK)
|
|
- return result;
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_css_feature (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiGetConfigHdr *hdr = NULL;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- int size;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- BRASERO_BURN_LOG ("Testing for Css encrypted media");
|
|
- result = brasero_mmc2_get_configuration_feature (fd,
|
|
- BRASERO_SCSI_FEAT_DVD_CSS,
|
|
- &hdr,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (hdr);
|
|
-
|
|
- BRASERO_BURN_LOG ("GET CONFIGURATION failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- if (hdr->desc->add_len < sizeof (BraseroScsiDVDCssDesc)) {
|
|
- g_free (hdr);
|
|
- return BRASERO_BURN_OK;
|
|
- }
|
|
-
|
|
- /* here we just need to see if this feature is current or not */
|
|
- if (hdr->desc->current) {
|
|
- priv->info |= BRASERO_MEDIUM_PROTECTED;
|
|
- BRASERO_BURN_LOG ("media is Css protected");
|
|
- }
|
|
-
|
|
- g_free (hdr);
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-/**
|
|
- * Functions to get information about disc contents
|
|
- */
|
|
-
|
|
-static void
|
|
-brasero_medium_set_track_type (BraseroMedium *self,
|
|
- BraseroMediumTrack *track,
|
|
- guchar control)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- if (control & BRASERO_SCSI_TRACK_COPY)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_COPY;
|
|
-
|
|
- if (!(control & BRASERO_SCSI_TRACK_DATA)) {
|
|
- track->type |= BRASERO_MEDIUM_TRACK_AUDIO;
|
|
- priv->info |= BRASERO_MEDIUM_HAS_AUDIO;
|
|
-
|
|
- if (control & BRASERO_SCSI_TRACK_PREEMP)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_PREEMP;
|
|
-
|
|
- if (control & BRASERO_SCSI_TRACK_4_CHANNELS)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_4_CHANNELS;
|
|
- }
|
|
- else {
|
|
- track->type |= BRASERO_MEDIUM_TRACK_DATA;
|
|
- priv->info |= BRASERO_MEDIUM_HAS_DATA;
|
|
-
|
|
- if (control & BRASERO_SCSI_TRACK_DATA_INCREMENTAL)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_INCREMENTAL;
|
|
- }
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_track_volume_size (BraseroMedium *self,
|
|
- BraseroMediumTrack *track,
|
|
- int fd)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroBurnResult res;
|
|
- GError *error = NULL;
|
|
- gint64 nb_blocks;
|
|
-
|
|
- if (!track)
|
|
- return BRASERO_BURN_ERR;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- /* This is a special case. For DVD+RW and DVD-RW in restricted
|
|
- * mode, there is only one session that takes the whole disc size
|
|
- * once formatted. That doesn't necessarily means they have data
|
|
- * Note also that they are reported as complete though you can
|
|
- * still add data (with growisofs). It is nevertheless on the
|
|
- * condition that the fs is valid.
|
|
- * So we check if their first and only volume is valid.
|
|
- * That's also used when the track size is reported a 300 Kio
|
|
- * see below */
|
|
- res = brasero_volume_get_size_fd (fd,
|
|
- track->start,
|
|
- &nb_blocks,
|
|
- NULL);
|
|
- if (!res) {
|
|
- BRASERO_BURN_LOG ("Failed to retrieve the volume size: %s",
|
|
- error && error->message ?
|
|
- error->message:"unknown error");
|
|
-
|
|
- if (error)
|
|
- g_error_free (error);
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- track->blocks_num = nb_blocks;
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_track_get_info (BraseroMedium *self,
|
|
- BraseroMediumTrack *track,
|
|
- int track_num,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- BraseroScsiTrackInfo track_info;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiResult result;
|
|
- int size;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving track information for %i", track_num);
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- /* at this point we know the type of the disc that's why we set the
|
|
- * size according to this type. That may help to avoid outrange address
|
|
- * errors. */
|
|
- if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DL|BRASERO_MEDIUM_WRITABLE))
|
|
- size = 48;
|
|
- else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_PLUS|BRASERO_MEDIUM_WRITABLE))
|
|
- size = 40;
|
|
- else
|
|
- size = 36;
|
|
-
|
|
- result = brasero_mmc1_read_track_info (fd,
|
|
- track_num,
|
|
- &track_info,
|
|
- &size,
|
|
- code);
|
|
-
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BRASERO_BURN_LOG ("READ TRACK INFO failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- track->blocks_num = BRASERO_GET_32 (track_info.track_size);
|
|
- track->session = BRASERO_SCSI_SESSION_NUM (track_info);
|
|
-
|
|
- /* Now here is a potential bug: we can write tracks (data or not)
|
|
- * shorter than 300 Kio /2 sec but they will be padded to reach this
|
|
- * floor value. That means that is blocks_num is 300 blocks that may
|
|
- * mean that the data length on the track is actually shorter.
|
|
- * So we read the volume descriptor. If it works, good otherwise
|
|
- * use the old value.
|
|
- * That's important for checksuming to have a perfect account of the
|
|
- * data size. */
|
|
- if (track->blocks_num <= 300) {
|
|
- BRASERO_BURN_LOG ("300 sectors size. Checking for real size");
|
|
- brasero_medium_track_volume_size (self, track, fd);
|
|
- }
|
|
-
|
|
- if (track_info.next_wrt_address_valid)
|
|
- priv->next_wr_add = BRASERO_GET_32 (track_info.next_wrt_address);
|
|
-
|
|
- BRASERO_BURN_LOG ("Track %i (session %i): type = %i start = %llu size = %llu",
|
|
- track_num,
|
|
- track->session,
|
|
- track->type,
|
|
- track->start,
|
|
- track->blocks_num);
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-/**
|
|
- * return :
|
|
- * 0 when it's not possible to determine (fallback to formatted toc)
|
|
- * -1 for BCD
|
|
- * 1 for HEX */
|
|
-static guint
|
|
-brasero_medium_check_BCD_use (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiRawTocDesc *desc,
|
|
- guint num,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- guint i;
|
|
- int size;
|
|
- guint leadout = 0;
|
|
- guint track_num = 0;
|
|
- gboolean use_BCD = TRUE;
|
|
- gboolean use_HEX = TRUE;
|
|
- BraseroScsiResult result;
|
|
- BraseroScsiTrackInfo track_info;
|
|
- guint start_BCD, start_LBA, track_start;
|
|
-
|
|
- /* first check if all values are valid BCD numbers in the descriptors */
|
|
- for (i = 0; i < num; i++) {
|
|
- if (desc [i].adr == 1 && desc [i].point <= BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) {
|
|
- if (!BRASERO_IS_BCD_VALID (desc [i].p_min)
|
|
- || !BRASERO_IS_BCD_VALID (desc [i].p_sec)
|
|
- || !BRASERO_IS_BCD_VALID (desc [i].p_frame)) {
|
|
- use_BCD = FALSE;
|
|
- break;
|
|
- }
|
|
- }
|
|
- else if (desc [i].point == BRASERO_SCSI_Q_SUB_CHANNEL_LEADOUT_START) {
|
|
- if (!BRASERO_IS_BCD_VALID (desc [i].p_min)
|
|
- || !BRASERO_IS_BCD_VALID (desc [i].p_sec)
|
|
- || !BRASERO_IS_BCD_VALID (desc [i].p_frame)) {
|
|
- use_BCD = FALSE;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* then check if there are valid Hex values */
|
|
- for (i = 0; i < num; i++) {
|
|
- if (desc [i].adr != 1 || desc [i].point > BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START)
|
|
- continue;
|
|
-
|
|
- if (desc [i].p_min > 99
|
|
- || desc [i].p_sec > 59
|
|
- || desc [i].p_frame > 74) {
|
|
- use_HEX = FALSE;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (use_BCD != use_HEX) {
|
|
- if (use_BCD)
|
|
- return -1;
|
|
-
|
|
- return 1;
|
|
- }
|
|
-
|
|
- /* To check if the drive uses BCD values or HEX values we ask for the
|
|
- * track information that contains also the start for the track but in
|
|
- * HEX values. If values are the same then it works. */
|
|
-
|
|
- /* NOTE: there could be another way to do it: get first track, in LBA
|
|
- * and BCD it must be 150. */
|
|
-
|
|
- /* First find the first track and get track start address in BCD */
|
|
- BRASERO_BURN_LOG ("Retrieving track information to determine number format");
|
|
-
|
|
- for (i = 0; i < num; i++) {
|
|
- if (desc [i].adr == BRASERO_SCSI_Q_SUB_CHANNEL_LEADIN_MODE5
|
|
- && desc [i].point == BRASERO_SCSI_Q_SUB_CHANNEL_MULTI_NEXT_SESSION) {
|
|
- /* store the leadout number just in case */
|
|
- leadout = i;
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (desc [i].adr != 1 || desc [i].point > BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START)
|
|
- continue;
|
|
-
|
|
- track_num ++;
|
|
-
|
|
- start_BCD = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (desc [i].p_min),
|
|
- BRASERO_GET_BCD (desc [i].p_sec),
|
|
- BRASERO_GET_BCD (desc [i].p_frame));
|
|
-
|
|
- start_LBA = BRASERO_MSF_TO_LBA (desc [i].p_min,
|
|
- desc [i].p_sec,
|
|
- desc [i].p_frame);
|
|
-
|
|
- BRASERO_BURN_LOG ("Comparing to track information from READ TRACK INFO for track %i", track_num);
|
|
-
|
|
- size = 36;
|
|
- start_LBA -= 150;
|
|
- start_BCD -= 150;
|
|
-
|
|
- result = brasero_mmc1_read_track_info (fd,
|
|
- track_num,
|
|
- &track_info,
|
|
- &size,
|
|
- code);
|
|
-
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BRASERO_BURN_LOG ("READ TRACK INFO failed");
|
|
- /* Fallback to formatted toc */
|
|
- return 0;
|
|
- }
|
|
-
|
|
- track_start = BRASERO_GET_32 (track_info.start_lba);
|
|
- BRASERO_BURN_LOG ("comparing DCB %i and LBA %i to real start address %i",
|
|
- start_BCD, start_LBA, track_start);
|
|
-
|
|
- /* try to find a conclusive match */
|
|
- if (track_start == start_BCD && track_start != start_LBA)
|
|
- return -1;
|
|
-
|
|
- if (track_start == start_LBA && track_start != start_BCD)
|
|
- return 1;
|
|
- }
|
|
-
|
|
- /* Our last chance, the leadout.
|
|
- * NOTE: no need to remove 150 sectors here. */
|
|
- start_BCD = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (desc [leadout].min),
|
|
- BRASERO_GET_BCD (desc [leadout].sec),
|
|
- BRASERO_GET_BCD (desc [leadout].frame));
|
|
-
|
|
- start_LBA = BRASERO_MSF_TO_LBA (desc [leadout].min,
|
|
- desc [leadout].sec,
|
|
- desc [leadout].frame);
|
|
-
|
|
- BRASERO_BURN_LOG ("Comparing to track information from READ TRACK INFO for leadout");
|
|
-
|
|
- size = 36;
|
|
-
|
|
- /* leadout number is number of tracks + 1 */
|
|
- result = brasero_mmc1_read_track_info (fd,
|
|
- track_num + 1,
|
|
- &track_info,
|
|
- &size,
|
|
- code);
|
|
-
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BRASERO_BURN_LOG ("READ TRACK INFO failed for leadout");
|
|
- /* Fallback to formatted toc */
|
|
- return 0;
|
|
- }
|
|
-
|
|
- track_start = BRASERO_GET_32 (track_info.start_lba);
|
|
- BRASERO_BURN_LOG ("comparing DCB %i and LBA %i to real start address %i",
|
|
- start_BCD, start_LBA, track_start);
|
|
-
|
|
- /* try to find a conclusive match */
|
|
- if (track_start == start_BCD && track_start != start_LBA)
|
|
- return -1;
|
|
-
|
|
- if (track_start == start_LBA && track_start != start_BCD)
|
|
- return 1;
|
|
-
|
|
- /* fallback to formatted toc */
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/**
|
|
- * The reason why we use this perhaps more lengthy method is that with
|
|
- * multisession discs, the first track is reported to be two sectors shorter
|
|
- * than it should. As I don't know why and since the following works we use
|
|
- * this one. */
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_CD_sessions_info (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- gint use_bcd;
|
|
- GSList *iter;
|
|
- int num, i, size;
|
|
- gint leadout_start = 0;
|
|
- BraseroScsiResult result;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiRawTocDesc *desc;
|
|
- BraseroScsiRawTocData *toc = NULL;
|
|
-
|
|
- BRASERO_BURN_LOG ("Reading Raw Toc");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- size = 0;
|
|
- result = brasero_mmc1_read_toc_raw (fd,
|
|
- 0,
|
|
- &toc,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- BRASERO_BURN_LOG ("READ TOC failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- num = (size - sizeof (BraseroScsiRawTocData)) /
|
|
- sizeof (BraseroScsiRawTocDesc);
|
|
-
|
|
- BRASERO_BURN_LOG ("%i track(s) found", num);
|
|
-
|
|
- desc = toc->desc;
|
|
- use_bcd = brasero_medium_check_BCD_use (self, fd, desc, num, code);
|
|
- if (!use_bcd) {
|
|
- g_free (toc);
|
|
-
|
|
- BRASERO_BURN_LOG ("Fallback to formatted toc");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- if (use_bcd > 0)
|
|
- use_bcd = 0;
|
|
-
|
|
- if (use_bcd) {
|
|
- BRASERO_BURN_LOG ("Using BCD format");
|
|
- }
|
|
- else {
|
|
- BRASERO_BURN_LOG ("Using HEX format");
|
|
- }
|
|
-
|
|
- for (i = 0; i < num; i++, desc ++) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- track = NULL;
|
|
- if (desc->adr == 1 && desc->point <= BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) {
|
|
- track = g_new0 (BraseroMediumTrack, 1);
|
|
- track->session = desc->session_num;
|
|
-
|
|
- brasero_medium_set_track_type (self, track, desc->control);
|
|
- if (use_bcd)
|
|
- track->start = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (desc->p_min),
|
|
- BRASERO_GET_BCD (desc->p_sec),
|
|
- BRASERO_GET_BCD (desc->p_frame));
|
|
- else
|
|
- track->start = BRASERO_MSF_TO_LBA (desc->p_min,
|
|
- desc->p_sec,
|
|
- desc->p_frame);
|
|
-
|
|
- track->start -= 150;
|
|
-
|
|
- /* if there are tracks and the last previously added track is in
|
|
- * the same session then set the size */
|
|
- if (priv->tracks) {
|
|
- BraseroMediumTrack *last_track;
|
|
-
|
|
- last_track = priv->tracks->data;
|
|
- if (last_track->session == track->session)
|
|
- last_track->blocks_num = track->start - last_track->start;
|
|
- }
|
|
-
|
|
- priv->tracks = g_slist_prepend (priv->tracks, track);
|
|
- }
|
|
- else if (desc->point == BRASERO_SCSI_Q_SUB_CHANNEL_LEADOUT_START) {
|
|
- /* NOTE: the leadout session is first in the list. So if
|
|
- * we have tracks in the list set the last session track
|
|
- * size when we reach a new leadout (and therefore a new
|
|
- * session). */
|
|
-
|
|
- if (priv->tracks) {
|
|
- BraseroMediumTrack *last_track;
|
|
-
|
|
- last_track = priv->tracks->data;
|
|
- last_track->blocks_num = leadout_start - last_track->start;
|
|
- }
|
|
-
|
|
- if (use_bcd)
|
|
- leadout_start = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (desc->p_min),
|
|
- BRASERO_GET_BCD (desc->p_sec),
|
|
- BRASERO_GET_BCD (desc->p_frame));
|
|
- else
|
|
- leadout_start = BRASERO_MSF_TO_LBA (desc->p_min,
|
|
- desc->p_sec,
|
|
- desc->p_frame);
|
|
- leadout_start -= 150;
|
|
- }
|
|
- }
|
|
-
|
|
- if (priv->tracks) {
|
|
- BraseroMediumTrack *last_track;
|
|
-
|
|
- /* set the last found track size */
|
|
- last_track = priv->tracks->data;
|
|
- last_track->blocks_num = leadout_start - last_track->start;
|
|
- }
|
|
-
|
|
- /* Add a leadout */
|
|
- if (!(priv->info & BRASERO_MEDIUM_CLOSED)) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- /* we shouldn't request info on leadout if the disc is closed */
|
|
- track = g_new0 (BraseroMediumTrack, 1);
|
|
- priv->tracks = g_slist_prepend (priv->tracks, track);
|
|
- track->start = leadout_start;
|
|
- track->type = BRASERO_MEDIUM_TRACK_LEADOUT;
|
|
-
|
|
- brasero_medium_track_get_info (self, track, g_slist_length (priv->tracks), fd, code);
|
|
- }
|
|
-
|
|
- priv->tracks = g_slist_reverse (priv->tracks);
|
|
-
|
|
- for (iter = priv->tracks; iter; iter = iter->next) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- track = iter->data;
|
|
-
|
|
- /* check for tracks less that 300 sectors */
|
|
- if (track->blocks_num <= 300 && track->type != BRASERO_MEDIUM_TRACK_LEADOUT) {
|
|
- BRASERO_BURN_LOG ("300 sectors size. Checking for real size");
|
|
- brasero_medium_track_volume_size (self, track, fd);
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Track %i: type = %i start = %llu size = %llu",
|
|
- g_slist_index (priv->tracks, track),
|
|
- track->type,
|
|
- track->start,
|
|
- track->blocks_num);
|
|
- }
|
|
-
|
|
- g_free (toc);
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-/**
|
|
- * NOTE: for DVD-R multisession we lose 28688 blocks for each session
|
|
- * so the capacity is the addition of all session sizes + 28688 for each
|
|
- * For all multisession DVD-/+R and CDR-RW the remaining size is given
|
|
- * in the leadout. One exception though with DVD+/-RW.
|
|
- */
|
|
-
|
|
-static void
|
|
-brasero_medium_add_DVD_plus_RW_leadout (BraseroMedium *self,
|
|
- gint32 start)
|
|
-{
|
|
- BraseroMediumTrack *leadout;
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- leadout = g_new0 (BraseroMediumTrack, 1);
|
|
- priv->tracks = g_slist_append (priv->tracks, leadout);
|
|
-
|
|
- leadout->start = start;
|
|
- leadout->type = BRASERO_MEDIUM_TRACK_LEADOUT;
|
|
-
|
|
- /* we fabricate the leadout here. We don't really need one in
|
|
- * fact since it is always at the last sector whatever the
|
|
- * amount of data written. So we need in fact to read the file
|
|
- * system and get the last sector from it. Hopefully it won't be
|
|
- * buggy */
|
|
- priv->next_wr_add = 0;
|
|
-
|
|
- leadout->blocks_num = priv->block_num;
|
|
- if (g_slist_length (priv->tracks) > 1) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- track = priv->tracks->data;
|
|
- leadout->blocks_num -= ((track->blocks_num > 300) ? track->blocks_num : 300);
|
|
- }
|
|
- BRASERO_BURN_LOG ("Adding fabricated leadout start = %llu length = %llu",
|
|
- leadout->start,
|
|
- leadout->blocks_num);
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_sessions_info (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- int num, i, size;
|
|
- BraseroScsiResult result;
|
|
- BraseroScsiTocDesc *desc;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiFormattedTocData *toc = NULL;
|
|
-
|
|
- BRASERO_BURN_LOG ("Reading Toc");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- result = brasero_mmc1_read_toc_formatted (fd,
|
|
- 0,
|
|
- &toc,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (toc);
|
|
-
|
|
- BRASERO_BURN_LOG ("READ TOC failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- num = (size - sizeof (BraseroScsiFormattedTocData)) /
|
|
- sizeof (BraseroScsiTocDesc);
|
|
-
|
|
- BRASERO_BURN_LOG ("%i track(s) found", num);
|
|
-
|
|
- desc = toc->desc;
|
|
- for (i = 0; i < num; i ++, desc ++) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- if (desc->track_num == BRASERO_SCSI_TRACK_LEADOUT_START)
|
|
- break;
|
|
-
|
|
- track = g_new0 (BraseroMediumTrack, 1);
|
|
- priv->tracks = g_slist_prepend (priv->tracks, track);
|
|
- track->start = BRASERO_GET_32 (desc->track_start);
|
|
-
|
|
- /* we shouldn't request info on a track if the disc is closed */
|
|
- brasero_medium_track_get_info (self,
|
|
- track,
|
|
- g_slist_length (priv->tracks),
|
|
- fd,
|
|
- code);
|
|
-
|
|
- if (desc->control & BRASERO_SCSI_TRACK_COPY)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_COPY;
|
|
-
|
|
- if (!(desc->control & BRASERO_SCSI_TRACK_DATA)) {
|
|
- track->type |= BRASERO_MEDIUM_TRACK_AUDIO;
|
|
- priv->info |= BRASERO_MEDIUM_HAS_AUDIO;
|
|
-
|
|
- if (desc->control & BRASERO_SCSI_TRACK_PREEMP)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_PREEMP;
|
|
-
|
|
- if (desc->control & BRASERO_SCSI_TRACK_4_CHANNELS)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_4_CHANNELS;
|
|
- }
|
|
- else if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)
|
|
- || BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED)) {
|
|
- BraseroBurnResult result;
|
|
-
|
|
- /* a special case for these two kinds of media (DVD+RW)
|
|
- * which have only one track: the first. */
|
|
- result = brasero_medium_track_volume_size (self,
|
|
- track,
|
|
- fd);
|
|
- if (result == BRASERO_BURN_OK) {
|
|
- track->type |= BRASERO_MEDIUM_TRACK_DATA;
|
|
- priv->info |= BRASERO_MEDIUM_HAS_DATA;
|
|
-
|
|
- priv->next_wr_add = 0;
|
|
-
|
|
- if (desc->control & BRASERO_SCSI_TRACK_DATA_INCREMENTAL)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_INCREMENTAL;
|
|
- }
|
|
- else {
|
|
- priv->tracks = g_slist_remove (priv->tracks, track);
|
|
- g_free (track);
|
|
-
|
|
- priv->info |= BRASERO_MEDIUM_BLANK;
|
|
- priv->info &= ~BRASERO_MEDIUM_CLOSED;
|
|
- }
|
|
- }
|
|
- else {
|
|
- track->type |= BRASERO_MEDIUM_TRACK_DATA;
|
|
- priv->info |= BRASERO_MEDIUM_HAS_DATA;
|
|
-
|
|
- if (desc->control & BRASERO_SCSI_TRACK_DATA_INCREMENTAL)
|
|
- track->type |= BRASERO_MEDIUM_TRACK_INCREMENTAL;
|
|
- }
|
|
- }
|
|
-
|
|
- /* put the tracks in the right order */
|
|
- priv->tracks = g_slist_reverse (priv->tracks);
|
|
-
|
|
- if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)
|
|
- || BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
|
|
- brasero_medium_add_DVD_plus_RW_leadout (self, BRASERO_GET_32 (desc->track_start));
|
|
- else if (!(priv->info & BRASERO_MEDIUM_CLOSED)) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- /* we shouldn't request info on leadout if the disc is closed
|
|
- * (except for DVD+/- (restricted) RW (see above) */
|
|
- track = g_new0 (BraseroMediumTrack, 1);
|
|
- priv->tracks = g_slist_append (priv->tracks, track);
|
|
- track->start = BRASERO_GET_32 (desc->track_start);
|
|
- track->type = BRASERO_MEDIUM_TRACK_LEADOUT;
|
|
-
|
|
- brasero_medium_track_get_info (self,
|
|
- track,
|
|
- g_slist_length (priv->tracks),
|
|
- fd,
|
|
- code);
|
|
- }
|
|
-
|
|
- g_free (toc);
|
|
-
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static BraseroBurnResult
|
|
-brasero_medium_get_contents (BraseroMedium *self,
|
|
- int fd,
|
|
- BraseroScsiErrCode *code)
|
|
-{
|
|
- int size;
|
|
- BraseroScsiResult result;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiDiscInfoStd *info = NULL;
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrieving media status");
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
-
|
|
- result = brasero_mmc1_read_disc_information_std (fd,
|
|
- &info,
|
|
- &size,
|
|
- code);
|
|
- if (result != BRASERO_SCSI_OK) {
|
|
- g_free (info);
|
|
-
|
|
- BRASERO_BURN_LOG ("READ DISC INFORMATION failed");
|
|
- return BRASERO_BURN_ERR;
|
|
- }
|
|
-
|
|
- if (info->erasable)
|
|
- priv->info |= BRASERO_MEDIUM_REWRITABLE;
|
|
-
|
|
- if (info->status == BRASERO_SCSI_DISC_EMPTY) {
|
|
- BraseroMediumTrack *track;
|
|
-
|
|
- BRASERO_BURN_LOG ("Empty media");
|
|
-
|
|
- priv->info |= BRASERO_MEDIUM_BLANK;
|
|
- priv->block_size = 2048;
|
|
-
|
|
- if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)
|
|
- || BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_RESTRICTED))
|
|
- brasero_medium_add_DVD_plus_RW_leadout (self, 0);
|
|
- else {
|
|
- track = g_new0 (BraseroMediumTrack, 1);
|
|
- track->start = 0;
|
|
- track->type = BRASERO_MEDIUM_TRACK_LEADOUT;
|
|
- priv->tracks = g_slist_prepend (priv->tracks, track);
|
|
-
|
|
- brasero_medium_track_get_info (self,
|
|
- track,
|
|
- 1,
|
|
- fd,
|
|
- code);
|
|
- }
|
|
- goto end;
|
|
- }
|
|
-
|
|
- if (info->status == BRASERO_SCSI_DISC_INCOMPLETE) {
|
|
- priv->info |= BRASERO_MEDIUM_APPENDABLE;
|
|
- BRASERO_BURN_LOG ("Appendable media");
|
|
- }
|
|
- else if (info->status == BRASERO_SCSI_DISC_FINALIZED) {
|
|
- priv->info |= BRASERO_MEDIUM_CLOSED;
|
|
- BRASERO_BURN_LOG ("Closed media");
|
|
- }
|
|
-
|
|
- if (priv->info & BRASERO_MEDIUM_CD) {
|
|
- result = brasero_medium_get_CD_sessions_info (self, fd, code);
|
|
- if (result != BRASERO_BURN_OK)
|
|
- result = brasero_medium_get_sessions_info (self, fd, code);
|
|
- }
|
|
- else
|
|
- result = brasero_medium_get_sessions_info (self, fd, code);
|
|
-
|
|
- if (result != BRASERO_BURN_OK)
|
|
- goto end;
|
|
-
|
|
-end:
|
|
-
|
|
- g_free (info);
|
|
- return BRASERO_BURN_OK;
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_init_real (BraseroMedium *object, int fd)
|
|
-{
|
|
- gchar *name;
|
|
- BraseroBurnResult result;
|
|
- BraseroMediumPrivate *priv;
|
|
- BraseroScsiErrCode code = 0;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
-
|
|
- name = nautilus_burn_drive_get_name_for_display (priv->drive);
|
|
- BRASERO_BURN_LOG ("Initializing information for medium in %s", name);
|
|
- g_free (name);
|
|
-
|
|
- result = brasero_medium_get_medium_type (object, fd, &code);
|
|
- if (result != BRASERO_BURN_OK)
|
|
- return;
|
|
-
|
|
- brasero_medium_get_capacity_by_type (object, fd, &code);
|
|
-
|
|
- result = brasero_medium_get_contents (object, fd, &code);
|
|
- if (result != BRASERO_BURN_OK)
|
|
- return;
|
|
-
|
|
- /* assume that css feature is only for DVD-ROM which might be wrong but
|
|
- * some drives wrongly reports that css is enabled for blank DVD+R/W */
|
|
- if (BRASERO_MEDIUM_IS (priv->info, (BRASERO_MEDIUM_DVD|BRASERO_MEDIUM_ROM)))
|
|
- brasero_medium_get_css_feature (object, fd, &code);
|
|
-
|
|
- BRASERO_BURN_LOG_DISC_TYPE (priv->info, "media is ");
|
|
-}
|
|
-
|
|
-static gboolean
|
|
-brasero_medium_retry_open (gpointer object)
|
|
-{
|
|
- int fd;
|
|
- const gchar *path;
|
|
- BraseroMedium *self;
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- self = BRASERO_MEDIUM (object);
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
- path = nautilus_burn_drive_get_device (priv->drive);
|
|
-
|
|
- BRASERO_BURN_LOG ("Retrying to open device %s", path);
|
|
- fd = open (path, OPEN_FLAGS);
|
|
- if (fd < 0) {
|
|
- if (errno == EBUSY
|
|
- || errno == EAGAIN
|
|
- || errno == EWOULDBLOCK) {
|
|
- BRASERO_BURN_LOG ("Device busy");
|
|
- /* we'll retry in a second */
|
|
- return TRUE;
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Open () failed");
|
|
- priv->info = BRASERO_MEDIUM_UNSUPPORTED;
|
|
- priv->retry_id = 0;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Open () succeeded\n");
|
|
- priv->info = BRASERO_MEDIUM_NONE;
|
|
- priv->icon = icons [0];
|
|
-
|
|
- priv->retry_id = 0;
|
|
-
|
|
- brasero_medium_init_real (self, fd);
|
|
- close (fd);
|
|
-
|
|
- return FALSE;
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_try_open (BraseroMedium *self)
|
|
-{
|
|
- int fd;
|
|
- const gchar *path;
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (self);
|
|
- path = nautilus_burn_drive_get_device (priv->drive);
|
|
-
|
|
- /* the drive might be busy (a burning is going on) so we don't block
|
|
- * but we re-try to open it every second */
|
|
- BRASERO_BURN_LOG ("Trying to open device %s", path);
|
|
- fd = open (path, OPEN_FLAGS);
|
|
- if (fd < 0) {
|
|
- if (errno == EAGAIN
|
|
- || errno == EWOULDBLOCK
|
|
- || errno == EBUSY) {
|
|
- BRASERO_BURN_LOG ("Device busy");
|
|
- priv->info = BRASERO_MEDIUM_BUSY;
|
|
- priv->icon = icons [0];
|
|
-
|
|
- priv->retry_id = g_timeout_add (BUSY_RETRY_TIME,
|
|
- brasero_medium_retry_open,
|
|
- self);
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Open () failed");
|
|
- return;
|
|
- }
|
|
-
|
|
- BRASERO_BURN_LOG ("Open () succeeded");
|
|
- brasero_medium_init_real (self, fd);
|
|
- close (fd);
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_init (BraseroMedium *object)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
- priv->next_wr_add = -1;
|
|
-
|
|
- /* we can't do anything here since properties haven't been set yet */
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_finalize (GObject *object)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
-
|
|
- if (priv->retry_id) {
|
|
- g_source_remove (priv->retry_id);
|
|
- priv->retry_id = 0;
|
|
- }
|
|
-
|
|
- g_free (priv->rd_speeds);
|
|
- priv->rd_speeds = NULL;
|
|
-
|
|
- g_free (priv->wr_speeds);
|
|
- priv->wr_speeds = NULL;
|
|
-
|
|
- g_slist_foreach (priv->tracks, (GFunc) g_free, NULL);
|
|
- g_slist_free (priv->tracks);
|
|
- priv->tracks = NULL;
|
|
-
|
|
- nautilus_burn_drive_unref (priv->drive);
|
|
- priv->drive = NULL;
|
|
-
|
|
- G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- g_return_if_fail (BRASERO_IS_MEDIUM (object));
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
-
|
|
- switch (prop_id)
|
|
- {
|
|
- case PROP_DRIVE:
|
|
- priv->drive = g_value_get_object (value);
|
|
- nautilus_burn_drive_ref (priv->drive);
|
|
- brasero_medium_try_open (BRASERO_MEDIUM (object));
|
|
- break;
|
|
- default:
|
|
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
|
-{
|
|
- BraseroMediumPrivate *priv;
|
|
-
|
|
- g_return_if_fail (BRASERO_IS_MEDIUM (object));
|
|
-
|
|
- priv = BRASERO_MEDIUM_PRIVATE (object);
|
|
-
|
|
- switch (prop_id)
|
|
- {
|
|
- case PROP_DRIVE:
|
|
- nautilus_burn_drive_ref (priv->drive);
|
|
- g_value_set_object (value, priv->drive);
|
|
- break;
|
|
- default:
|
|
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-brasero_medium_class_init (BraseroMediumClass *klass)
|
|
-{
|
|
- GObjectClass* object_class = G_OBJECT_CLASS (klass);
|
|
- parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
|
|
-
|
|
- g_type_class_add_private (klass, sizeof (BraseroMediumPrivate));
|
|
-
|
|
- object_class->finalize = brasero_medium_finalize;
|
|
- object_class->set_property = brasero_medium_set_property;
|
|
- object_class->get_property = brasero_medium_get_property;
|
|
-
|
|
- g_object_class_install_property (object_class,
|
|
- PROP_DRIVE,
|
|
- g_param_spec_object ("drive",
|
|
- "drive",
|
|
- "drive in which medium is inserted",
|
|
- NAUTILUS_BURN_TYPE_DRIVE,
|
|
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
-}
|
|
-
|
|
-GType
|
|
-brasero_medium_get_type (void)
|
|
-{
|
|
- static GType our_type = 0;
|
|
-
|
|
- if (our_type == 0)
|
|
- {
|
|
- static const GTypeInfo our_info =
|
|
- {
|
|
- sizeof (BraseroMediumClass), /* class_size */
|
|
- (GBaseInitFunc) NULL, /* base_init */
|
|
- (GBaseFinalizeFunc) NULL, /* base_finalize */
|
|
- (GClassInitFunc) brasero_medium_class_init, /* class_init */
|
|
- (GClassFinalizeFunc) NULL, /* class_finalize */
|
|
- NULL /* class_data */,
|
|
- sizeof (BraseroMedium), /* instance_size */
|
|
- 0, /* n_preallocs */
|
|
- (GInstanceInitFunc) brasero_medium_init, /* instance_init */
|
|
- NULL /* value_table */
|
|
- };
|
|
-
|
|
- our_type = g_type_register_static (G_TYPE_OBJECT, "BraseroMedium",
|
|
- &our_info, 0);
|
|
- }
|
|
-
|
|
- return our_type;
|
|
-}
|
|
-
|
|
-BraseroMedium *
|
|
-brasero_medium_new (NautilusBurnDrive *drive)
|
|
-{
|
|
- g_return_val_if_fail (drive != NULL, NULL);
|
|
- return BRASERO_MEDIUM (g_object_new (BRASERO_TYPE_MEDIUM,
|
|
- "drive", drive,
|
|
- NULL));
|
|
-}
|