diff options
author | Joe Marcus Clarke <marcus@FreeBSD.org> | 2009-01-10 05:22:13 +0000 |
---|---|---|
committer | Joe Marcus Clarke <marcus@FreeBSD.org> | 2009-01-10 05:22:13 +0000 |
commit | 610ae5681637c1051a0c17b54e29d97f53da2f3a (patch) | |
tree | c231a1eb74b07e444fa7363012cb84bf23d83ce0 /sysutils/brasero/files/patch-src_burn-medium-cam.c | |
parent | Add a new framework for browser plugins, USE_WEBPLUGINS. It is for which foo (diff) |
Presenting GNOME 2.24 for FreeBSD.
See http://library.gnome.org/misc/release-notes/2.24/ for the general
release notes. On the FreeBSD front, this release introduces Fuse support
in HAL, adds multi-CPU support to libgtop, WebKit updates, and fixes some
long-standing seahorse and gnome-keyring bugs. The documentation updates
to the website are forthcoming.
This release features commits by adamw, ahze, kwm, mezz, and myself. It would
not have been possible without are contributors and testers:
Alexander Loginov
Craig Butler [1]
Dmitry Marakasov [6]
Eric L. Chen
Joseph S. Atkinson
Kris Moore
Lapo Luchini [7]
Nikos Ntarmos
Pawel Worach
Romain Tartiere
TAOKA Fumiyoshi [3]
Yasuda Keisuke
Zyl
aZ [4]
bf [2] [5]
Florent Thoumie
Peter Wemm
pluknet
PR: 125857 [1]
126993 [2]
130031 [3]
127399 [4]
127661 [5]
124302 [6]
129570 [7]
129936
123790
Notes
Notes:
svn path=/head/; revision=225629
Diffstat (limited to 'sysutils/brasero/files/patch-src_burn-medium-cam.c')
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-medium-cam.c | 1928 |
1 files changed, 0 insertions, 1928 deletions
diff --git a/sysutils/brasero/files/patch-src_burn-medium-cam.c b/sysutils/brasero/files/patch-src_burn-medium-cam.c deleted file mode 100644 index 2db8d00ca985..000000000000 --- a/sysutils/brasero/files/patch-src_burn-medium-cam.c +++ /dev/null @@ -1,1928 +0,0 @@ ---- src/burn-medium-cam.c.orig 2008-02-06 01:53:39.000000000 -0500 -+++ src/burn-medium-cam.c 2008-02-06 01:56:01.000000000 -0500 -@@ -0,0 +1,1925 @@ -+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -+/* -+ * brasero -+ * Copyright (C) Philippe Rouquier 2007 <bonfire-app@wanadoo.fr> -+ * Joe Marcus Clarke 2007 <marcus@FreeBSD.org> -+ * -+ * 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 <stdlib.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 "cam-cdrom.h" -+#include "scsi-read-format-capacities.h" -+#include "scsi-read-toc-pma-atip.h" -+#include "scsi-get-configuration.h" -+#include "scsi-q-subchannel.h" -+#include "scsi-utils.h" -+#include "freebsd_dvd_rw_utils.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)) -+ -+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, -+ BRASEROCDROM *cdrom) -+{ -+ unsigned char *atip_data = NULL; -+ unsigned char *desc; -+ BraseroMediumPrivate *priv; -+ int result; -+ int size; -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ -+ BRASERO_BURN_LOG ("Retrieving capacity from atip"); -+ -+ result = brasero_cdrom_read_atip (cdrom, &atip_data); -+ -+ if (result != 0) { -+ g_free (atip_data); -+ -+ BRASERO_BURN_LOG ("READ ATIP failed (scsi error)"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ size = (atip_data[0] << 8 | atip_data[1]) - 2; -+ -+ /* 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; -+ } -+ -+ desc = atip_data + 8; -+ -+ priv->block_num = BRASERO_MSF_TO_LBA (desc[8], desc[9], desc[10]); -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ unsigned char *hdr = NULL; -+ unsigned char *current; -+ BraseroMediumPrivate *priv; -+ int result; -+ -+ BRASERO_BURN_LOG ("Retrieving format capacity"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ result = brasero_cdrom_read_format_capacities (cdrom, &hdr); -+ if (result != 0) { -+ g_free (hdr); -+ -+ BRASERO_BURN_LOG ("READ FORMAT CAPACITIES failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ current = hdr + 5; -+ -+ /* see if the media is already formatted */ -+ if ((current[4] & 3) != BRASERO_SCSI_DESC_FORMATTED) { -+ int i, max; -+ unsigned char *desc; -+ -+ max = (hdr[4] - 8) / 8; -+ -+ desc = hdr + 5; -+ for (i = 0; i < max; i ++, desc += 8) { -+ /* search for the correct descriptor */ -+ if (BRASERO_MEDIUM_IS (priv->info, BRASERO_MEDIUM_DVDRW_PLUS)) { -+ if ((desc[4] >> 2) == BRASERO_SCSI_DVDRW_PLUS) { -+ priv->block_num = (desc[0] << 24 | desc[1] << 16 | desc[2] << 8 | desc[3]); -+ priv->block_size = (desc[5] << 16 | desc[6] << 8 | desc[7]); -+ -+ /* that can happen */ -+ if (!priv->block_size) -+ priv->block_size = 2048; -+ break; -+ } -+ } -+ else if ((desc[4] >> 2) == BRASERO_SCSI_BLOCK_SIZE_DEFAULT_AND_DB) { -+ priv->block_num = (desc[0] << 24 | desc[1] << 16 | desc[2] << 8 | desc[3]); -+ priv->block_size = (desc[5] << 16 | desc[6] << 8 | desc[7]); -+ break; -+ } -+ } -+ } -+ else { -+ priv->block_num = (current[0] << 24 | current[1] << 16 | current[2] << 8 | current[3]); -+ priv->block_size = (current[5] << 16 | current[6] << 8 | current[7]); -+ } -+ -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ 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, cdrom); -+ else -+ brasero_medium_get_capacity_DVD_RW (self, cdrom); -+ -+ return BRASERO_BURN_OK; -+} -+ -+/** -+ * Functions to retrieve the speed -+ */ -+ -+static BraseroBurnResult -+brasero_medium_get_speed_mmc3 (BraseroMedium *self, -+ BRASEROCDROM *cdrom) -+{ -+ int size; -+ int num_desc, i; -+ gint max_rd, max_wrt; -+ int result; -+ BraseroMediumPrivate *priv; -+ unsigned char *desc; -+ unsigned char *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_cdrom_get_performance_wrt_spd_desc (cdrom, &wrt_perf); -+ -+ if (result != 0) { -+ g_free (wrt_perf); -+ -+ BRASERO_BURN_LOG ("GET PERFORMANCE failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ size = 4 + (wrt_perf[0] << 24 | wrt_perf[1] << 16 | wrt_perf[2] << 8 | wrt_perf[3]); -+ -+ num_desc = (size - 8) / 16; -+ -+ 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 = wrt_perf + 8; -+ for (i = 0; i < num_desc; i ++, desc += 16) { -+ priv->rd_speeds [i] = (desc[8] << 24 | desc[9] << 16 | desc[10] << 8 || desc[11]); -+ priv->wr_speeds [i] = (desc[12] << 24 | desc[13] << 16 | desc[14] << 8 | desc[15]); -+ -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ BraseroMediumPrivate *priv; -+ int result; -+ char *wspeeds; -+ int rspeed, wspeed; -+ -+ BRASERO_BURN_LOG ("Retrieving speed (2A speeds)"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ result = brasero_cdrom_get_read_write_speed (cdrom, &rspeed, &wspeed, &wspeeds); -+ -+ if (result != 0) { -+ BRASERO_BURN_LOG ("MODE SENSE failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ if (wspeeds != NULL) { -+ char **speedv; -+ int i; -+ -+ speedv = g_strsplit_set (wspeeds, ",", 0); -+ g_free (wspeeds); -+ priv->wr_speeds = g_new0 (gint, g_strv_length (speedv) + 1); -+ for (i = 0; speedv[i] != NULL; i++) { -+ if (*(speedv[i])) -+ priv->wr_speeds[i] = atoi (speedv[i]); -+ } -+ g_strfreev (speedv); -+ } -+ -+ priv->max_wrt = wspeed; -+ priv->max_rd = rspeed; -+ -+ return BRASERO_BURN_OK; -+} -+ -+static BraseroBurnResult -+brasero_medium_get_page_2A_max_speed (BraseroMedium *self, -+ BRASEROCDROM *cdrom) -+{ -+ BraseroMediumPrivate *priv; -+ int result; -+ int rspeed, wspeed; -+ char *wspeeds; -+ -+ BRASERO_BURN_LOG ("Retrieving speed (2A max)"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ -+ result = brasero_cdrom_get_read_write_speed (cdrom, &rspeed, &wspeed, &wspeeds); -+ -+ if (result != 0) { -+ BRASERO_BURN_LOG ("MODE SENSE failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ priv->max_rd = rspeed; -+ priv->max_wrt = wspeed; -+ -+ g_free (wspeeds); -+ -+ return BRASERO_BURN_OK; -+} -+ -+static BraseroBurnResult -+brasero_medium_get_medium_type (BraseroMedium *self, -+ BRASEROCDROM *cdrom) -+{ -+ unsigned char *hdr = NULL; -+ unsigned char *confdesc; -+ BraseroMediumPrivate *priv; -+ BraseroBurnResult result; -+ int profile; -+ int res; -+ -+ BRASERO_BURN_LOG ("Retrieving media profile"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ res = brasero_cdrom_get_configuration_feature (cdrom, -+ BRASERO_SCSI_FEAT_REAL_TIME_STREAM, -+ &hdr); -+ if (res != 0) { -+ unsigned char *data = NULL; -+ unsigned char *desc; -+ int size; -+ -+ 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. -+ */ -+ res = brasero_cdrom_read_atip (cdrom, &data); -+ if (res != 0) { -+ /* 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 */ -+ size = (data[0] << 8 | data[1]) - 2; -+ if (size < 8) { -+ if (size) -+ g_free (data); -+ -+ BRASERO_BURN_LOG ("READ ATIP failed (wrong size)"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ desc = data + 4; -+ -+ if ((desc[2] >> 6) & 1) { -+ /* 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, cdrom); -+ return result; -+ } -+ -+ profile = (hdr[6] << 8 | hdr[7]); -+ -+ switch (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; -+ } -+ -+ confdesc = hdr + 8; -+ -+ /* try all SCSI functions to get write/read speeds in order */ -+ if (confdesc[4] >= 4) { -+ unsigned char *stream; -+ -+ /* means it's at least an MMC3 drive */ -+ stream = confdesc + 5; -+ if ((stream[0] >> 1) & 1) { -+ result = brasero_medium_get_speed_mmc3 (self, cdrom); -+ if (result == BRASERO_BURN_OK) -+ goto end; -+ } -+ -+ if ((stream[0] >> 2) & 1) { -+ result = brasero_medium_get_page_2A_write_speed_desc (self, cdrom); -+ if (result == BRASERO_BURN_OK) -+ goto end; -+ } -+ } -+ -+ /* fallback for speeds */ -+ result = brasero_medium_get_page_2A_max_speed (self, cdrom); -+ -+end: -+ -+ g_free (hdr); -+ -+ if (result != BRASERO_BURN_OK) -+ return result; -+ -+ return BRASERO_BURN_OK; -+} -+ -+static BraseroBurnResult -+brasero_medium_get_css_feature (BraseroMedium *self, -+ BRASEROCDROM *cdrom) -+{ -+ unsigned char *hdr = NULL; -+ BraseroMediumPrivate *priv; -+ int result; -+ int size; -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ -+ BRASERO_BURN_LOG ("Testing for Css encrypted media"); -+ result = brasero_cdrom_get_configuration_feature (cdrom, -+ BRASERO_SCSI_FEAT_DVD_CSS, -+ &hdr); -+ if (result != 0) { -+ g_free (hdr); -+ -+ BRASERO_BURN_LOG ("GET CONFIGURATION failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ size = 4 + (hdr[0] << 24 | hdr[1] << 16 | hdr[2] << 8 | hdr[3]); -+ -+ if (size < 9 || hdr[12] < 4) { -+ g_free (hdr); -+ return BRASERO_BURN_OK; -+ } -+ -+ /* here we just need to see if this feature is current or not */ -+ if (hdr[11] & 1) { -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ 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 (brasero_cdrom_get_fd (cdrom), -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ unsigned char track_info[48]; -+ BraseroMediumPrivate *priv; -+ int result; -+ int size; -+ int next_wrt; -+ -+ 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_cdrom_read_track_info (cdrom, track_num, track_info, size); -+ -+ if (result != 0) { -+ BRASERO_BURN_LOG ("READ TRACK INFO failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ track->blocks_num = (track_info[24] << 24 | track_info[25] << 16 | track_info[26] << 8 | track_info[27]); -+ track->session = (track_info[33] << 8 | track_info[3]); -+ -+ /* 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, cdrom); -+ } -+ -+ next_wrt = (track_info[12] << 24 | track_info[13] << 16 | track_info[14] << 7 | track_info[15]); -+ -+ if (next_wrt); -+ priv->next_wr_add = next_wrt; -+ -+ 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, -+ BRASEROCDROM *cdrom, -+ unsigned char *desc, -+ guint num) -+{ -+ guint i; -+ int size; -+ guint leadout = 0; -+ guint track_num = 0; -+ gboolean use_BCD = TRUE; -+ gboolean use_HEX = TRUE; -+ int result; -+ unsigned char *dptr; -+ unsigned char track_info[48]; -+ guint start_BCD, start_LBA, track_start; -+ -+ /* first check if all values are valid BCD numbers in the descriptors */ -+ dptr = desc; -+ for (i = 0; i < num; i++, dptr += 11) { -+ if ((dptr[1] >> 4) == 1 && dptr[3] <= BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) { -+ if (!BRASERO_IS_BCD_VALID (dptr[8]) -+ || !BRASERO_IS_BCD_VALID (dptr[9]) -+ || !BRASERO_IS_BCD_VALID (dptr[10])) { -+ use_BCD = FALSE; -+ break; -+ } -+ } -+ else if (dptr[3] == BRASERO_SCSI_Q_SUB_CHANNEL_LEADOUT_START) { -+ if (!BRASERO_IS_BCD_VALID (dptr[8]) -+ || !BRASERO_IS_BCD_VALID (dptr[9]) -+ || !BRASERO_IS_BCD_VALID (dptr[10])) { -+ use_BCD = FALSE; -+ break; -+ } -+ } -+ } -+ -+ /* then check if there are valid Hex values */ -+ dptr = desc; -+ for (i = 0; i < num; i++, dptr += 11) { -+ if ((dptr[i] >> 4) != 1 || dptr[3] > BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) -+ continue; -+ -+ if (dptr[8] > 99 -+ || dptr[9] > 59 -+ || dptr[10] > 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"); -+ -+ dptr = desc; -+ for (i = 0; i < num; i++, dptr += 11) { -+ if ((dptr[1] >> 4) == BRASERO_SCSI_Q_SUB_CHANNEL_LEADIN_MODE5 -+ && dptr[3] == BRASERO_SCSI_Q_SUB_CHANNEL_MULTI_NEXT_SESSION) { -+ /* store the leadout number just in case */ -+ leadout = i; -+ continue; -+ } -+ -+ if ((dptr[1] >> 4) != 1 || dptr[3] > BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) -+ continue; -+ -+ track_num ++; -+ -+ start_BCD = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (dptr[8]), -+ BRASERO_GET_BCD (dptr[9]), -+ BRASERO_GET_BCD (dptr[10])); -+ -+ start_LBA = BRASERO_MSF_TO_LBA (dptr[8], dptr[9], dptr[10]); -+ -+ 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_cdrom_read_track_info (cdrom, -+ track_num, -+ track_info, -+ size); -+ -+ if (result != 0) { -+ BRASERO_BURN_LOG ("READ TRACK INFO failed"); -+ /* Fallback to formatted toc */ -+ return 0; -+ } -+ -+ track_start = (track_info[8] << 24 | track_info[9] << 16 | track_info[10] << 8 | track_info[11]); -+ 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. */ -+ dptr = desc + (leadout * 11); -+ start_BCD = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (dptr[4]), -+ BRASERO_GET_BCD (dptr[5]), -+ BRASERO_GET_BCD (dptr[6])); -+ -+ start_LBA = BRASERO_MSF_TO_LBA (dptr[4], dptr[5], dptr[6]); -+ -+ BRASERO_BURN_LOG ("Comparing to track information from READ TRACK INFO for leadout"); -+ -+ size = 36; -+ -+ /* leadout number is number of tracks + 1 */ -+ result = brasero_cdrom_read_track_info (cdrom, -+ track_num + 1, -+ track_info, -+ size); -+ -+ if (result != 0) { -+ BRASERO_BURN_LOG ("READ TRACK INFO failed for leadout"); -+ /* Fallback to formatted toc */ -+ return 0; -+ } -+ -+ track_start = (track_info[8] << 24 | track_info[9] << 16 | track_info[10] << 8 | track_info[11]); -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ gint use_bcd; -+ GSList *iter; -+ int num, i, size, res; -+ gint leadout_start = 0; -+ BraseroMediumPrivate *priv; -+ unsigned char *desc; -+ unsigned char *toc = NULL; -+ -+ BRASERO_BURN_LOG ("Reading Raw Toc"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ -+ res = brasero_cdrom_read_toc_raw (cdrom, 0, &toc); -+ if (res != 0) { -+ BRASERO_BURN_LOG ("READ TOC failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ size = (toc[0] << 8 | toc[1]) - 2; -+ num = size / 11; -+ -+ BRASERO_BURN_LOG ("%i track(s) found", num); -+ -+ desc = toc + 4; -+ use_bcd = brasero_medium_check_BCD_use (self, cdrom, desc, num); -+ 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 += 11) { -+ BraseroMediumTrack *track; -+ -+ track = NULL; -+ if ((desc[1] >> 4) == 1 && desc[3] <= BRASERO_SCSI_Q_SUB_CHANNEL_TRACK_START) { -+ track = g_new0 (BraseroMediumTrack, 1); -+ track->session = desc[0]; -+ -+ brasero_medium_set_track_type (self, track, (desc[1] & 15)); -+ if (use_bcd) -+ track->start = BRASERO_MSF_TO_LBA (BRASERO_GET_BCD (desc[8]), -+ BRASERO_GET_BCD (desc[9]), -+ BRASERO_GET_BCD (desc[10])); -+ else -+ track->start = BRASERO_MSF_TO_LBA (desc[8], -+ desc[9], -+ desc[10]); -+ -+ 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[3] == 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[8]), -+ BRASERO_GET_BCD (desc[9]), -+ BRASERO_GET_BCD (desc[10])); -+ else -+ leadout_start = BRASERO_MSF_TO_LBA (desc[8], -+ desc[9], -+ desc[10]); -+ 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), cdrom); -+ } -+ -+ 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, cdrom); -+ } -+ -+ 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, -+ BRASEROCDROM *cdrom) -+{ -+ int num, i, size, res; -+ gint32 tstart; -+ unsigned char *toc = NULL; -+ unsigned char *desc; -+ BraseroMediumPrivate *priv; -+ -+ BRASERO_BURN_LOG ("Reading Toc"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ res = brasero_cdrom_read_toc_formatted (cdrom, 0, &toc); -+ if (res != 0) { -+ g_free (toc); -+ -+ BRASERO_BURN_LOG ("READ TOC failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ size = (toc[0] << 8 | toc[1]) - 2; -+ -+ num = size / 8; /* Each track description is 8 bytes. */ -+ -+ BRASERO_BURN_LOG ("%i track(s) found", num); -+ -+ for (desc = toc + 4, i = 0; i < num; i ++, desc += 8) { -+ BraseroMediumTrack *track; -+ -+ if (desc[2] == BRASERO_SCSI_TRACK_LEADOUT_START) -+ break; -+ -+ tstart = (desc[4] << 24 | desc[5] << 16 | desc[6] << 8 | desc[7]); -+ -+ track = g_new0 (BraseroMediumTrack, 1); -+ priv->tracks = g_slist_prepend (priv->tracks, track); -+ track->start = tstart; -+ -+ /* 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), -+ cdrom); -+ -+ if ((desc[1] & 15) & BRASERO_SCSI_TRACK_COPY) -+ track->type |= BRASERO_MEDIUM_TRACK_COPY; -+ -+ if (!((desc[1] & 15) & BRASERO_SCSI_TRACK_DATA)) { -+ track->type |= BRASERO_MEDIUM_TRACK_AUDIO; -+ priv->info |= BRASERO_MEDIUM_HAS_AUDIO; -+ -+ if ((desc[1] & 15) & BRASERO_SCSI_TRACK_PREEMP) -+ track->type |= BRASERO_MEDIUM_TRACK_PREEMP; -+ -+ if ((desc[1] & 15) & 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, -+ cdrom); -+ if (result == BRASERO_BURN_OK) { -+ track->type |= BRASERO_MEDIUM_TRACK_DATA; -+ priv->info |= BRASERO_MEDIUM_HAS_DATA; -+ -+ priv->next_wr_add = 0; -+ -+ if ((desc[1] & 15) & 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[1] & 15) & 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); -+ tstart = (desc[4] << 24 | desc[5] << 16 | desc[6] << 8 | desc[7]); -+ -+ 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, tstart); -+ 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 = tstart; -+ track->type = BRASERO_MEDIUM_TRACK_LEADOUT; -+ -+ brasero_medium_track_get_info (self, -+ track, -+ g_slist_length (priv->tracks), -+ cdrom); -+ } -+ -+ g_free (toc); -+ -+ return BRASERO_BURN_OK; -+} -+ -+static BraseroBurnResult -+brasero_medium_get_contents (BraseroMedium *self, -+ BRASEROCDROM *cdrom) -+{ -+ BraseroBurnResult result; -+ int res; -+ BraseroMediumPrivate *priv; -+ unsigned char buf[32]; -+ -+ BRASERO_BURN_LOG ("Retrieving media status"); -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ -+ res = brasero_cdrom_read_disc_information_std (cdrom, buf); -+ if (res != 0) { -+ BRASERO_BURN_LOG ("READ DISC INFORMATION failed"); -+ return BRASERO_BURN_ERR; -+ } -+ -+ if (buf[2] & 16) /* Erasable */ -+ priv->info |= BRASERO_MEDIUM_REWRITABLE; -+ -+ if ((buf[2] & 3) == 0) { /* Empty disc */ -+ 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, -+ cdrom); -+ } -+ goto end; -+ } -+ -+ if (buf[2] & 1) { /* Appendable */ -+ priv->info |= BRASERO_MEDIUM_APPENDABLE; -+ BRASERO_BURN_LOG ("Appendable media"); -+ } -+ else if (buf[2] & 2) { /* Complete */ -+ priv->info |= BRASERO_MEDIUM_CLOSED; -+ BRASERO_BURN_LOG ("Closed media"); -+ } -+ -+ if (priv->info & BRASERO_MEDIUM_CD) { -+ result = brasero_medium_get_CD_sessions_info (self, cdrom); -+ if (result != BRASERO_BURN_OK) -+ result = brasero_medium_get_sessions_info (self, cdrom); -+ } -+ else -+ result = brasero_medium_get_sessions_info (self, cdrom); -+ -+ if (result != BRASERO_BURN_OK) -+ goto end; -+ -+end: -+ -+ return BRASERO_BURN_OK; -+} -+ -+static void -+brasero_medium_init_real (BraseroMedium *object, BRASEROCDROM *cdrom) -+{ -+ gchar *name; -+ BraseroBurnResult result; -+ BraseroMediumPrivate *priv; -+ -+ 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, cdrom); -+ if (result != BRASERO_BURN_OK) -+ return; -+ -+ brasero_medium_get_capacity_by_type (object, cdrom); -+ -+ result = brasero_medium_get_contents (object, cdrom); -+ 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, cdrom); -+ -+ BRASERO_BURN_LOG_DISC_TYPE (priv->info, "media is "); -+} -+ -+static void -+brasero_medium_try_open (BraseroMedium *self) -+{ -+ const gchar *path; -+ BRASEROCDROM *cdrom; -+ BraseroMediumPrivate *priv; -+ -+ priv = BRASERO_MEDIUM_PRIVATE (self); -+ path = nautilus_burn_drive_get_device (priv->drive); -+ -+ BRASERO_BURN_LOG ("Trying to create BRASERCDROM for device %s", path); -+ cdrom = brasero_cdrom_new (path); -+ if (cdrom == NULL) { -+ BRASERO_BURN_LOG ("Creation failed"); -+ return; -+ } -+ -+ BRASERO_BURN_LOG ("Creation succeeded"); -+ brasero_medium_init_real (self, cdrom); -+ brasero_cdrom_free (cdrom); -+} -+ -+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)); -+} |