summaryrefslogtreecommitdiffstats
path: root/sysutils/brasero
diff options
context:
space:
mode:
authormarcus <marcus@df743ca5-7f9a-e211-a948-0013205c9059>2008-05-14 10:10:41 +0800
committermarcus <marcus@df743ca5-7f9a-e211-a948-0013205c9059>2008-05-14 10:10:41 +0800
commit5a79bf43b13b13189baa1824b8b3fb029464aa0b (patch)
tree45975c5272e9a8c9f5514c6b91858799ee697cf3 /sysutils/brasero
parent02807bdcb78a7514c33a38c18f846b5a6af982af (diff)
downloadmarcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar.gz
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar.bz2
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar.lz
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar.xz
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.tar.zst
marcuscom-ports-5a79bf43b13b13189baa1824b8b3fb029464aa0b.zip
Chase the totem-pl-parser shared lib version.
git-svn-id: svn://creme-brulee.marcuscom.com/ports/trunk@10944 df743ca5-7f9a-e211-a948-0013205c9059
Diffstat (limited to 'sysutils/brasero')
-rw-r--r--sysutils/brasero/Makefile41
-rw-r--r--sysutils/brasero/distinfo3
-rw-r--r--sysutils/brasero/files/patch-configure264
-rw-r--r--sysutils/brasero/files/patch-src_Makefile.in275
-rw-r--r--sysutils/brasero/files/patch-src_brasero-ncb.h12
-rw-r--r--sysutils/brasero/files/patch-src_burn-job.c31
-rw-r--r--sysutils/brasero/files/patch-src_burn-job.h12
-rw-r--r--sysutils/brasero/files/patch-src_burn-medium-cam.c1928
-rw-r--r--sysutils/brasero/files/patch-src_burn-medium-scsi.c2073
-rw-r--r--sysutils/brasero/files/patch-src_burn-medium.c2073
-rw-r--r--sysutils/brasero/files/patch-src_cam1361
-rw-r--r--sysutils/brasero/files/patch-src_plugins_cdrtools_burn-cdrecord.c11
-rw-r--r--sysutils/brasero/pkg-descr23
-rw-r--r--sysutils/brasero/pkg-plist245
14 files changed, 8352 insertions, 0 deletions
diff --git a/sysutils/brasero/Makefile b/sysutils/brasero/Makefile
new file mode 100644
index 000000000..3d0683269
--- /dev/null
+++ b/sysutils/brasero/Makefile
@@ -0,0 +1,41 @@
+# New ports collection makefile for: bonfire
+# Date created: 2006-05-12
+# Whom: Michael Johnson <ahze@FreeBSD.org>
+#
+# $FreeBSD$
+# $MCom: ports/sysutils/brasero/Makefile,v 1.23 2008/02/06 07:11:46 marcus Exp $
+
+PORTNAME= brasero
+PORTVERSION= 0.7.1
+PORTREVISION= 4
+CATEGORIES= sysutils audio multimedia gnome
+MASTER_SITES= ${MASTER_SITE_GNOME}
+MASTER_SITE_SUBDIR= sources/${PORTNAME}/${PORTVERSION:C/^([0-9]+\.[0-9]+).*/\1/}
+DIST_SUBDIR= gnome2
+
+MAINTAINER= gnome@FreeBSD.org
+COMMENT= CD/DVD mastering tool for the GNOME desktop
+
+LIB_DEPENDS= notify.1:${PORTSDIR}/devel/libnotify \
+ totem-plparser.12:${PORTSDIR}/multimedia/totem-pl-parser
+
+USE_GETTEXT= yes
+USE_BZIP2= yes
+GNU_CONFIGURE= yes
+USE_GMAKE= yes
+USE_GNOME= gnomehier nautiluscdburner
+USE_GSTREAMER= gconf core
+INSTALLS_ICONS= yes
+CONFIGURE_ARGS= --disable-inotify \
+ --with-cam
+CONFIGURE_ENV= CPPFLAGS="-I${LOCALBASE}/include" \
+ LDFLAGS="-L${LOCALBASE}/lib"
+
+MAN1= brasero.1
+GCONF_SCHEMAS= brasero.schemas
+
+post-patch:
+ @${REINPLACE_CMD} -e 's|blank-cd:|blank-cd;|g' \
+ ${WRKSRC}/data/brasero.desktop.in.in
+
+.include <bsd.port.mk>
diff --git a/sysutils/brasero/distinfo b/sysutils/brasero/distinfo
new file mode 100644
index 000000000..ba88da57f
--- /dev/null
+++ b/sysutils/brasero/distinfo
@@ -0,0 +1,3 @@
+MD5 (gnome2/brasero-0.7.1.tar.bz2) = 2754fca21c31f00016981cc8fe7c48be
+SHA256 (gnome2/brasero-0.7.1.tar.bz2) = 0ad851ba9f05c2e4ae0778e61c74aee56bbae3a4181b172009698cde03387f5c
+SIZE (gnome2/brasero-0.7.1.tar.bz2) = 1483716
diff --git a/sysutils/brasero/files/patch-configure b/sysutils/brasero/files/patch-configure
new file mode 100644
index 000000000..3f4958a84
--- /dev/null
+++ b/sysutils/brasero/files/patch-configure
@@ -0,0 +1,264 @@
+--- configure.orig 2008-01-24 16:49:00.000000000 -0500
++++ configure 2008-01-24 16:49:16.000000000 -0500
+@@ -885,6 +885,8 @@ BRASERO_BASE_CFLAGS
+ BRASERO_BASE_LIBS
+ BRASERO_CFLAGS
+ BRASERO_LIBS
++WITH_CAM_TRUE
++WITH_CAM_FALSE
+ LIBBURNIA_CFLAGS
+ LIBBURNIA_LIBS
+ BRASERO_LIBBURNIA_CFLAGS
+@@ -1610,6 +1612,7 @@ Optional Packages:
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS] include additional configurations [automatic]
++ --with-cam Build with CAM backend instead of Linux SCSI [default = no]
+ --with-gconf-source=sourceaddress Config database for installing schema files.
+ --with-gconf-schema-file-dir=dir Directory for installing schema files.
+
+@@ -4514,7 +4517,7 @@ ia64-*-hpux*)
+ ;;
+ *-*-irix6*)
+ # Find out which ABI we are using.
+- echo '#line 4517 "configure"' > conftest.$ac_ext
++ echo '#line 4520 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+@@ -7252,11 +7255,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:7255: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:7258: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:7259: \$? = $ac_status" >&5
++ echo "$as_me:7262: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -7542,11 +7545,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:7545: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:7548: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:7549: \$? = $ac_status" >&5
++ echo "$as_me:7552: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -7646,11 +7649,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:7649: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:7652: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+- echo "$as_me:7653: \$? = $ac_status" >&5
++ echo "$as_me:7656: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+@@ -9997,7 +10000,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 10000 "configure"
++#line 10003 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -10097,7 +10100,7 @@ else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+-#line 10100 "configure"
++#line 10103 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+@@ -12517,11 +12520,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:12520: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:12523: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:12524: \$? = $ac_status" >&5
++ echo "$as_me:12527: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -12621,11 +12624,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:12624: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:12627: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+- echo "$as_me:12628: \$? = $ac_status" >&5
++ echo "$as_me:12631: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+@@ -14185,11 +14188,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:14188: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:14191: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:14192: \$? = $ac_status" >&5
++ echo "$as_me:14195: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -14289,11 +14292,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:14292: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:14295: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+- echo "$as_me:14296: \$? = $ac_status" >&5
++ echo "$as_me:14299: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+@@ -16478,11 +16481,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:16481: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:16484: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:16485: \$? = $ac_status" >&5
++ echo "$as_me:16488: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -16768,11 +16771,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:16771: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:16774: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+- echo "$as_me:16775: \$? = $ac_status" >&5
++ echo "$as_me:16778: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+@@ -16872,11 +16875,11 @@ else
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+- (eval echo "\"\$as_me:16875: $lt_compile\"" >&5)
++ (eval echo "\"\$as_me:16878: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+- echo "$as_me:16879: \$? = $ac_status" >&5
++ echo "$as_me:16882: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+@@ -22350,6 +22353,27 @@ BRASERO_LIBS="$BRASERO_BASE_LIBS $BRASER
+ LIBBURN_REQUIRED=0.4.0
+ LIBISOFS_REQUIRED=0.2.8
+
++
++# Check whether --with-cam was given.
++if test "${with_cam+set}" = set; then
++ withval=$with_cam;
++else
++ with_cam="no"
++fi
++
++
++if text x"$with_cam" = "xyes"; then
++ BRASERO_LIBS="$BRASERO_LIBS -lcam"
++fi
++ if test x"$with_cam" = "xyes"; then
++ WITH_CAM_TRUE=
++ WITH_CAM_FALSE='#'
++else
++ WITH_CAM_TRUE='#'
++ WITH_CAM_FALSE=
++fi
++
++
+ # Check whether --enable-libburnia was given.
+ if test "${enable_libburnia+set}" = set; then
+ enableval=$enable_libburnia;
+@@ -25144,6 +25168,13 @@ echo "$as_me: error: conditional \"am__f
+ Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
++if test -z "${WITH_CAM_TRUE}" && test -z "${WITH_CAM_FALSE}"; then
++ { { echo "$as_me:$LINENO: error: conditional \"WITH_CAM\" was never defined.
++Usually this means the macro was only invoked conditionally." >&5
++echo "$as_me: error: conditional \"WITH_CAM\" was never defined.
++Usually this means the macro was only invoked conditionally." >&2;}
++ { (exit 1); exit 1; }; }
++fi
+ if test -z "${BUILD_LIBBURNIA_TRUE}" && test -z "${BUILD_LIBBURNIA_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"BUILD_LIBBURNIA\" was never defined.
+ Usually this means the macro was only invoked conditionally." >&5
+@@ -25945,6 +25976,8 @@ BRASERO_BASE_CFLAGS!$BRASERO_BASE_CFLAGS
+ BRASERO_BASE_LIBS!$BRASERO_BASE_LIBS$ac_delim
+ BRASERO_CFLAGS!$BRASERO_CFLAGS$ac_delim
+ BRASERO_LIBS!$BRASERO_LIBS$ac_delim
++WITH_CAM_TRUE!$WITH_CAM_TRUE$ac_delim
++WITH_CAM_FALSE!$WITH_CAM_FALSE$ac_delim
+ LIBBURNIA_CFLAGS!$LIBBURNIA_CFLAGS$ac_delim
+ LIBBURNIA_LIBS!$LIBBURNIA_LIBS$ac_delim
+ BRASERO_LIBBURNIA_CFLAGS!$BRASERO_LIBBURNIA_CFLAGS$ac_delim
+@@ -26019,8 +26052,6 @@ INTLTOOL_UPDATE!$INTLTOOL_UPDATE$ac_deli
+ INTLTOOL_PERL!$INTLTOOL_PERL$ac_delim
+ ALL_LINGUAS!$ALL_LINGUAS$ac_delim
+ SCHEMAS_INSTALL_TRUE!$SCHEMAS_INSTALL_TRUE$ac_delim
+-SCHEMAS_INSTALL_FALSE!$SCHEMAS_INSTALL_FALSE$ac_delim
+-GCONFTOOL!$GCONFTOOL$ac_delim
+ _ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+@@ -26062,6 +26093,8 @@ _ACEOF
+ ac_delim='%!_!# '
+ for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
++SCHEMAS_INSTALL_FALSE!$SCHEMAS_INSTALL_FALSE$ac_delim
++GCONFTOOL!$GCONFTOOL$ac_delim
+ GCONF_SCHEMA_CONFIG_SOURCE!$GCONF_SCHEMA_CONFIG_SOURCE$ac_delim
+ GCONF_SCHEMA_FILE_DIR!$GCONF_SCHEMA_FILE_DIR$ac_delim
+ GCONF_SCHEMAS_INSTALL_TRUE!$GCONF_SCHEMAS_INSTALL_TRUE$ac_delim
+@@ -26070,7 +26103,7 @@ LIBOBJS!$LIBOBJS$ac_delim
+ LTLIBOBJS!$LTLIBOBJS$ac_delim
+ _ACEOF
+
+- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then
++ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 8; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/sysutils/brasero/files/patch-src_Makefile.in b/sysutils/brasero/files/patch-src_Makefile.in
new file mode 100644
index 000000000..c57255769
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_Makefile.in
@@ -0,0 +1,275 @@
+--- src/Makefile.in.orig 2008-01-24 16:49:38.000000000 -0500
++++ src/Makefile.in 2008-01-24 16:49:47.000000000 -0500
+@@ -45,7 +45,96 @@ CONFIG_CLEAN_FILES =
+ am__installdirs = "$(DESTDIR)$(bindir)"
+ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+ PROGRAMS = $(bin_PROGRAMS)
++am__brasero_SOURCES_DIST = brasero-marshal.h brasero-marshal.c main.c \
++ brasero-utils.h brasero-utils.c burn-dbus.h burn-dbus.c \
++ brasero-search-entry.c brasero-search-entry.h \
++ brasero-search-beagle.c brasero-search-beagle.h \
++ brasero-mime-filter.c brasero-mime-filter.h brasero-playlist.c \
++ brasero-playlist.h brasero-player.c brasero-player.h \
++ brasero-menu.h brasero-burn-dialog.c brasero-burn-dialog.h \
++ brasero-disc-copy-dialog.c brasero-disc-copy-dialog.h \
++ brasero-blank-dialog.c brasero-blank-dialog.h inotify.h \
++ brasero-metadata.c brasero-metadata.h inotify-syscalls.h \
++ brasero-filtered-window.c brasero-filtered-window.h \
++ brasero-disc.c brasero-disc.h brasero-data-disc.c \
++ brasero-data-disc.h brasero-audio-disc.c brasero-audio-disc.h \
++ brasero-project.c brasero-project.h \
++ brasero-project-type-chooser.c brasero-project-type-chooser.h \
++ brasero-player-bacon.c brasero-player-bacon.h \
++ brasero-progress.c brasero-progress.h \
++ brasero-song-properties.c brasero-song-properties.h \
++ brasero-tray.c brasero-tray.h burn.c burn.h burn-job.c \
++ burn-job.h burn-process.c burn-process.h burn-basics.h \
++ burn-basics.c burn-caps.c burn-caps.h brasero-session.c \
++ brasero-session.h brasero-app.h brasero-uri-container.c \
++ brasero-uri-container.h brasero-project-manager.c \
++ brasero-project-manager.h brasero-layout.c brasero-layout.h \
++ brasero-file-chooser.c brasero-file-chooser.h \
++ brasero-project-size.c brasero-project-size.h burn-session.h \
++ brasero-sum-dialog.c brasero-sum-dialog.h \
++ brasero-tool-dialog.c brasero-tool-dialog.h brasero-ncb.h \
++ brasero-ncb.c burn-task.c burn-task.h brasero-vfs.c \
++ brasero-vfs.h brasero-async-task-manager.c \
++ brasero-async-task-manager.h eggtreemultidnd.c \
++ eggtreemultidnd.h brasero-multi-dnd.c brasero-multi-dnd.h \
++ brasero-image-option-dialog.c brasero-image-option-dialog.h \
++ brasero-disc-option-dialog.c brasero-disc-option-dialog.h \
++ brasero-image-type-chooser.c brasero-image-type-chooser.h \
++ burn-iso9660.c burn-iso9660.h brasero-layout-object.c \
++ brasero-layout-object.h burn-volume.c burn-volume.h \
++ burn-susp.c burn-susp.h burn-iso-field.c burn-iso-field.h \
++ burn-medium.h cam/cam-cdrom.h cam/freebsd_dvd_rw_utils.h \
++ scsi/scsi-base.h scsi/scsi-command.h scsi/scsi-error.h \
++ scsi/scsi-get-configuration.h scsi/scsi-mmc1.h \
++ scsi/scsi-mmc2.h scsi/scsi-opcodes.h \
++ scsi/scsi-read-disc-info.h scsi/scsi-read-toc-pma-atip.h \
++ scsi/scsi-sense-data.h scsi/scsi-sg.h scsi/scsi-utils.h \
++ scsi/scsi-q-subchannel.h scsi/scsi-read-track-information.h \
++ scsi/scsi-get-performance.h scsi/scsi-mmc3.h \
++ scsi/scsi-mode-pages.h scsi/scsi-status-page.h \
++ scsi/scsi-spc1.h scsi/scsi-read-capacity.h \
++ scsi/scsi-read-disc-structure.h scsi/scsi-dvd-structures.h \
++ scsi/scsi-read-format-capacities.h scsi/scsi-command.c \
++ scsi/scsi-get-configuration.c scsi/scsi-read-disc-info.c \
++ scsi/scsi-read-toc-pma-atip.c scsi/scsi-sense-data.c \
++ scsi/scsi-sg.c scsi/scsi-error.c \
++ scsi/scsi-read-track-information.c scsi/scsi-get-performance.c \
++ scsi/scsi-mode-sense.c scsi/scsi-read-capacity.c \
++ scsi/scsi-read-disc-structure.c \
++ scsi/scsi-read-format-capacities.c burn-medium-scsi.c \
++ cam/cam-cdrom.c cam/freebsd_dvd_rw_utils.c burn-medium-cam.c \
++ burn-debug.c burn-debug.h burn-track.h burn-plugin.h \
++ burn-plugin.c burn-plugin-private.h burn-plugin-manager.c \
++ burn-plugin-manager.h burn-task-ctx.h burn-task-item.c \
++ burn-task-item.h burn-task-ctx.c burn-mkisofs-base.c \
++ burn-mkisofs-base.h brasero-drive-selection.h \
++ brasero-drive-selection.c brasero-src-selection.h \
++ brasero-src-selection.c brasero-dest-selection.h \
++ brasero-dest-selection.c brasero-drive-info.c \
++ brasero-drive-info.h brasero-drive-properties.h \
++ brasero-drive-properties.c brasero-image-properties.h \
++ brasero-image-properties.c brasero-xfer.c brasero-xfer.h \
++ burn-session.c burn-track.c brasero-plugin-manager-ui.c \
++ brasero-plugin-manager-ui.h brasero-pref.h brasero-pref.c \
++ brasero-plugin-option.h brasero-plugin-option.c \
++ brasero-split-dialog.h brasero-split-dialog.c \
++ brasero-time-button.h brasero-time-button.c brasero-preview.h \
++ brasero-preview.c burn-image-format.c burn-image-format.h
+ am__objects_1 = brasero-marshal.$(OBJEXT)
++am__objects_2 = scsi-command.$(OBJEXT) \
++ scsi-get-configuration.$(OBJEXT) scsi-read-disc-info.$(OBJEXT) \
++ scsi-read-toc-pma-atip.$(OBJEXT) scsi-sense-data.$(OBJEXT) \
++ scsi-sg.$(OBJEXT) scsi-error.$(OBJEXT) \
++ scsi-read-track-information.$(OBJEXT) \
++ scsi-get-performance.$(OBJEXT) scsi-mode-sense.$(OBJEXT) \
++ scsi-read-capacity.$(OBJEXT) \
++ scsi-read-disc-structure.$(OBJEXT) \
++ scsi-read-format-capacities.$(OBJEXT) \
++ burn-medium-scsi.$(OBJEXT)
++am__objects_3 = cam-cdrom.$(OBJEXT) freebsd_dvd_rw_utils.$(OBJEXT) \
++ burn-medium-cam.$(OBJEXT)
++@WITH_CAM_FALSE@am__objects_4 = $(am__objects_2)
++@WITH_CAM_TRUE@am__objects_4 = $(am__objects_3)
+ am_brasero_OBJECTS = $(am__objects_1) main.$(OBJEXT) \
+ brasero-utils.$(OBJEXT) burn-dbus.$(OBJEXT) \
+ brasero-search-entry.$(OBJEXT) brasero-search-beagle.$(OBJEXT) \
+@@ -72,19 +161,11 @@ am_brasero_OBJECTS = $(am__objects_1) ma
+ brasero-disc-option-dialog.$(OBJEXT) \
+ brasero-image-type-chooser.$(OBJEXT) burn-iso9660.$(OBJEXT) \
+ brasero-layout-object.$(OBJEXT) burn-volume.$(OBJEXT) \
+- burn-susp.$(OBJEXT) burn-iso-field.$(OBJEXT) \
+- burn-medium.$(OBJEXT) scsi-command.$(OBJEXT) \
+- scsi-get-configuration.$(OBJEXT) scsi-read-disc-info.$(OBJEXT) \
+- scsi-read-toc-pma-atip.$(OBJEXT) scsi-sense-data.$(OBJEXT) \
+- scsi-sg.$(OBJEXT) scsi-error.$(OBJEXT) \
+- scsi-read-track-information.$(OBJEXT) \
+- scsi-get-performance.$(OBJEXT) scsi-mode-sense.$(OBJEXT) \
+- scsi-read-capacity.$(OBJEXT) \
+- scsi-read-disc-structure.$(OBJEXT) \
+- scsi-read-format-capacities.$(OBJEXT) burn-debug.$(OBJEXT) \
+- burn-plugin.$(OBJEXT) burn-plugin-manager.$(OBJEXT) \
+- burn-task-item.$(OBJEXT) burn-task-ctx.$(OBJEXT) \
+- burn-mkisofs-base.$(OBJEXT) brasero-drive-selection.$(OBJEXT) \
++ burn-susp.$(OBJEXT) burn-iso-field.$(OBJEXT) $(am__objects_4) \
++ burn-debug.$(OBJEXT) burn-plugin.$(OBJEXT) \
++ burn-plugin-manager.$(OBJEXT) burn-task-item.$(OBJEXT) \
++ burn-task-ctx.$(OBJEXT) burn-mkisofs-base.$(OBJEXT) \
++ brasero-drive-selection.$(OBJEXT) \
+ brasero-src-selection.$(OBJEXT) \
+ brasero-dest-selection.$(OBJEXT) brasero-drive-info.$(OBJEXT) \
+ brasero-drive-properties.$(OBJEXT) \
+@@ -110,7 +191,7 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLF
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+ SOURCES = $(brasero_SOURCES)
+-DIST_SOURCES = $(brasero_SOURCES)
++DIST_SOURCES = $(am__brasero_SOURCES_DIST)
+ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+@@ -316,6 +397,7 @@ INCLUDES = \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ -I./scsi \
++ -I./cam \
+ -I./md5 \
+ -DBRASERO_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+ -DBRASERO_PREFIX=\"$(prefix)\" \
+@@ -327,9 +409,30 @@ INCLUDES = \
+
+ CLEANFILES = $(RECMARSHALFILES)
+ AM_CFLAGS = -g
+-EXTRA_DIST = cd-content-marshal.list
++CAMFILES = cam/cam-cdrom.c \
++ cam/freebsd_dvd_rw_utils.c \
++ burn-medium-cam.c
++
++SCSIFILES = scsi/scsi-command.c \
++ scsi/scsi-get-configuration.c \
++ scsi/scsi-read-disc-info.c \
++ scsi/scsi-read-toc-pma-atip.c \
++ scsi/scsi-sense-data.c \
++ scsi/scsi-sg.c \
++ scsi/scsi-error.c \
++ scsi/scsi-read-track-information.c \
++ scsi/scsi-get-performance.c \
++ scsi/scsi-mode-sense.c \
++ scsi/scsi-read-capacity.c \
++ scsi/scsi-read-disc-structure.c \
++ scsi/scsi-read-format-capacities.c \
++ burn-medium-scsi.c
++
++EXTRA_DIST = cd-content-marshal.list $(CAMFILES) $(SCSIFILES)
+ GLIB_GENMARSHAL = `pkg-config --variable=glib_genmarshal glib-2.0`
+ RECMARSHALFILES = brasero-marshal.h brasero-marshal.c
++@WITH_CAM_FALSE@SCSISOURCES = $(SCSIFILES)
++@WITH_CAM_TRUE@SCSISOURCES = $(CAMFILES)
+ brasero_SOURCES = \
+ $(RECMARSHALFILES) \
+ main.c \
+@@ -435,43 +538,32 @@ brasero_SOURCES = \
+ burn-iso-field.c \
+ burn-iso-field.h \
+ burn-medium.h \
+- burn-medium.c \
++ cam/cam-cdrom.h \
++ cam/freebsd_dvd_rw_utils.h \
+ scsi/scsi-base.h \
+- scsi/scsi-command.c \
+ scsi/scsi-command.h \
+ scsi/scsi-error.h \
+- scsi/scsi-get-configuration.c \
+ scsi/scsi-get-configuration.h \
+ scsi/scsi-mmc1.h \
+ scsi/scsi-mmc2.h \
+ scsi/scsi-opcodes.h \
+- scsi/scsi-read-disc-info.c \
+ scsi/scsi-read-disc-info.h \
+- scsi/scsi-read-toc-pma-atip.c \
+ scsi/scsi-read-toc-pma-atip.h \
+- scsi/scsi-sense-data.c \
+ scsi/scsi-sense-data.h \
+- scsi/scsi-sg.c \
+ scsi/scsi-sg.h \
+ scsi/scsi-utils.h \
+ scsi/scsi-q-subchannel.h \
+- scsi/scsi-error.c \
+- scsi/scsi-read-track-information.c \
+ scsi/scsi-read-track-information.h \
+- scsi/scsi-get-performance.c \
+ scsi/scsi-get-performance.h \
+ scsi/scsi-mmc3.h \
+ scsi/scsi-mode-pages.h \
+- scsi/scsi-mode-sense.c \
+ scsi/scsi-status-page.h \
+ scsi/scsi-spc1.h \
+- scsi/scsi-read-capacity.c \
+ scsi/scsi-read-capacity.h \
+- scsi/scsi-read-disc-structure.c \
+ scsi/scsi-read-disc-structure.h \
+ scsi/scsi-dvd-structures.h \
+- scsi/scsi-read-format-capacities.c \
+ scsi/scsi-read-format-capacities.h \
++ $(SCSISOURCES) \
+ burn-debug.c \
+ burn-debug.h \
+ burn-track.h \
+@@ -647,7 +739,8 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-iso-field.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-iso9660.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-job.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-medium.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-medium-cam.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-medium-scsi.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-mkisofs-base.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-plugin-manager.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-plugin.Po@am__quote@
+@@ -660,7 +753,9 @@ distclean-compile:
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-track.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn-volume.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/burn.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cam-cdrom.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eggtreemultidnd.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/freebsd_dvd_rw_utils.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsi-command.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scsi-error.Po@am__quote@
+@@ -879,6 +974,34 @@ scsi-read-format-capacities.obj: scsi/sc
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o scsi-read-format-capacities.obj `if test -f 'scsi/scsi-read-format-capacities.c'; then $(CYGPATH_W) 'scsi/scsi-read-format-capacities.c'; else $(CYGPATH_W) '$(srcdir)/scsi/scsi-read-format-capacities.c'; fi`
+
++cam-cdrom.o: cam/cam-cdrom.c
++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cam-cdrom.o -MD -MP -MF $(DEPDIR)/cam-cdrom.Tpo -c -o cam-cdrom.o `test -f 'cam/cam-cdrom.c' || echo '$(srcdir)/'`cam/cam-cdrom.c
++@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cam-cdrom.Tpo $(DEPDIR)/cam-cdrom.Po
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cam/cam-cdrom.c' object='cam-cdrom.o' libtool=no @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cam-cdrom.o `test -f 'cam/cam-cdrom.c' || echo '$(srcdir)/'`cam/cam-cdrom.c
++
++cam-cdrom.obj: cam/cam-cdrom.c
++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cam-cdrom.obj -MD -MP -MF $(DEPDIR)/cam-cdrom.Tpo -c -o cam-cdrom.obj `if test -f 'cam/cam-cdrom.c'; then $(CYGPATH_W) 'cam/cam-cdrom.c'; else $(CYGPATH_W) '$(srcdir)/cam/cam-cdrom.c'; fi`
++@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cam-cdrom.Tpo $(DEPDIR)/cam-cdrom.Po
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cam/cam-cdrom.c' object='cam-cdrom.obj' libtool=no @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cam-cdrom.obj `if test -f 'cam/cam-cdrom.c'; then $(CYGPATH_W) 'cam/cam-cdrom.c'; else $(CYGPATH_W) '$(srcdir)/cam/cam-cdrom.c'; fi`
++
++freebsd_dvd_rw_utils.o: cam/freebsd_dvd_rw_utils.c
++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT freebsd_dvd_rw_utils.o -MD -MP -MF $(DEPDIR)/freebsd_dvd_rw_utils.Tpo -c -o freebsd_dvd_rw_utils.o `test -f 'cam/freebsd_dvd_rw_utils.c' || echo '$(srcdir)/'`cam/freebsd_dvd_rw_utils.c
++@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/freebsd_dvd_rw_utils.Tpo $(DEPDIR)/freebsd_dvd_rw_utils.Po
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cam/freebsd_dvd_rw_utils.c' object='freebsd_dvd_rw_utils.o' libtool=no @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o freebsd_dvd_rw_utils.o `test -f 'cam/freebsd_dvd_rw_utils.c' || echo '$(srcdir)/'`cam/freebsd_dvd_rw_utils.c
++
++freebsd_dvd_rw_utils.obj: cam/freebsd_dvd_rw_utils.c
++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT freebsd_dvd_rw_utils.obj -MD -MP -MF $(DEPDIR)/freebsd_dvd_rw_utils.Tpo -c -o freebsd_dvd_rw_utils.obj `if test -f 'cam/freebsd_dvd_rw_utils.c'; then $(CYGPATH_W) 'cam/freebsd_dvd_rw_utils.c'; else $(CYGPATH_W) '$(srcdir)/cam/freebsd_dvd_rw_utils.c'; fi`
++@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/freebsd_dvd_rw_utils.Tpo $(DEPDIR)/freebsd_dvd_rw_utils.Po
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cam/freebsd_dvd_rw_utils.c' object='freebsd_dvd_rw_utils.obj' libtool=no @AMDEPBACKSLASH@
++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o freebsd_dvd_rw_utils.obj `if test -f 'cam/freebsd_dvd_rw_utils.c'; then $(CYGPATH_W) 'cam/freebsd_dvd_rw_utils.c'; else $(CYGPATH_W) '$(srcdir)/cam/freebsd_dvd_rw_utils.c'; fi`
++
+ mostlyclean-libtool:
+ -rm -f *.lo
+
diff --git a/sysutils/brasero/files/patch-src_brasero-ncb.h b/sysutils/brasero/files/patch-src_brasero-ncb.h
new file mode 100644
index 000000000..bd5106d64
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_brasero-ncb.h
@@ -0,0 +1,12 @@
+--- src/brasero-ncb.h.orig 2008-01-02 15:01:39.000000000 -0500
++++ src/brasero-ncb.h 2008-01-02 15:02:15.000000000 -0500
+@@ -42,6 +42,9 @@ nautilus_burn_drive_get_drive_type ((dri
+ #define NCB_DRIVE_GET_DEVICE(drive) \
+ nautilus_burn_drive_get_device (drive)
+
++#define NCB_DRIVE_GET_CRECORD_DEVICE(drive) \
++nautilus_burn_drive_get_cdrecord_device (drive)
++
+ #define NCB_DRIVE_GET_LIST(list, recorders, image) \
+ { \
+ NautilusBurnDriveMonitor *monitor; \
diff --git a/sysutils/brasero/files/patch-src_burn-job.c b/sysutils/brasero/files/patch-src_burn-job.c
new file mode 100644
index 000000000..c26d1bb72
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_burn-job.c
@@ -0,0 +1,31 @@
+--- src/burn-job.c.orig 2008-01-02 15:00:34.000000000 -0500
++++ src/burn-job.c 2008-01-02 15:01:15.000000000 -0500
+@@ -1300,6 +1300,28 @@ brasero_job_get_device (BraseroJob *self
+ }
+
+ BraseroBurnResult
++brasero_job_get_cdrecord_device (BraseroJob *self, gchar **device)
++{
++ BraseroBurnSession *session;
++ NautilusBurnDrive *drive;
++ BraseroJobPrivate *priv;
++ const gchar *path;
++
++ BRASERO_JOB_DEBUG (self);
++
++ g_return_val_if_fail (device != NULL, BRASERO_BURN_ERR);
++
++ priv = BRASERO_JOB_PRIVATE (self);
++ session = brasero_task_ctx_get_session (priv->ctx);
++
++ drive = brasero_burn_session_get_burner (session);
++ path = NCB_DRIVE_GET_CRECORD_DEVICE (drive);
++ *device = g_strdup (path);
++
++ return BRASERO_BURN_OK;
++}
++
++BraseroBurnResult
+ brasero_job_get_media (BraseroJob *self, BraseroMedia *media)
+ {
+ BraseroBurnSession *session;
diff --git a/sysutils/brasero/files/patch-src_burn-job.h b/sysutils/brasero/files/patch-src_burn-job.h
new file mode 100644
index 000000000..d73d8e6e2
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_burn-job.h
@@ -0,0 +1,12 @@
+--- src/burn-job.h.orig 2008-01-02 14:59:55.000000000 -0500
++++ src/burn-job.h 2008-01-02 15:00:13.000000000 -0500
+@@ -148,6 +148,9 @@ BraseroBurnResult
+ brasero_job_get_device (BraseroJob *job, gchar **device);
+
+ BraseroBurnResult
++brasero_job_get_cdrecord_device (BraseroJob *job, gchar **device);
++
++BraseroBurnResult
+ brasero_job_get_media (BraseroJob *job, BraseroMedia *media);
+
+ BraseroBurnResult
diff --git a/sysutils/brasero/files/patch-src_burn-medium-cam.c b/sysutils/brasero/files/patch-src_burn-medium-cam.c
new file mode 100644
index 000000000..2db8d00ca
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_burn-medium-cam.c
@@ -0,0 +1,1928 @@
+--- 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));
++}
diff --git a/sysutils/brasero/files/patch-src_burn-medium-scsi.c b/sysutils/brasero/files/patch-src_burn-medium-scsi.c
new file mode 100644
index 000000000..974754cde
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_burn-medium-scsi.c
@@ -0,0 +1,2073 @@
+--- src/burn-medium-scsi.c.orig 2008-02-06 01:53:39.000000000 -0500
++++ src/burn-medium-scsi.c 2008-02-06 01:54:19.000000000 -0500
+@@ -0,0 +1,2070 @@
++/* -*- 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));
++}
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));
+-}
diff --git a/sysutils/brasero/files/patch-src_cam b/sysutils/brasero/files/patch-src_cam
new file mode 100644
index 000000000..febbbd1c3
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_cam
@@ -0,0 +1,1361 @@
+diff -rupN cam.orig/freebsd_dvd_rw_utils.h cam/freebsd_dvd_rw_utils.h
+--- /dev/null 1969-12-31 19:00:00.000000000 -0500
++++ src/cam/freebsd_dvd_rw_utils.h 2008-01-24 16:52:25.000000000 -0500
+@@ -0,0 +1,49 @@
++//
++// This is part of dvd+rw-tools by Andy Polyakov <appro@fy.chalmers.se>
++//
++// Use-it-on-your-own-risk, GPL bless...
++//
++// For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
++//
++
++#ifndef FREEBSD_DVD_RW_UTILS_H
++#define FREEBSD_DVD_RW_UTILS_H
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <glib.h>
++
++#include "cam-cdrom.h"
++
++#define DRIVE_CDROM_CAPS_DVDRW 1
++#define DRIVE_CDROM_CAPS_DVDPLUSR 2
++#define DRIVE_CDROM_CAPS_DVDPLUSRW 4
++#define DRIVE_CDROM_CAPS_DVDPLUSRWDL 8
++#define DRIVE_CDROM_CAPS_DVDPLUSRDL 16
++#define DRIVE_CDROM_CAPS_BDROM 32
++#define DRIVE_CDROM_CAPS_BDR 64
++#define DRIVE_CDROM_CAPS_BDRE 128
++#define DRIVE_CDROM_CAPS_HDDVDROM 256
++#define DRIVE_CDROM_CAPS_HDDVDR 512
++#define DRIVE_CDROM_CAPS_HDDVDRW 1024
++
++int brasero_cdrom_get_dvd_r_rw_profile (BRASEROCDROM *cdrom);
++int brasero_cdrom_get_read_write_speed (BRASEROCDROM *cdrom, int *read_speed, int *write_speed, char **write_speeds);
++int brasero_cdrom_get_disc_capacity_for_type (BRASEROCDROM *cdrom, int type, guint64 *capacity);
++int brasero_cdrom_get_disc_type (BRASEROCDROM *cdrom);
++int brasero_cdrom_read_disc_information_std (BRASEROCDROM *cdrom, unsigned char *buf);
++int brasero_cdrom_disc_is_appendable (BRASEROCDROM *cdrom);
++int brasero_cdrom_disc_is_rewritable (BRASEROCDROM *cdrom);
++int brasero_cdrom_read_atip (BRASEROCDROM *cdrom, unsigned char **buf);
++int brasero_cdrom_read_format_capacities (BRASEROCDROM *cdrom, unsigned char **buf);
++int brasero_cdrom_get_performance_wrt_spd_desc (BRASEROCDROM *cdrom, unsigned char **buf);
++int brasero_cdrom_get_configuration_feature (BRASEROCDROM *cdrom, int feature, unsigned char **buf);
++int brasero_cdrom_read_track_info (BRASEROCDROM *cdrom, int track_num, unsigned char *buf, int size);
++int brasero_cdrom_read_toc_raw (BRASEROCDROM *cdrom, int track_num, unsigned char **buf);
++int brasero_cdrom_read_toc_formatted (BRASEROCDROM *cdrom, int track_num, unsigned char **buf);
++int brasero_read_disc_information_std (BRASEROCDROM *cdrom, unsigned char *buf);
++int brasero_cdrom_read_format_capacities (BRASEROCDROM *cdrom, unsigned char **buf);
++
++#endif /* FREEBSD_DVD_RW_UTILS_H */
+--- /dev/null 2008-02-03 02:26:39.000000000 -0500
++++ src/cam/cam-cdrom.h 2008-02-03 11:32:23.000000000 -0500
+@@ -0,0 +1,68 @@
++/***************************************************************************
++ * CVSID: $Id: patch-src_cam,v 1.3 2008-05-14 02:10:40 marcus Exp $
++ *
++ * hfp-cdrom.h : SCSI CD-ROM abstraction layer
++ *
++ * Copyright (C) 2006 Jean-Yves Lefort <jylefort@FreeBSD.org>
++ *
++ * This program is free software; you can 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.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ **************************************************************************/
++
++#ifndef _BRASERO_CDROM_H
++#define _BRASERO_CDROM_H
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <glib.h>
++
++#include <sys/types.h>
++
++typedef struct _BRASEROCDROM BRASEROCDROM;
++
++typedef enum
++{
++ BRASERO_CDROM_DIRECTION_NONE,
++ BRASERO_CDROM_DIRECTION_IN,
++ BRASERO_CDROM_DIRECTION_OUT
++} BRASEROCDROMDirection;
++
++/* ATAPI/SCSI commands */
++enum
++{
++ BRASERO_CDROM_TEST_UNIT_READY = 0x00,
++ BRASERO_CDROM_GET_EVENT_STATUS_NOTIFICATION = 0x4a,
++ BRASERO_CDROM_MODE_SENSE_BIG = 0x5a
++};
++
++BRASEROCDROM *brasero_cdrom_new (const char *path);
++
++gboolean brasero_cdrom_send_ccb (BRASEROCDROM *cdrom,
++ const char *ccb,
++ int ccb_len,
++ BRASEROCDROMDirection direction,
++ void *data,
++ int len,
++ char **err);
++
++gboolean brasero_cdrom_test_unit_ready (BRASEROCDROM *cdrom);
++
++int brasero_cdrom_get_fd (BRASEROCDROM *cdrom);
++
++void brasero_cdrom_free (BRASEROCDROM *cdrom);
++
++#endif /* _BRASERO_CDROM_H */
+--- /dev/null 2008-02-03 13:11:45.000000000 -0500
++++ src/cam/cam-cdrom.c 2008-02-03 13:24:53.000000000 -0500
+@@ -0,0 +1,156 @@
++/***************************************************************************
++ * CVSID: $Id: patch-src_cam,v 1.3 2008-05-14 02:10:40 marcus Exp $
++ *
++ * cam-cdrom.c : SCSI CD-ROM abstraction layer
++ *
++ * Copyright (C) 2006 Jean-Yves Lefort <jylefort@FreeBSD.org>
++ *
++ * This program is free software; you can 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.
++ *
++ * This program 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 this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ **************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include <string.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/ioctl.h>
++#include <sys/types.h>
++#include <sys/ata.h>
++#include <stdio.h>
++#include <camlib.h>
++#include <cam/scsi/scsi_message.h>
++#include <glib.h>
++
++#include "cam-cdrom.h"
++
++struct _BRASEROCDROM
++{
++ struct cam_device *cam; /* for SCSI drives */
++ int fd;
++};
++
++BRASEROCDROM *
++brasero_cdrom_new (const char *path)
++{
++ BRASEROCDROM *cdrom = NULL;
++ struct cam_device *cam;
++ int fd;
++
++ g_assert(path != NULL);
++
++ /* brasero_open_device() fails unless we use O_RDWR */
++ cam = cam_open_device(path, O_RDWR);
++ fd = open(path, O_RDONLY | O_NONBLOCK);
++ if (cam && fd > -1)
++ {
++ cdrom = g_new0(BRASEROCDROM, 1);
++ cdrom->cam = cam;
++ cdrom->fd = fd;
++ }
++
++ return cdrom;
++}
++
++gboolean
++brasero_cdrom_send_ccb (BRASEROCDROM *cdrom,
++ const char *ccb,
++ int ccb_len,
++ BRASEROCDROMDirection direction,
++ void *data,
++ int len,
++ char **err)
++{
++ int timeout;
++
++ g_assert(cdrom != NULL);
++ g_assert(ccb != NULL);
++ g_assert(direction == BRASERO_CDROM_DIRECTION_NONE
++ || direction == BRASERO_CDROM_DIRECTION_IN
++ || direction == BRASERO_CDROM_DIRECTION_OUT);
++ g_assert(direction == BRASERO_CDROM_DIRECTION_NONE || data != NULL);
++
++ timeout = 10;
++
++ union ccb cam_ccb;
++ static int scsi_direction[] = { CAM_DIR_NONE, CAM_DIR_IN, CAM_DIR_OUT };
++
++ memset(&cam_ccb, 0, sizeof(cam_ccb));
++
++ cam_ccb.ccb_h.path_id = cdrom->cam->path_id;
++ cam_ccb.ccb_h.target_id = cdrom->cam->target_id;
++ cam_ccb.ccb_h.target_lun = cdrom->cam->target_lun;
++
++ cam_fill_csio(&cam_ccb.csio,
++ 1,
++ NULL,
++ scsi_direction[direction],
++ MSG_SIMPLE_Q_TAG,
++ data,
++ len,
++ sizeof(cam_ccb.csio.sense_data),
++ ccb_len,
++ timeout * 1000);
++
++ memcpy(cam_ccb.csio.cdb_io.cdb_bytes, ccb, 16);
++
++ if (cam_send_ccb(cdrom->cam, &cam_ccb) == -1)
++ {
++ if (err)
++ *err = g_strdup_printf("cam_send_ccb() failure: %s", g_strerror(errno));
++ }
++ if ((cam_ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
++ {
++ if (err)
++ *err = g_strdup_printf("CCB request failed with status %i", cam_ccb.ccb_h.status & CAM_STATUS_MASK);
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++gboolean
++brasero_cdrom_test_unit_ready (BRASEROCDROM *cdrom)
++{
++ static char ccb[16] = { BRASERO_CDROM_TEST_UNIT_READY };
++
++ g_assert(cdrom != NULL);
++
++ return brasero_cdrom_send_ccb(cdrom, ccb, 6, BRASERO_CDROM_DIRECTION_NONE, NULL, 0, NULL);
++}
++
++int
++brasero_cdrom_get_fd (BRASEROCDROM *cdrom)
++{
++ g_assert(cdrom != NULL);
++
++ return (cdrom->fd);
++}
++
++void
++brasero_cdrom_free (BRASEROCDROM *cdrom)
++{
++ g_assert(cdrom != NULL);
++
++ if (cdrom->cam)
++ cam_close_device(cdrom->cam);
++
++ close(cdrom->fd);
++
++ g_free(cdrom);
++}
+--- /dev/null 2008-02-03 13:11:45.000000000 -0500
++++ src/cam/freebsd_dvd_rw_utils.c 2008-02-03 13:30:36.000000000 -0500
+@@ -0,0 +1,1075 @@
++/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
++ *
++ * This is part of dvd+rw-tools by Andy Polyakov <appro@fy.chalmers.se>
++ *
++ * Use-it-on-your-own-risk, GPL bless...
++ *
++ * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
++*/
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <sys/types.h>
++
++#include <glib.h>
++
++#include "freebsd_dvd_rw_utils.h"
++
++typedef enum {
++ NONE = BRASERO_CDROM_DIRECTION_NONE,
++ READ = BRASERO_CDROM_DIRECTION_IN,
++ WRITE = BRASERO_CDROM_DIRECTION_OUT
++} Direction;
++
++typedef struct ScsiCommand ScsiCommand;
++
++struct ScsiCommand {
++ BRASEROCDROM *cdrom;
++ char ccb[16];
++ int len;
++};
++
++static ScsiCommand *
++scsi_command_new_from_cdrom (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++
++ cmd = g_new0 (ScsiCommand, 1);
++ cmd->cdrom = cdrom;
++
++ return cmd;
++}
++
++static void
++scsi_command_free (ScsiCommand * cmd)
++{
++ free (cmd);
++}
++
++static void
++scsi_command_init (ScsiCommand * cmd, size_t i, int arg)
++{
++ cmd->ccb[i] = arg;
++ if (i == 0 || i >= cmd->len)
++ cmd->len = i + 1;
++}
++
++static int
++scsi_command_transport (ScsiCommand * cmd, Direction dir, void *buf,
++ size_t sz)
++{
++ if (brasero_cdrom_send_ccb(cmd->cdrom, cmd->ccb, cmd->len, dir, buf, sz, NULL))
++ return 0;
++ else
++ return -1;
++}
++
++int
++brasero_cdrom_get_dvd_r_rw_profile (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ unsigned char page[20];
++ unsigned char *list;
++ int i, len;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x46);
++ scsi_command_init (cmd, 1, 2);
++ scsi_command_init (cmd, 8, 8);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, page, 8)) {
++ /* GET CONFIGURATION failed */
++ scsi_command_free (cmd);
++ return -1;
++ }
++
++ /* See if it's 2 gen drive by checking if DVD+R profile is an option */
++ len = 4 + (page[0] << 24 | page[1] << 16 | page[2] << 8 | page[3]);
++ if (len > 264) {
++ scsi_command_free (cmd);
++ /* insane profile list length */
++ return -1;
++ }
++
++ list = g_new (unsigned char, len);
++
++ scsi_command_init (cmd, 0, 0x46);
++ scsi_command_init (cmd, 1, 2);
++ scsi_command_init (cmd, 7, len >> 8);
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, list, len)) {
++ /* GET CONFIGURATION failed */
++ scsi_command_free (cmd);
++ free (list);
++ return -1;
++ }
++
++ for (i = 12; i < list[11]; i += 4) {
++ int profile = (list[i] << 8 | list[i + 1]);
++ /* 0x13: DVD-RW Restricted Overwrite
++ * 0x14: DVD-RW Sequential
++ * 0x1B: DVD+R
++ * 0x1A: DVD+RW
++ * 0x2A: DVD+RW DL
++ * 0x2B: DVD+R DL
++ * 0x40: BD-ROM
++ * 0x41: BD-R SRM
++ * 0x42: BD-R RRM
++ * 0x43: BD-RE
++ * 0x50: HD DVD-ROM
++ * 0x51: HD DVD-R
++ * 0x52: HD DVD-Rewritable
++ */
++
++ switch (profile) {
++ case 0x13:
++ case 0x14:
++ retval |= DRIVE_CDROM_CAPS_DVDRW;
++ break;
++ case 0x1B:
++ retval |= DRIVE_CDROM_CAPS_DVDPLUSR;
++ break;
++ case 0x1A:
++ retval |= DRIVE_CDROM_CAPS_DVDPLUSRW;
++ break;
++ case 0x2A:
++ retval |= DRIVE_CDROM_CAPS_DVDPLUSRWDL;
++ break;
++ case 0x2B:
++ retval |= DRIVE_CDROM_CAPS_DVDPLUSRDL;
++ break;
++ case 0x40:
++ retval |= DRIVE_CDROM_CAPS_BDROM;
++ break;
++ case 0x41:
++ case 0x42:
++ retval |= DRIVE_CDROM_CAPS_BDR;
++ break;
++ case 0x43:
++ retval |= DRIVE_CDROM_CAPS_BDRE;
++ break;
++ case 0x50:
++ retval |= DRIVE_CDROM_CAPS_HDDVDROM;
++ break;
++ case 0x51:
++ retval |= DRIVE_CDROM_CAPS_HDDVDR;
++ break;
++ case 0x52:
++ retval |= DRIVE_CDROM_CAPS_HDDVDRW;
++ break;
++ default:
++ break;
++ }
++ }
++
++ scsi_command_free (cmd);
++ free (list);
++
++ return retval;
++
++}
++
++static unsigned char *
++pull_page2a_from_cdrom (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++ unsigned char header[12], *page2A;
++ unsigned int len, bdlen;
++
++ g_return_val_if_fail (cdrom != NULL, NULL);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x5A); /* MODE SENSE */
++ scsi_command_init (cmd, 1, 0x08); /* Disable Block Descriptors */
++ scsi_command_init (cmd, 2, 0x2A); /* Capabilities and Mechanical Status */
++ scsi_command_init (cmd, 8, sizeof (header)); /* header only to start with */
++ scsi_command_init (cmd, 9, 0);
++
++ if (scsi_command_transport (cmd, READ, header, sizeof (header))) {
++ /* MODE SENSE failed */
++ scsi_command_free (cmd);
++ return NULL;
++ }
++
++ len = (header[0] << 8 | header[1]) + 2;
++ bdlen = header[6] << 8 | header[7];
++
++ /* should never happen as we set "DBD" above */
++ if (bdlen) {
++ if (len < (8 + bdlen + 30)) {
++ /* LUN impossible to bear with */
++ scsi_command_free (cmd);
++ return NULL;
++ }
++ } else if (len < (8 + 2 + (unsigned int) header[9])) {
++ /* SANYO does this. */
++ len = 8 + 2 + header[9];
++ }
++
++ page2A = g_new (unsigned char, len);
++ if (page2A == NULL) {
++ /* ENOMEM */
++ scsi_command_free (cmd);
++ return NULL;
++ }
++
++ scsi_command_init (cmd, 0, 0x5A); /* MODE SENSE */
++ scsi_command_init (cmd, 1, 0x08); /* Disable Block Descriptors */
++ scsi_command_init (cmd, 2, 0x2A); /* Capabilities and Mechanical Status */
++ scsi_command_init (cmd, 7, len >> 8);
++ scsi_command_init (cmd, 8, len); /* Real length */
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, page2A, len)) {
++ /* MODE SENSE failed */
++ scsi_command_free (cmd);
++ free (page2A);
++ return NULL;
++ }
++
++ scsi_command_free (cmd);
++
++ len -= 2;
++ /* paranoia */
++ if (len < ((unsigned int) page2A[0] << 8 | page2A[1])) {
++ page2A[0] = len >> 8;
++ page2A[1] = len;
++ }
++
++ return page2A;
++}
++
++static int
++int_compare (const void *a, const void *b)
++{
++ /* descending order */
++ return *((int *) b) - *((int *) a);
++}
++
++/* gets the list of supported write speeds. in the event
++ * that anything goes wrong, returns NULL.
++ */
++static char *
++get_write_speeds (const unsigned char *p, int length, int max_speed)
++{
++ char *result, *str;
++ int nr_records;
++ int *tmpspeeds;
++ int i, j;
++
++ result = NULL;
++
++ /* paranoia */
++ if (length < 32)
++ return NULL;
++
++ nr_records = p[30] << 8 | p[31];
++
++ /* paranoia */
++ if (length < 32 + 4 * nr_records)
++ return NULL;
++
++ tmpspeeds = g_new (int, nr_records);
++
++ for (i = 0; i < nr_records; i++)
++ {
++ tmpspeeds[i] = p[4*i + 34] << 8 | p[4*i + 35];
++
++ /* i'm not sure how likely this is to show up, but it's
++ * definitely wrong. if we see it, abort.
++ */
++ if (tmpspeeds[i] == 0)
++ goto free_tmpspeeds;
++ }
++
++ /* sort */
++ qsort (tmpspeeds, nr_records, sizeof (int), int_compare);
++
++ /* uniq */
++ for (i = j = 0; i < nr_records; i++)
++ {
++ tmpspeeds[j] = tmpspeeds[i];
++
++ /* make sure we don't look past the end of the array */
++ if (i >= (nr_records - 1) || tmpspeeds[i+1] != tmpspeeds[i])
++ j++;
++ }
++
++ /* j is now the number of unique entries in the array */
++ if (j == 0)
++ /* no entries? this isn't right. */
++ goto free_tmpspeeds;
++
++ /* sanity check: the first item in the descending order
++ * list ought to be the highest speed as detected through
++ * other means
++ */
++ if (tmpspeeds[0] != max_speed)
++ /* sanity check failed. */
++ goto free_tmpspeeds;
++
++ /* our values are 16-bit. 8 bytes per value
++ * is more than enough including space for
++ * ',' and '\0'. we know j is not zero.
++ */
++ result = str = g_new (char, 8 * j);
++
++ for (i = 0; i < j; i++)
++ {
++ if (i > 0)
++ *(str++) = ',';
++
++ str += sprintf (str, "%d", tmpspeeds[i]);
++ }
++
++free_tmpspeeds:
++ free (tmpspeeds);
++
++ return result;
++}
++
++int
++brasero_cdrom_get_read_write_speed (BRASEROCDROM *cdrom, int *read_speed, int *write_speed, char **write_speeds)
++{
++ unsigned char *page2A;
++ int len, hlen;
++ unsigned char *p;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ *read_speed = 0;
++ *write_speed = 0;
++ *write_speeds = NULL;
++
++ page2A = pull_page2a_from_cdrom (cdrom);
++ if (page2A == NULL) {
++ printf ("Failed to get Page 2A\n");
++ /* Failed to get Page 2A */
++ return -1;
++ }
++
++ len = (page2A[0] << 8 | page2A[1]) + 2;
++ hlen = 8 + (page2A[6] << 8 | page2A[7]);
++ p = page2A + hlen;
++
++ /* Values guessed from the cd_mode_page_2A struct
++ * in cdrecord's libscg/scg/scsireg.h */
++ if (len < (hlen + 30) || p[1] < (30 - 2)) {
++ /* no MMC-3 "Current Write Speed" present,
++ * try to use the MMC-2 one */
++ if (len < (hlen + 20) || p[1] < (20 - 2))
++ *write_speed = 0;
++ else
++ *write_speed = p[18] << 8 | p[19];
++ } else {
++ *write_speed = p[28] << 8 | p[29];
++ }
++
++ if (len >= hlen+9)
++ *read_speed = p[8] << 8 | p[9];
++ else
++ *read_speed = 0;
++
++ *write_speeds = get_write_speeds (p, len, *write_speed);
++
++ free (page2A);
++
++ return 0;
++}
++
++
++static int
++get_disc_capacity_cd (BRASEROCDROM *cdrom, guint64 *size)
++{
++ ScsiCommand *cmd;
++ int retval;
++ guint64 block_size;
++ guint64 num_blocks;
++ unsigned char header [8];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ retval = -1;
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++ scsi_command_init (cmd, 0, 0x25);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 8)) {
++ /* READ CDROM CAPACITY failed */
++ goto done;
++ }
++
++ num_blocks = (header [0] << 24) | (header [1] << 16) | (header [2] << 8) | header [3];
++ num_blocks++;
++ block_size = header [4] << 24 | header [5] << 16 | header [6] << 8 | header [7];
++
++ if (size) {
++ *size = num_blocks * block_size;
++ }
++ retval = 0;
++
++ done:
++ scsi_command_free (cmd);
++
++ return retval;
++}
++
++static int
++get_disc_capacity_cdr (BRASEROCDROM *cdrom, guint64 *size)
++{
++ ScsiCommand *cmd;
++ int retval;
++ guint64 secs;
++ unsigned char toc [8];
++ unsigned char *atip;
++ int len;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ retval = -1;
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++ /* READ_TOC */
++ scsi_command_init (cmd, 0, 0x43);
++ /* FMT_ATIP */
++ scsi_command_init (cmd, 2, 4 & 0x0F);
++ scsi_command_init (cmd, 6, 0);
++ scsi_command_init (cmd, 8, 4);
++ scsi_command_init (cmd, 9, 0);
++
++ if (scsi_command_transport (cmd, READ, toc, 4)) {
++ /* READ TOC failed */
++ goto done;
++ }
++
++ len = 2 + (toc [0] << 8 | toc [1]);
++
++ atip = g_new (unsigned char, len);
++
++ scsi_command_init (cmd, 0, 0x43);
++ scsi_command_init (cmd, 2, 4 & 0x0F);
++ scsi_command_init (cmd, 6, 0);
++ scsi_command_init (cmd, 7, len >> 8);
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++
++ if (scsi_command_transport (cmd, READ, atip, len)) {
++ /* READ TOC failed */
++ free (atip);
++ goto done;
++ }
++
++ secs = atip [12] * 60 + atip [13] + (atip [14] / 75 + 1);
++
++ if (size) {
++ *size = (1 + secs * 7 / 48) * 1024 * 1024;
++ }
++ retval = 0;
++
++ free (atip);
++ done:
++ scsi_command_free (cmd);
++
++ return retval;
++}
++
++static int
++get_disc_capacity_dvdr_from_type (BRASEROCDROM *cdrom, int type, guint64 *size)
++{
++ ScsiCommand *cmd;
++ unsigned char formats [260];
++ unsigned char buf [32];
++ guint64 blocks;
++ guint64 nwa;
++ int i;
++ int len;
++ int obligatory;
++ int retval;
++ int next_track;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ retval = -1;
++ blocks = 0;
++ next_track = 1;
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ retry:
++ if (type == 0x1A || type == 0x14 || type == 0x13 || type == 0x12) {
++
++ /* READ FORMAT CAPACITIES */
++ scsi_command_init (cmd, 0, 0x23);
++ scsi_command_init (cmd, 8, 12);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, formats, 12)) {
++ /* READ FORMAT CAPACITIES failed */
++ goto done;
++ }
++
++ len = formats [3];
++ if (len & 7 || len < 16) {
++ /* Length isn't sane */
++ goto done;
++ }
++
++ scsi_command_init (cmd, 0, 0x23);
++ scsi_command_init (cmd, 7, (4 + len) >> 8);
++ scsi_command_init (cmd, 8, (4 + len) & 0xFF);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, formats, 4 + len)) {
++ /* READ FORMAT CAPACITIES failed */
++ goto done;
++ }
++
++ if (len != formats [3]) {
++ /* Parameter length inconsistency */
++ goto done;
++ }
++ }
++
++ obligatory = 0x00;
++
++ switch (type) {
++ case 0x1A: /* DVD+RW */
++ obligatory = 0x26;
++ case 0x13: /* DVD-RW Restricted Overwrite */
++ case 0x14: /* DVD-RW Sequential */
++ for (i = 8, len = formats [3]; i < len; i += 8) {
++ if ((formats [4 + i + 4] >> 2) == obligatory) {
++ break;
++ }
++ }
++
++ if (i == len) {
++ /* Can't find obligatory format descriptor */
++ goto done;
++ }
++
++ blocks = formats [4 + i + 0] << 24;
++ blocks |= formats [4 + i + 1] << 16;
++ blocks |= formats [4 + i + 2] << 8;
++ blocks |= formats [4 + i + 3];
++ nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
++ if (nwa > 2048) {
++ blocks *= nwa / 2048;
++ } else if (nwa < 2048) {
++ blocks /= 2048 / nwa;
++ }
++
++ retval = 0;
++ break;
++
++ case 0x12: /* DVD-RAM */
++
++ blocks = formats [4 + 0] << 24;
++ blocks |= formats [4 + 1] << 16;
++ blocks |= formats [4 + 2] << 8;
++ blocks |= formats [4 + 3];
++ nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
++ if (nwa > 2048) {
++ blocks *= nwa / 2048;
++ } else if (nwa < 2048) {
++ blocks /= 2048 / nwa;
++ }
++
++ retval = 0;
++ break;
++
++ case 0x11: /* DVD-R */
++ case 0x1B: /* DVD+R */
++ case 0x2B: /* DVD+R Double Layer */
++ case 0x41: /* BD-R SRM */
++
++ /* READ TRACK INFORMATION */
++ scsi_command_init (cmd, 0, 0x52);
++ scsi_command_init (cmd, 1, 1);
++ scsi_command_init (cmd, 4, next_track >> 8);
++ scsi_command_init (cmd, 5, next_track & 0xFF);
++ scsi_command_init (cmd, 8, sizeof (buf));
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, buf, sizeof (buf))) {
++ /* READ TRACK INFORMATION failed */
++ if (next_track > 0) {
++ goto done;
++ } else {
++ next_track = 1;
++ goto retry;
++ }
++ }
++
++ blocks = buf [24] << 24;
++ blocks |= buf [25] << 16;
++ blocks |= buf [26] << 8;
++ blocks |= buf [27];
++
++ retval = 0;
++ break;
++ case 0x43: /* DB-RE */
++ /* Pull the formatted capacity */
++ blocks = formats [4 + 0] << 24;
++ blocks |= formats [4 + 1] << 16;
++ blocks |= formats [4 + 2] << 8;
++ blocks |= formats [4 + 3];
++ break;
++ default:
++ blocks = 0;
++ break;
++ }
++
++ done:
++ scsi_command_free (cmd);
++
++ if (size) {
++ *size = blocks * 2048;
++ }
++
++ return retval;
++}
++
++int
++brasero_cdrom_get_disc_capacity_for_type (BRASEROCDROM *cdrom, int type, guint64 *size)
++{
++ int retval;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ retval = -1;
++
++ switch (type) {
++ case 0x8:
++ retval = get_disc_capacity_cd (cdrom, size);
++ break;
++ case 0x9:
++ case 0xa:
++ retval = get_disc_capacity_cdr (cdrom, size);
++ break;
++ case 0x10:
++ retval = get_disc_capacity_cd (cdrom, size);
++ break;
++ case 0x11:
++ case 0x13:
++ case 0x14:
++ case 0x1B:
++ case 0x2B:
++ case 0x1A:
++ case 0x12:
++ case 0x41:
++ case 0x43:
++ retval = get_disc_capacity_dvdr_from_type (cdrom, type, size);
++ break;
++ default:
++ retval = -1;
++ }
++
++ return retval;
++}
++
++int
++brasero_cdrom_get_disc_type (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++ int retval = -1;
++ unsigned char header[8];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x46);
++ scsi_command_init (cmd, 1, 1);
++ scsi_command_init (cmd, 8, 8);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 8)) {
++ /* GET CONFIGURATION failed */
++ scsi_command_free (cmd);
++ return -1;
++ }
++
++ retval = (header[6]<<8)|(header[7]);
++
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_get_configuration_feature (BRASEROCDROM *cdrom,
++ int feature,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ unsigned char header[8];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x46);
++ scsi_command_init (cmd, 1, 2);
++ scsi_command_init (cmd, 2, feature >> 8);
++ scsi_command_init (cmd, 3, feature);
++ scsi_command_init (cmd, 8, 8);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 8)) {
++ scsi_command_free (cmd);
++ return -1;
++ }
++
++ len = 4 + (header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3]);
++ if (len > 264) {
++ scsi_command_free (cmd);
++ return -1;
++ }
++
++ *buf = g_new (unsigned char, len);
++
++ scsi_command_init (cmd, 0, 0x46);
++ scsi_command_init (cmd, 1, 2);
++ scsi_command_init (cmd, 2, feature >> 8);
++ scsi_command_init (cmd, 3, feature);
++ scsi_command_init (cmd, 7, len >> 8);
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, *buf, len)) {
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++
++ return retval;
++}
++
++int
++brasero_cdrom_read_disc_information_std (BRASEROCDROM *cdrom,
++ unsigned char *buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ /* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
++ scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
++ scsi_command_init (cmd, 8, 32);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, buf, 32)) {
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_read_track_info (BRASEROCDROM *cdrom,
++ int track_num,
++ unsigned char *buf,
++ int size)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x52);
++ scsi_command_init (cmd, 1, 1);
++ scsi_command_init (cmd, 4, track_num >> 8);
++ scsi_command_init (cmd, 5, track_num & 0xFF);
++ scsi_command_init (cmd, 8, size);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, buf, size)) {
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_read_toc_formatted (BRASEROCDROM *cdrom,
++ int track_num,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ unsigned char header[4];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x43);
++ scsi_command_init (cmd, 2, 0);
++ scsi_command_init (cmd, 6, track_num);
++ scsi_command_init (cmd, 8, 4);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 4)) {
++ scsi_command_free (cmd);
++ *buf = NULL;
++ return -1;
++ }
++
++ len = (header[0] << 8 | header[1]) + 2;
++
++ *buf = g_malloc0 (len);
++
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, *buf, len)) {
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_read_toc_raw (BRASEROCDROM *cdrom,
++ int track_num,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ unsigned char header[4];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x43);
++ scsi_command_init (cmd, 2, 2);
++ scsi_command_init (cmd, 6, track_num);
++ scsi_command_init (cmd, 8, 4);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 4)) {
++ scsi_command_free (cmd);
++ *buf = NULL;
++ return -1;
++ }
++
++ len = (header[0] << 8 | header[1]) + 2;
++
++ *buf = g_malloc0 (len);
++
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, *buf, len)) {
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_read_atip (BRASEROCDROM *cdrom,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ unsigned char header[4];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x43);
++ scsi_command_init (cmd, 2, 4);
++ scsi_command_init (cmd, 6, 0);
++ scsi_command_init (cmd, 8, 4);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 4)) {
++ scsi_command_free (cmd);
++ *buf = NULL;
++ return -1;
++ }
++
++ len = (header[0] << 8 | header[1]) + 2;
++
++ *buf = g_malloc0 (len);
++
++ scsi_command_init (cmd, 8, len);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, *buf, len)) {
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_read_format_capacities (BRASEROCDROM *cdrom,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ unsigned char header[12];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0x23);
++ scsi_command_init (cmd, 8, 12);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 12)) {
++ /* READ FORMAT CAPACITIES failed */
++ return -1;
++ }
++
++ len = header [3];
++ if (len & 7 || len < 16) {
++ /* Length isn't sane */
++ return -1;
++ }
++
++ *buf = g_new (unsigned char, len + 4);
++
++ scsi_command_init (cmd, 0, 0x23);
++ scsi_command_init (cmd, 7, (4 + len) >> 8);
++ scsi_command_init (cmd, 8, (4 + len) & 0xFF);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, *buf, 4 + len)) {
++ /* READ FORMAT CAPACITIES failed */
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ return retval;
++}
++
++int
++brasero_cdrom_get_performance_wrt_spd_desc (BRASEROCDROM *cdrom,
++ unsigned char **buf)
++{
++ ScsiCommand *cmd;
++ int retval = 0;
++ int len;
++ int desc_num;
++ unsigned char header[8];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++ g_return_val_if_fail (buf != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ scsi_command_init (cmd, 0, 0xac);
++ scsi_command_init (cmd, 8, 0);
++ scsi_command_init (cmd, 9, 0);
++ scsi_command_init (cmd, 10, 3);
++ scsi_command_init (cmd, 11, 0);
++ if (scsi_command_transport (cmd, READ, header, 8)) {
++ scsi_command_free (cmd);
++ *buf = NULL;
++ return -1;
++ }
++
++ len = (header[0] << 24 | header[1] << 16 | header[2] << 8 | header[3]) + 4;
++ if (len > 2048) {
++ len = 2048;
++ }
++
++ desc_num = (len - 8) / 12;
++
++ *buf = g_malloc0 (len);
++
++ scsi_command_init (cmd, 8, desc_num >> 8);
++ scsi_command_init (cmd, 9, desc_num);
++ scsi_command_init (cmd, 11, 0);
++ if (scsi_command_transport (cmd, READ, *buf, len)) {
++ g_free (*buf);
++ *buf = NULL;
++ retval = -1;
++ }
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_disc_is_appendable (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++ int retval = -1;
++ unsigned char header[32];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ /* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
++ scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
++ scsi_command_init (cmd, 8, 32);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 32)) {
++ /* READ_DISC_INFORMATION failed */
++ scsi_command_free (cmd);
++ return 0;
++ }
++
++ retval = ((header[2]&0x03) == 0x01);
++
++ scsi_command_free (cmd);
++ return retval;
++}
++
++int
++brasero_cdrom_disc_is_rewritable (BRASEROCDROM *cdrom)
++{
++ ScsiCommand *cmd;
++ int retval = -1;
++ unsigned char header[32];
++
++ g_return_val_if_fail (cdrom != NULL, -1);
++
++ cmd = scsi_command_new_from_cdrom (cdrom);
++
++ /* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
++ scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
++ scsi_command_init (cmd, 8, 32);
++ scsi_command_init (cmd, 9, 0);
++ if (scsi_command_transport (cmd, READ, header, 32)) {
++ /* READ_DISC_INFORMATION failed */
++ scsi_command_free (cmd);
++ return 0;
++ }
++
++ retval = ((header[2]&0x10) != 0);
++
++ scsi_command_free (cmd);
++ return retval;
++}
diff --git a/sysutils/brasero/files/patch-src_plugins_cdrtools_burn-cdrecord.c b/sysutils/brasero/files/patch-src_plugins_cdrtools_burn-cdrecord.c
new file mode 100644
index 000000000..583807240
--- /dev/null
+++ b/sysutils/brasero/files/patch-src_plugins_cdrtools_burn-cdrecord.c
@@ -0,0 +1,11 @@
+--- src/plugins/cdrtools/burn-cdrecord.c.orig 2008-01-02 14:59:18.000000000 -0500
++++ src/plugins/cdrtools/burn-cdrecord.c 2008-01-02 14:59:27.000000000 -0500
+@@ -899,7 +899,7 @@ brasero_cdrecord_set_argv (BraseroProces
+ g_ptr_array_add (argv, g_strdup ("cdrecord"));
+ g_ptr_array_add (argv, g_strdup ("-v"));
+
+- brasero_job_get_device (BRASERO_JOB (cdrecord), &device);
++ brasero_job_get_cdrecord_device (BRASERO_JOB (cdrecord), &device);
+ dev_str = g_strdup_printf ("dev=%s", device);
+ g_ptr_array_add (argv, dev_str);
+ g_free (device);
diff --git a/sysutils/brasero/pkg-descr b/sysutils/brasero/pkg-descr
new file mode 100644
index 000000000..2e6f14b59
--- /dev/null
+++ b/sysutils/brasero/pkg-descr
@@ -0,0 +1,23 @@
+CD/DVD mastering tool for the gnome desktop. It has been designed to be
+simple and easy to use.
+
+Features:
+Data CD/DVD:
+- supports edition of discs contents
+- can burn data CD/DVD on the fly
+- supports multisession
+- supports joliet extension
+- can write the image to the hard drive
+Audio CD:
+- write CD-TEXT information (automatically found thanks to gstreamer)
+- supports the edition of CD-TEXT information
+- can burn audio CD on the fly
+- can use all audio files handled by Gstreamer local installation
+- can search for audio files inside dropped folders
+CD/DVD copy:
+- can copy a CD/DVD to the hard drive
+- can copy DVD and CD on the fly
+- supports single-session data DVD
+- supports any kind of CD
+
+WWW: http://perso.wanadoo.fr/bonfire/
diff --git a/sysutils/brasero/pkg-plist b/sysutils/brasero/pkg-plist
new file mode 100644
index 000000000..acbe2314b
--- /dev/null
+++ b/sysutils/brasero/pkg-plist
@@ -0,0 +1,245 @@
+bin/brasero
+lib/brasero/plugins/libbrasero-cdrdao.la
+lib/brasero/plugins/libbrasero-cdrdao.so
+lib/brasero/plugins/libbrasero-cdrecord.la
+lib/brasero/plugins/libbrasero-cdrecord.so
+lib/brasero/plugins/libbrasero-dvdcss.la
+lib/brasero/plugins/libbrasero-dvdcss.so
+lib/brasero/plugins/libbrasero-dvdrwformat.la
+lib/brasero/plugins/libbrasero-dvdrwformat.so
+lib/brasero/plugins/libbrasero-genisoimage.la
+lib/brasero/plugins/libbrasero-genisoimage.so
+lib/brasero/plugins/libbrasero-growisofs.la
+lib/brasero/plugins/libbrasero-growisofs.so
+lib/brasero/plugins/libbrasero-local-track.la
+lib/brasero/plugins/libbrasero-local-track.so
+lib/brasero/plugins/libbrasero-md5sum-file.la
+lib/brasero/plugins/libbrasero-md5sum-file.so
+lib/brasero/plugins/libbrasero-md5sum.la
+lib/brasero/plugins/libbrasero-md5sum.so
+lib/brasero/plugins/libbrasero-mkisofs.la
+lib/brasero/plugins/libbrasero-mkisofs.so
+lib/brasero/plugins/libbrasero-readcd.la
+lib/brasero/plugins/libbrasero-readcd.so
+lib/brasero/plugins/libbrasero-readom.la
+lib/brasero/plugins/libbrasero-readom.so
+lib/brasero/plugins/libbrasero-toc2cue.la
+lib/brasero/plugins/libbrasero-toc2cue.so
+lib/brasero/plugins/libbrasero-transcode.la
+lib/brasero/plugins/libbrasero-transcode.so
+lib/brasero/plugins/libbrasero-wodim.la
+lib/brasero/plugins/libbrasero-wodim.so
+share/applications/brasero.desktop
+%%DATADIR%%/icons/hicolor/16x16/actions/insert-pause.png
+%%DATADIR%%/icons/hicolor/16x16/actions/iso-image-burn.png
+%%DATADIR%%/icons/hicolor/16x16/actions/iso-image-new.png
+%%DATADIR%%/icons/hicolor/16x16/actions/media-optical-audio-new.png
+%%DATADIR%%/icons/hicolor/16x16/actions/media-optical-blank.png
+%%DATADIR%%/icons/hicolor/16x16/actions/media-optical-burn.png
+%%DATADIR%%/icons/hicolor/16x16/actions/media-optical-copy.png
+%%DATADIR%%/icons/hicolor/16x16/actions/media-optical-data-new.png
+%%DATADIR%%/icons/hicolor/16x16/actions/transform-crop-and-resize.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-00.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-05.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-10.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-100.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-15.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-20.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-25.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-30.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-35.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-40.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-45.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-50.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-55.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-60.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-65.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-70.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-75.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-80.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-85.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-90.png
+%%DATADIR%%/icons/hicolor/16x16/status/brasero-disc-95.png
+%%DATADIR%%/icons/hicolor/22x22/actions/insert-pause.png
+%%DATADIR%%/icons/hicolor/22x22/actions/iso-image-burn.png
+%%DATADIR%%/icons/hicolor/22x22/actions/iso-image-new.png
+%%DATADIR%%/icons/hicolor/22x22/actions/media-optical-audio-new.png
+%%DATADIR%%/icons/hicolor/22x22/actions/media-optical-blank.png
+%%DATADIR%%/icons/hicolor/22x22/actions/media-optical-burn.png
+%%DATADIR%%/icons/hicolor/22x22/actions/media-optical-copy.png
+%%DATADIR%%/icons/hicolor/22x22/actions/media-optical-data-new.png
+%%DATADIR%%/icons/hicolor/22x22/actions/transform-crop-and-resize.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-00.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-05.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-10.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-100.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-15.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-20.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-25.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-30.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-35.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-40.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-45.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-50.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-55.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-60.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-65.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-70.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-75.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-80.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-85.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-90.png
+%%DATADIR%%/icons/hicolor/22x22/status/brasero-disc-95.png
+%%DATADIR%%/icons/hicolor/24x24/actions/insert-pause.png
+%%DATADIR%%/icons/hicolor/24x24/actions/iso-image-burn.png
+%%DATADIR%%/icons/hicolor/24x24/actions/iso-image-new.png
+%%DATADIR%%/icons/hicolor/24x24/actions/media-optical-audio-new.png
+%%DATADIR%%/icons/hicolor/24x24/actions/media-optical-blank.png
+%%DATADIR%%/icons/hicolor/24x24/actions/media-optical-burn.png
+%%DATADIR%%/icons/hicolor/24x24/actions/media-optical-copy.png
+%%DATADIR%%/icons/hicolor/24x24/actions/media-optical-data-new.png
+%%DATADIR%%/icons/hicolor/24x24/actions/transform-crop-and-resize.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-00.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-05.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-10.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-100.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-15.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-20.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-25.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-30.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-35.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-40.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-45.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-50.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-55.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-60.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-65.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-70.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-75.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-80.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-85.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-90.png
+%%DATADIR%%/icons/hicolor/24x24/status/brasero-disc-95.png
+%%DATADIR%%/icons/hicolor/32x32/actions/insert-pause.png
+%%DATADIR%%/icons/hicolor/32x32/actions/iso-image-burn.png
+%%DATADIR%%/icons/hicolor/32x32/actions/iso-image-new.png
+%%DATADIR%%/icons/hicolor/32x32/actions/media-optical-audio-new.png
+%%DATADIR%%/icons/hicolor/32x32/actions/media-optical-blank.png
+%%DATADIR%%/icons/hicolor/32x32/actions/media-optical-burn.png
+%%DATADIR%%/icons/hicolor/32x32/actions/media-optical-copy.png
+%%DATADIR%%/icons/hicolor/32x32/actions/media-optical-data-new.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-00.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-05.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-10.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-100.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-15.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-20.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-25.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-30.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-35.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-40.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-45.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-50.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-55.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-60.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-65.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-70.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-75.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-80.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-85.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-90.png
+%%DATADIR%%/icons/hicolor/32x32/status/brasero-disc-95.png
+%%DATADIR%%/icons/hicolor/scalable/actions/insert-pause.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/iso-image-burn.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/iso-image-new.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/media-optical-audio-new.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/media-optical-blank.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/media-optical-burn.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/media-optical-copy.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/media-optical-data-new.svg
+%%DATADIR%%/icons/hicolor/scalable/actions/transform-crop-and-resize.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-00.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-05.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-10.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-100.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-15.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-20.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-25.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-30.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-35.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-40.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-45.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-50.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-55.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-60.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-65.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-70.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-75.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-80.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-85.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-90.svg
+%%DATADIR%%/icons/hicolor/scalable/status/brasero-disc-95.svg
+%%DATADIR%%/logo.png
+share/icons/hicolor/16x16/apps/brasero.png
+share/icons/hicolor/22x22/apps/brasero.png
+share/icons/hicolor/24x24/apps/brasero.png
+share/icons/hicolor/32x32/apps/brasero.png
+share/icons/hicolor/48x48/apps/brasero.png
+share/icons/hicolor/scalable/apps/brasero.svg
+share/locale/ar/LC_MESSAGES/brasero.mo
+share/locale/ca/LC_MESSAGES/brasero.mo
+share/locale/cs/LC_MESSAGES/brasero.mo
+share/locale/de/LC_MESSAGES/brasero.mo
+share/locale/dz/LC_MESSAGES/brasero.mo
+share/locale/en_GB/LC_MESSAGES/brasero.mo
+share/locale/es/LC_MESSAGES/brasero.mo
+share/locale/fi/LC_MESSAGES/brasero.mo
+share/locale/fr/LC_MESSAGES/brasero.mo
+share/locale/gl/LC_MESSAGES/brasero.mo
+share/locale/he/LC_MESSAGES/brasero.mo
+share/locale/hu/LC_MESSAGES/brasero.mo
+share/locale/it/LC_MESSAGES/brasero.mo
+share/locale/ja/LC_MESSAGES/brasero.mo
+share/locale/lt/LC_MESSAGES/brasero.mo
+share/locale/mk/LC_MESSAGES/brasero.mo
+share/locale/nb/LC_MESSAGES/brasero.mo
+share/locale/oc/LC_MESSAGES/brasero.mo
+share/locale/pa/LC_MESSAGES/brasero.mo
+share/locale/pl/LC_MESSAGES/brasero.mo
+share/locale/pt/LC_MESSAGES/brasero.mo
+share/locale/pt_BR/LC_MESSAGES/brasero.mo
+share/locale/ru/LC_MESSAGES/brasero.mo
+share/locale/sl/LC_MESSAGES/brasero.mo
+share/locale/sr/LC_MESSAGES/brasero.mo
+share/locale/sr@Latn/LC_MESSAGES/brasero.mo
+share/locale/sv/LC_MESSAGES/brasero.mo
+share/mime/packages/brasero.xml
+@dirrm %%DATADIR%%/icons/hicolor/16x16/status
+@dirrm %%DATADIR%%/icons/hicolor/16x16/actions
+@dirrm %%DATADIR%%/icons/hicolor/16x16
+@dirrm %%DATADIR%%/icons/hicolor/22x22/status
+@dirrm %%DATADIR%%/icons/hicolor/22x22/actions
+@dirrm %%DATADIR%%/icons/hicolor/22x22
+@dirrm %%DATADIR%%/icons/hicolor/24x24/status
+@dirrm %%DATADIR%%/icons/hicolor/24x24/actions
+@dirrm %%DATADIR%%/icons/hicolor/24x24
+@dirrm %%DATADIR%%/icons/hicolor/32x32/status
+@dirrm %%DATADIR%%/icons/hicolor/32x32/actions
+@dirrm %%DATADIR%%/icons/hicolor/32x32
+@dirrm %%DATADIR%%/icons/hicolor/scalable/status
+@dirrm %%DATADIR%%/icons/hicolor/scalable/actions
+@dirrm %%DATADIR%%/icons/hicolor/scalable
+@dirrm %%DATADIR%%/icons/hicolor
+@dirrm %%DATADIR%%/icons
+@dirrm %%DATADIR%%
+@dirrmtry share/applications
+@dirrm lib/brasero/plugins
+@dirrm lib/brasero
+@exec %%LOCALBASE%%/bin/update-mime-database %D/share/mime
+@unexec %%LOCALBASE%%/bin/update-mime-database %D/share/mime
+@exec %%LOCALBASE%%/bin/update-desktop-database > /dev/null || /usr/bin/true
+@unexec %%LOCALBASE%%/bin/update-desktop-database > /dev/null || /usr/bin/true
+@dirrmtry share/locale/oc/LC_MESSAGES
+@dirrmtry share/locale/oc
+@dirrmtry share/locale/dz/LC_MESSAGES
+@dirrmtry share/locale/dz