diff options
author | marcus <marcus@df743ca5-7f9a-e211-a948-0013205c9059> | 2008-02-06 15:09:50 +0800 |
---|---|---|
committer | marcus <marcus@df743ca5-7f9a-e211-a948-0013205c9059> | 2008-02-06 15:09:50 +0800 |
commit | bf602796537561d1fa98ad9757dc499fc7e3248f (patch) | |
tree | ba6cc276aadd3c8ef506720f13c478ba6e24a155 /sysutils/brasero/files | |
parent | 19468d8b00c55abd34de0a57fbfad4d9e3ba5075 (diff) | |
download | marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar.gz marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar.bz2 marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar.lz marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar.xz marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.tar.zst marcuscom-ports-bf602796537561d1fa98ad9757dc499fc7e3248f.zip |
Sync with FreeBSD ports tree.
git-svn-id: svn://creme-brulee.marcuscom.com/ports/trunk@10361 df743ca5-7f9a-e211-a948-0013205c9059
Diffstat (limited to 'sysutils/brasero/files')
-rw-r--r-- | sysutils/brasero/files/patch-configure | 264 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_Makefile.in | 275 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_brasero-ncb.h | 12 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-job.c | 31 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-job.h | 12 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-medium-cam.c | 1928 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-medium-scsi.c | 2073 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_burn-medium.c | 2073 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_cam | 1361 | ||||
-rw-r--r-- | sysutils/brasero/files/patch-src_plugins_cdrtools_burn-cdrecord.c | 11 |
10 files changed, 8040 insertions, 0 deletions
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..7e8be77e7 --- /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.1 2008-02-06 07:09:50 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.1 2008-02-06 07:09:50 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); |