diff options
Diffstat (limited to 'sysutils/brasero/files/patch-src_burn-medium.c')
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-medium.c | 2073 |
1 files changed, 2073 insertions, 0 deletions
diff --git a/sysutils/brasero/files/patch-src_burn-medium.c b/sysutils/brasero/files/patch-src_burn-medium.c new file mode 100644 index 000000000..accb659e2 --- /dev/null +++ b/sysutils/brasero/files/patch-src_burn-medium.c @@ -0,0 +1,2073 @@ +--- 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)); +-} |